l3lab/ntp-mathlib huggingface dataset:
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    

Proof state:
case cons
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
hd1 : α × Bool
tl1 : List (α × Bool)
hd2 : α × Bool
tl2 : List (α × Bool)
htl : reduce tl1 = hd2 :: tl2
ih : Red tl1 (hd2 :: tl2)
⊢ Red (hd1 :: tl1)
    (List.rec [hd1] (fun head tail tail_ih => if hd1.1 = head.1 ∧ hd1.2 = !head.2 then tail else hd1 :: head :: tail)
      (hd2 :: tl2))

Next tactic:
case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          cases hd2
          cases h
          dsimp at *
          subst_vars
          apply Red.trans (Red.cons_cons ih)
          exact Red.Step.cons_not_rev.to_red
      · exact Red.cons_cons ih
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
hd1 : α × Bool
tl1 : List (α × Bool)
hd2 : α × Bool
tl2 : List (α × Bool)
htl : reduce tl1 = hd2 :: tl2
ih : Red tl1 (hd2 :: tl2)
⊢ Red (hd1 :: tl1)
    (List.rec [hd1] (fun head tail tail_ih => if hd1.1 = head.1 ∧ hd1.2 = !head.2 then tail else hd1 :: head :: tail)
      (hd2 :: tl2))

Next tactic:
case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          cases hd2
          cases h
          dsimp at *
          subst_vars
          apply Red.trans (Red.cons_cons ih)
          exact Red.Step.cons_not_rev.to_red
      · exact Red.cons_cons ih
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
hd1 : α × Bool
tl1 : List (α × Bool)
hd2 : α × Bool
tl2 : List (α × Bool)
htl : reduce tl1 = hd2 :: tl2
ih : Red tl1 (hd2 :: tl2)
⊢ Red (hd1 :: tl1)
    (List.rec [hd1] (fun head tail tail_ih => if hd1.1 = head.1 ∧ hd1.2 = !head.2 then tail else hd1 :: head :: tail)
      (hd2 :: tl2))

Next tactic:
dsimp only
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
hd1 : α × Bool
tl1 : List (α × Bool)
hd2 : α × Bool
tl2 : List (α × Bool)
htl : reduce tl1 = hd2 :: tl2
ih : Red tl1 (hd2 :: tl2)
⊢ Red (hd1 :: tl1) (if hd1.1 = hd2.1 ∧ hd1.2 = !hd2.2 then tl2 else hd1 :: hd2 :: tl2)

Next tactic:
split_ifs with h
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · 

Proof state:
case pos
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
hd1 : α × Bool
tl1 : List (α × Bool)
hd2 : α × Bool
tl2 : List (α × Bool)
htl : reduce tl1 = hd2 :: tl2
ih : Red tl1 (hd2 :: tl2)
h : hd1.1 = hd2.1 ∧ hd1.2 = !hd2.2
⊢ Red (hd1 :: tl1) tl2

Next tactic:
trans
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · trans
        · 

Proof state:
case pos
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
hd1 : α × Bool
tl1 : List (α × Bool)
hd2 : α × Bool
tl2 : List (α × Bool)
htl : reduce tl1 = hd2 :: tl2
ih : Red tl1 (hd2 :: tl2)
h : hd1.1 = hd2.1 ∧ hd1.2 = !hd2.2
⊢ Red (hd1 :: tl1) tl2

Next tactic:
cases hd1
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          

Proof state:
case pos.mk
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
tl1 : List (α × Bool)
hd2 : α × Bool
tl2 : List (α × Bool)
htl : reduce tl1 = hd2 :: tl2
ih : Red tl1 (hd2 :: tl2)
fst✝ : α
snd✝ : Bool
h : (fst✝, snd✝).1 = hd2.1 ∧ (fst✝, snd✝).2 = !hd2.2
⊢ Red ((fst✝, snd✝) :: tl1) tl2

Next tactic:
cases hd2
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          cases hd2
          

Proof state:
case pos.mk.mk
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
tl1 tl2 : List (α × Bool)
fst✝¹ : α
snd✝¹ : Bool
fst✝ : α
snd✝ : Bool
htl : reduce tl1 = (fst✝, snd✝) :: tl2
ih : Red tl1 ((fst✝, snd✝) :: tl2)
h : (fst✝¹, snd✝¹).1 = (fst✝, snd✝).1 ∧ (fst✝¹, snd✝¹).2 = !(fst✝, snd✝).2
⊢ Red ((fst✝¹, snd✝¹) :: tl1) tl2

Next tactic:
cases h
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          cases hd2
          cases h
          

Proof state:
case pos.mk.mk.intro
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
tl1 tl2 : List (α × Bool)
fst✝¹ : α
snd✝¹ : Bool
fst✝ : α
snd✝ : Bool
htl : reduce tl1 = (fst✝, snd✝) :: tl2
ih : Red tl1 ((fst✝, snd✝) :: tl2)
left✝ : (fst✝¹, snd✝¹).1 = (fst✝, snd✝).1
right✝ : (fst✝¹, snd✝¹).2 = !(fst✝, snd✝).2
⊢ Red ((fst✝¹, snd✝¹) :: tl1) tl2

Next tactic:
dsimp at *
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          cases hd2
          cases h
          dsimp at *
          

Proof state:
case pos.mk.mk.intro
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
tl1 tl2 : List (α × Bool)
fst✝¹ : α
snd✝¹ : Bool
fst✝ : α
snd✝ : Bool
htl : reduce tl1 = (fst✝, snd✝) :: tl2
ih : Red tl1 ((fst✝, snd✝) :: tl2)
left✝ : fst✝¹ = fst✝
right✝ : snd✝¹ = !snd✝
⊢ Red ((fst✝¹, snd✝¹) :: tl1) tl2

Next tactic:
subst_vars
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          cases hd2
          cases h
          dsimp at *
          subst_vars
          

Proof state:
case pos.mk.mk.intro
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
tl1 tl2 : List (α × Bool)
fst✝ : α
snd✝ : Bool
htl : reduce tl1 = (fst✝, snd✝) :: tl2
ih : Red tl1 ((fst✝, snd✝) :: tl2)
⊢ Red ((fst✝, !snd✝) :: tl1) tl2

Next tactic:
apply Red.trans (Red.cons_cons ih)
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          cases hd2
          cases h
          dsimp at *
          subst_vars
          apply Red.trans (Red.cons_cons ih)
          

Proof state:
case pos.mk.mk.intro
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
tl1 tl2 : List (α × Bool)
fst✝ : α
snd✝ : Bool
htl : reduce tl1 = (fst✝, snd✝) :: tl2
ih : Red tl1 ((fst✝, snd✝) :: tl2)
⊢ Red ((fst✝, !snd✝) :: (fst✝, snd✝) :: tl2) tl2

Next tactic:
exact Red.Step.cons_not_rev.to_red
/-- The first theorem that characterises the function `reduce`: a word reduces to its maximal
  reduction. -/
@[to_additive "The first theorem that characterises the function `reduce`: a word reduces to its
  maximal reduction."]
theorem reduce.red : Red L (reduce L) := by
  induction' L with hd1 tl1 ih
  case nil => constructor
  case cons =>
    dsimp
    revert ih
    generalize htl : reduce tl1 = TL
    intro ih
    cases' TL with hd2 tl2
    case nil => exact Red.cons_cons ih
    case cons =>
      dsimp only
      split_ifs with h
      · trans
        · cases hd1
          cases hd2
          cases h
          dsimp at *
          subst_vars
          apply Red.trans (Red.cons_cons ih)
          exact Red.Step.cons_not_rev.to_red
      · 

Proof state:
case neg
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
hd1 : α × Bool
tl1 : List (α × Bool)
hd2 : α × Bool
tl2 : List (α × Bool)
htl : reduce tl1 = hd2 :: tl2
ih : Red tl1 (hd2 :: tl2)
h : ¬(hd1.1 = hd2.1 ∧ hd1.2 = !hd2.2)
⊢ Red (hd1 :: tl1) (hd1 :: hd2 :: tl2)

Next tactic:
exact Red.cons_cons ih
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by 

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
L2 L3 : List (α × Bool)
x✝¹ : α
x✝ : Bool
h : reduce [] = L2 ++ (x✝¹, x✝) :: (x✝¹, !x✝) :: L3
⊢ p

Next tactic:
cases L2
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> 

Proof state:
case nil
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
L3 : List (α × Bool)
x✝¹ : α
x✝ : Bool
h : reduce [] = [] ++ (x✝¹, x✝) :: (x✝¹, !x✝) :: L3
⊢ p

Next tactic:
injections
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> 

Proof state:
case cons
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
L3 : List (α × Bool)
x✝¹ : α
x✝ : Bool
head✝ : α × Bool
tail✝ : List (α × Bool)
h : reduce [] = head✝ :: tail✝ ++ (x✝¹, x✝) :: (x✝¹, !x✝) :: L3
⊢ p

Next tactic:
injections
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
⊢ reduce ((x, b) :: L1) = L2 ++ (x', b') :: (x', !b') :: L3 → p

Next tactic:
dsimp
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
⊢ List.rec [(x, b)] (fun head tail tail_ih => if x = head.1 ∧ b = !head.2 then tail else (x, b) :: head :: tail)
        (reduce L1) =
      L2 ++ (x', b') :: (x', !b') :: L3 →
    p

Next tactic:
cases r : reduce L1 with
      | nil =>
        dsimp
        intro h
        exfalso
        have := congr_arg List.length h
        simp? [List.length] at this says
         simp only [List.length, zero_add, List.length_append] at this
        rw [add_comm, add_assoc, add_assoc, add_comm, <-add_assoc] at this
        simp [Nat.one_eq_succ_zero, Nat.succ_add] at this
        -- Porting note: needed to add this step in #3414.
        -- This is caused by https://github.com/leanprover/lean4/pull/2146.
        -- Nevertheless the proof could be cleaned up.
        cases this
      | cons hd tail =>
        cases' hd with y c
        dsimp only
        split_ifs with h <;> intro H
        · rw [ H ] at r
          exact @reduce.not _ L1 ((y, c)::L2) L3 x' b' r
        · rcases L2 with ( _ | ⟨ a , L2 ⟩ )
          · injections
            subst_vars
            simp at h
          · refine' @reduce.not _ L1 L2 L3 x' b' _
            injection H with _ H
            rw [ r , H ]
            rfl
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      

Proof state:
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
x✝ : List (α × Bool)
r : reduce L1 = x✝
⊢ List.rec [(x, b)] (fun head tail tail_ih => if x = head.1 ∧ b = !head.2 then tail else (x, b) :: head :: tail) x✝ =
      L2 ++ (x', b') :: (x', !b') :: L3 →
    p

Next tactic:
cases r : reduce L1 with
      | nil =>
        dsimp
        intro h
        exfalso
        have := congr_arg List.length h
        simp? [List.length] at this says
         simp only [List.length, zero_add, List.length_append] at this
        rw [add_comm, add_assoc, add_assoc, add_comm, <-add_assoc] at this
        simp [Nat.one_eq_succ_zero, Nat.succ_add] at this
        -- Porting note: needed to add this step in #3414.
        -- This is caused by https://github.com/leanprover/lean4/pull/2146.
        -- Nevertheless the proof could be cleaned up.
        cases this
      | cons hd tail =>
        cases' hd with y c
        dsimp only
        split_ifs with h <;> intro H
        · rw [ H ] at r
          exact @reduce.not _ L1 ((y, c)::L2) L3 x' b' r
        · rcases L2 with ( _ | ⟨ a , L2 ⟩ )
          · injections
            subst_vars
            simp at h
          · refine' @reduce.not _ L1 L2 L3 x' b' _
            injection H with _ H
            rw [ r , H ]
            rfl
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      cases r : reduce L1 with
      

Proof state:
case nil
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
r : reduce L1 = []
⊢ List.rec [(x, b)] (fun head tail tail_ih => if x = head.1 ∧ b = !head.2 then tail else (x, b) :: head :: tail) [] =
      L2 ++ (x', b') :: (x', !b') :: L3 →
    p

Next tactic:
| nil =>
        dsimp
        intro h
        exfalso
        have := congr_arg List.length h
        simp? [List.length] at this says
         simp only [List.length, zero_add, List.length_append] at this
        rw [add_comm, add_assoc, add_assoc, add_comm, <-add_assoc] at this
        simp [Nat.one_eq_succ_zero, Nat.succ_add] at this
        -- Porting note: needed to add this step in #3414.
        -- This is caused by https://github.com/leanprover/lean4/pull/2146.
        -- Nevertheless the proof could be cleaned up.
        cases this
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      cases r : reduce L1 with
      | nil =>
        

Proof state:
case nil
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
r : reduce L1 = []
⊢ List.rec [(x, b)] (fun head tail tail_ih => if x = head.1 ∧ b = !head.2 then tail else (x, b) :: head :: tail) [] =
      L2 ++ (x', b') :: (x', !b') :: L3 →
    p

Next tactic:
dsimp
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      cases r : reduce L1 with
      | nil =>
        dsimp
        

Proof state:
case nil
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
r : reduce L1 = []
⊢ [(x, b)] = L2 ++ (x', b') :: (x', !b') :: L3 → p

Next tactic:
intro h
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      cases r : reduce L1 with
      | nil =>
        dsimp
        intro h
        

Proof state:
case nil
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
r : reduce L1 = []
h : [(x, b)] = L2 ++ (x', b') :: (x', !b') :: L3
⊢ p

Next tactic:
exfalso
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      cases r : reduce L1 with
      | nil =>
        dsimp
        intro h
        exfalso
        

Proof state:
case nil.h
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
r : reduce L1 = []
h : [(x, b)] = L2 ++ (x', b') :: (x', !b') :: L3
⊢ False

Next tactic:
have := congr_arg List.length h
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      cases r : reduce L1 with
      | nil =>
        dsimp
        intro h
        exfalso
        have := congr_arg List.length h
        

Proof state:
case nil.h
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
r : reduce L1 = []
h : [(x, b)] = L2 ++ (x', b') :: (x', !b') :: L3
this : List.length [(x, b)] = List.length (L2 ++ (x', b') :: (x', !b') :: L3)
⊢ False

Next tactic:
simp? [List.length] at this says
         simp only [List.length, zero_add, List.length_append] at this
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      cases r : reduce L1 with
      | nil =>
        dsimp
        intro h
        exfalso
        have := congr_arg List.length h
        simp? [List.length] at this says
         

Proof state:
case nil.h
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
r : reduce L1 = []
h : [(x, b)] = L2 ++ (x', b') :: (x', !b') :: L3
this : List.length [(x, b)] = List.length (L2 ++ (x', b') :: (x', !b') :: L3)
⊢ False

Next tactic:
simp only [List.length, zero_add, List.length_append] at this
@[to_additive]
theorem reduce.not {p : Prop} : ∀ {L₁ L₂ L₃ : List (α × Bool)} {x : α} {b},
    ((reduce L₁) = L₂ ++ ((x,b)::(x ,!b)::L₃)) → p
  | [], L2 ,L3, _, _ => fun h => by cases L2 <;> injections
  | (x, b)::L1, L2, L3, x', b' => by
      dsimp
      cases r : reduce L1 with
      | nil =>
        dsimp
        intro h
        exfalso
        have := congr_arg List.length h
        simp? [List.length] at this says
         simp only [List.length, zero_add, List.length_append] at this
        

Proof state:
case nil.h
α : Type u
L L₁ L₂ L₃ L₄ : List (α × Bool)
inst✝ : DecidableEq α
p : Prop
x : α
b : Bool
L1 L2 L3 : List (α × Bool)
x' : α
b' : Bool
r : reduce L1 = []
h : [(x, b)] = L2 ++ (x', b') :: (x', !b') :: L3
this : 1 = List.length L2 + (List.length L3 + 1 + 1)
⊢ False

Next tactic:
rw [add_comm, add_assoc, add_assoc, add_comm, <-add_assoc] at this