l3lab/ntp-mathlib huggingface dataset:
theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p (S k) = (L₁, o, L₂)) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.clear p k q), s, S⟩ ⟨some q, o, update S k L₂⟩ := by
  induction' L₁ with a L₁ IH generalizing S s
  · refine' TransGen.head' rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    revert e; cases' S k with a Sk <;> intro e
    · cases e
      rfl
    simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢
    revert e; cases p a <;> intro e <;>
      simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢
    · rcases e with ⟨e₁, e₂⟩
      rw [e₁, e₂]
  · refine' TransGen.head rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    cases' e₁ : S k with a' Sk <;> rw [e₁, splitAtPred] at e
    · cases e
    cases e₂ : p a' <;> simp only [e₂, cond] at e
    swap
    · 

Proof state:
case cons.cons.true
p : Γ' → Bool
k : K'
q : Λ'
o : Option Γ'
L₂ : List Γ'
a : Γ'
L₁ : List Γ'
IH :
  ∀ {s : Option Γ'} {S : K' → List Γ'},
    splitAtPred p (S k) = (L₁, o, L₂) →
      Reaches₁ (TM2.step tr) { l := some (Λ'.clear p k q), var := s, stk := S }
        { l := some q, var := o, stk := update S k L₂ }
s : Option Γ'
S : K' → List Γ'
a' : Γ'
Sk : List Γ'
e₁ : S k = a' :: Sk
e₂ : p a' = true
e : ([], some a', Sk) = (a :: L₁, o, L₂)
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif
        match List.head? (a' :: Sk), true, p with
        | some x, x_1, f => f x
        | none, y, x => y then
      { l := some q, var := List.head? (a' :: Sk), stk := update S k (List.tail (a' :: Sk)) }
    else { l := some (Λ'.clear p k q), var := List.head? (a' :: Sk), stk := update S k (List.tail (a' :: Sk)) })
    { l := some q, var := o, stk := update S k L₂ }

Next tactic:
cases e
theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p (S k) = (L₁, o, L₂)) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.clear p k q), s, S⟩ ⟨some q, o, update S k L₂⟩ := by
  induction' L₁ with a L₁ IH generalizing S s
  · refine' TransGen.head' rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    revert e; cases' S k with a Sk <;> intro e
    · cases e
      rfl
    simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢
    revert e; cases p a <;> intro e <;>
      simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢
    · rcases e with ⟨e₁, e₂⟩
      rw [e₁, e₂]
  · refine' TransGen.head rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    cases' e₁ : S k with a' Sk <;> rw [e₁, splitAtPred] at e
    · cases e
    cases e₂ : p a' <;> simp only [e₂, cond] at e
    swap
    · cases e
    

Proof state:
case cons.cons.false
p : Γ' → Bool
k : K'
q : Λ'
o : Option Γ'
L₂ : List Γ'
a : Γ'
L₁ : List Γ'
IH :
  ∀ {s : Option Γ'} {S : K' → List Γ'},
    splitAtPred p (S k) = (L₁, o, L₂) →
      Reaches₁ (TM2.step tr) { l := some (Λ'.clear p k q), var := s, stk := S }
        { l := some q, var := o, stk := update S k L₂ }
s : Option Γ'
S : K' → List Γ'
a' : Γ'
Sk : List Γ'
e₁ : S k = a' :: Sk
e₂ : p a' = false
e : (a' :: (splitAtPred p Sk).1, (splitAtPred p Sk).2.1, (splitAtPred p Sk).2.2) = (a :: L₁, o, L₂)
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif
        match List.head? (a' :: Sk), true, p with
        | some x, x_1, f => f x
        | none, y, x => y then
      { l := some q, var := List.head? (a' :: Sk), stk := update S k (List.tail (a' :: Sk)) }
    else { l := some (Λ'.clear p k q), var := List.head? (a' :: Sk), stk := update S k (List.tail (a' :: Sk)) })
    { l := some q, var := o, stk := update S k L₂ }

Next tactic:
rcases e₃ : splitAtPred p Sk with ⟨_, _, _⟩
theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p (S k) = (L₁, o, L₂)) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.clear p k q), s, S⟩ ⟨some q, o, update S k L₂⟩ := by
  induction' L₁ with a L₁ IH generalizing S s
  · refine' TransGen.head' rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    revert e; cases' S k with a Sk <;> intro e
    · cases e
      rfl
    simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢
    revert e; cases p a <;> intro e <;>
      simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢
    · rcases e with ⟨e₁, e₂⟩
      rw [e₁, e₂]
  · refine' TransGen.head rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    cases' e₁ : S k with a' Sk <;> rw [e₁, splitAtPred] at e
    · cases e
    cases e₂ : p a' <;> simp only [e₂, cond] at e
    swap
    · cases e
    rcases e₃ : splitAtPred p Sk with ⟨_, _, _⟩
    

Proof state:
case cons.cons.false.mk.mk
p : Γ' → Bool
k : K'
q : Λ'
o : Option Γ'
L₂ : List Γ'
a : Γ'
L₁ : List Γ'
IH :
  ∀ {s : Option Γ'} {S : K' → List Γ'},
    splitAtPred p (S k) = (L₁, o, L₂) →
      Reaches₁ (TM2.step tr) { l := some (Λ'.clear p k q), var := s, stk := S }
        { l := some q, var := o, stk := update S k L₂ }
s : Option Γ'
S : K' → List Γ'
a' : Γ'
Sk : List Γ'
e₁ : S k = a' :: Sk
e₂ : p a' = false
e : (a' :: (splitAtPred p Sk).1, (splitAtPred p Sk).2.1, (splitAtPred p Sk).2.2) = (a :: L₁, o, L₂)
fst✝¹ : List Γ'
fst✝ : Option Γ'
snd✝ : List Γ'
e₃ : splitAtPred p Sk = (fst✝¹, fst✝, snd✝)
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif
        match List.head? (a' :: Sk), true, p with
        | some x, x_1, f => f x
        | none, y, x => y then
      { l := some q, var := List.head? (a' :: Sk), stk := update S k (List.tail (a' :: Sk)) }
    else { l := some (Λ'.clear p k q), var := List.head? (a' :: Sk), stk := update S k (List.tail (a' :: Sk)) })
    { l := some q, var := o, stk := update S k L₂ }

Next tactic:
rw [e₃] at e
theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p (S k) = (L₁, o, L₂)) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.clear p k q), s, S⟩ ⟨some q, o, update S k L₂⟩ := by
  induction' L₁ with a L₁ IH generalizing S s
  · refine' TransGen.head' rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    revert e; cases' S k with a Sk <;> intro e
    · cases e
      rfl
    simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢
    revert e; cases p a <;> intro e <;>
      simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢
    · rcases e with ⟨e₁, e₂⟩
      rw [e₁, e₂]
  · refine' TransGen.head rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    cases' e₁ : S k with a' Sk <;> rw [e₁, splitAtPred] at e
    · cases e
    cases e₂ : p a' <;> simp only [e₂, cond] at e
    swap
    · cases e
    rcases e₃ : splitAtPred p Sk with ⟨_, _, _⟩
    rw [e₃] at e
    

Proof state:
case cons.cons.false.mk.mk
p : Γ' → Bool
k : K'
q : Λ'
o : Option Γ'
L₂ : List Γ'
a : Γ'
L₁ : List Γ'
IH :
  ∀ {s : Option Γ'} {S : K' → List Γ'},
    splitAtPred p (S k) = (L₁, o, L₂) →
      Reaches₁ (TM2.step tr) { l := some (Λ'.clear p k q), var := s, stk := S }
        { l := some q, var := o, stk := update S k L₂ }
s : Option Γ'
S : K' → List Γ'
a' : Γ'
Sk : List Γ'
e₁ : S k = a' :: Sk
e₂ : p a' = false
fst✝¹ : List Γ'
fst✝ : Option Γ'
snd✝ : List Γ'
e : (a' :: (fst✝¹, fst✝, snd✝).1, (fst✝¹, fst✝, snd✝).2.1, (fst✝¹, fst✝, snd✝).2.2) = (a :: L₁, o, L₂)
e₃ : splitAtPred p Sk = (fst✝¹, fst✝, snd✝)
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif
        match List.head? (a' :: Sk), true, p with
        | some x, x_1, f => f x
        | none, y, x => y then
      { l := some q, var := List.head? (a' :: Sk), stk := update S k (List.tail (a' :: Sk)) }
    else { l := some (Λ'.clear p k q), var := List.head? (a' :: Sk), stk := update S k (List.tail (a' :: Sk)) })
    { l := some q, var := o, stk := update S k L₂ }

Next tactic:
cases e
theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p (S k) = (L₁, o, L₂)) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.clear p k q), s, S⟩ ⟨some q, o, update S k L₂⟩ := by
  induction' L₁ with a L₁ IH generalizing S s
  · refine' TransGen.head' rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    revert e; cases' S k with a Sk <;> intro e
    · cases e
      rfl
    simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢
    revert e; cases p a <;> intro e <;>
      simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢
    · rcases e with ⟨e₁, e₂⟩
      rw [e₁, e₂]
  · refine' TransGen.head rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    cases' e₁ : S k with a' Sk <;> rw [e₁, splitAtPred] at e
    · cases e
    cases e₂ : p a' <;> simp only [e₂, cond] at e
    swap
    · cases e
    rcases e₃ : splitAtPred p Sk with ⟨_, _, _⟩
    rw [e₃] at e
    cases e
    

Proof state:
case cons.cons.false.mk.mk.refl
p : Γ' → Bool
k : K'
q : Λ'
a : Γ'
s : Option Γ'
S : K' → List Γ'
Sk fst✝¹ : List Γ'
fst✝ : Option Γ'
snd✝ : List Γ'
e₃ : splitAtPred p Sk = (fst✝¹, fst✝, snd✝)
e₁ : S k = a :: Sk
e₂ : p a = false
IH :
  ∀ {s : Option Γ'} {S : K' → List Γ'},
    splitAtPred p (S k) = ((fst✝¹, fst✝, snd✝).1, (fst✝¹, fst✝, snd✝).2.1, (fst✝¹, fst✝, snd✝).2.2) →
      Reaches₁ (TM2.step tr) { l := some (Λ'.clear p k q), var := s, stk := S }
        { l := some q, var := (fst✝¹, fst✝, snd✝).2.1, stk := update S k (fst✝¹, fst✝, snd✝).2.2 }
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    (bif
        match List.head? (a :: Sk), true, p with
        | some x, x_1, f => f x
        | none, y, x => y then
      { l := some q, var := List.head? (a :: Sk), stk := update S k (List.tail (a :: Sk)) }
    else { l := some (Λ'.clear p k q), var := List.head? (a :: Sk), stk := update S k (List.tail (a :: Sk)) })
    { l := some q, var := (fst✝¹, fst✝, snd✝).2.1, stk := update S k (fst✝¹, fst✝, snd✝).2.2 }

Next tactic:
simp only [List.head?_cons, e₂, List.tail_cons, cond_false]
theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p (S k) = (L₁, o, L₂)) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.clear p k q), s, S⟩ ⟨some q, o, update S k L₂⟩ := by
  induction' L₁ with a L₁ IH generalizing S s
  · refine' TransGen.head' rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    revert e; cases' S k with a Sk <;> intro e
    · cases e
      rfl
    simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢
    revert e; cases p a <;> intro e <;>
      simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢
    · rcases e with ⟨e₁, e₂⟩
      rw [e₁, e₂]
  · refine' TransGen.head rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    cases' e₁ : S k with a' Sk <;> rw [e₁, splitAtPred] at e
    · cases e
    cases e₂ : p a' <;> simp only [e₂, cond] at e
    swap
    · cases e
    rcases e₃ : splitAtPred p Sk with ⟨_, _, _⟩
    rw [e₃] at e
    cases e
    simp only [List.head?_cons, e₂, List.tail_cons, cond_false]
    

Proof state:
case cons.cons.false.mk.mk.refl
p : Γ' → Bool
k : K'
q : Λ'
a : Γ'
s : Option Γ'
S : K' → List Γ'
Sk fst✝¹ : List Γ'
fst✝ : Option Γ'
snd✝ : List Γ'
e₃ : splitAtPred p Sk = (fst✝¹, fst✝, snd✝)
e₁ : S k = a :: Sk
e₂ : p a = false
IH :
  ∀ {s : Option Γ'} {S : K' → List Γ'},
    splitAtPred p (S k) = ((fst✝¹, fst✝, snd✝).1, (fst✝¹, fst✝, snd✝).2.1, (fst✝¹, fst✝, snd✝).2.2) →
      Reaches₁ (TM2.step tr) { l := some (Λ'.clear p k q), var := s, stk := S }
        { l := some q, var := (fst✝¹, fst✝, snd✝).2.1, stk := update S k (fst✝¹, fst✝, snd✝).2.2 }
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    { l := some (Λ'.clear p k q), var := some a, stk := update S k Sk }
    { l := some q, var := fst✝, stk := update S k snd✝ }

Next tactic:
convert @IH _ (update S k Sk) _ using 2
theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p (S k) = (L₁, o, L₂)) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.clear p k q), s, S⟩ ⟨some q, o, update S k L₂⟩ := by
  induction' L₁ with a L₁ IH generalizing S s
  · refine' TransGen.head' rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    revert e; cases' S k with a Sk <;> intro e
    · cases e
      rfl
    simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢
    revert e; cases p a <;> intro e <;>
      simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢
    · rcases e with ⟨e₁, e₂⟩
      rw [e₁, e₂]
  · refine' TransGen.head rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    cases' e₁ : S k with a' Sk <;> rw [e₁, splitAtPred] at e
    · cases e
    cases e₂ : p a' <;> simp only [e₂, cond] at e
    swap
    · cases e
    rcases e₃ : splitAtPred p Sk with ⟨_, _, _⟩
    rw [e₃] at e
    cases e
    simp only [List.head?_cons, e₂, List.tail_cons, cond_false]
    convert @IH _ (update S k Sk) _ using 2 <;> 

Proof state:
case h.e'_2.h.e'_7
p : Γ' → Bool
k : K'
q : Λ'
a : Γ'
s : Option Γ'
S : K' → List Γ'
Sk fst✝¹ : List Γ'
fst✝ : Option Γ'
snd✝ : List Γ'
e₃ : splitAtPred p Sk = (fst✝¹, fst✝, snd✝)
e₁ : S k = a :: Sk
e₂ : p a = false
IH :
  ∀ {s : Option Γ'} {S : K' → List Γ'},
    splitAtPred p (S k) = ((fst✝¹, fst✝, snd✝).1, (fst✝¹, fst✝, snd✝).2.1, (fst✝¹, fst✝, snd✝).2.2) →
      Reaches₁ (TM2.step tr) { l := some (Λ'.clear p k q), var := s, stk := S }
        { l := some q, var := (fst✝¹, fst✝, snd✝).2.1, stk := update S k (fst✝¹, fst✝, snd✝).2.2 }
⊢ update S k snd✝ = update (update S k Sk) k (fst✝¹, fst✝, snd✝).2.2

Next tactic:
simp [e₃]
theorem clear_ok {p k q s L₁ o L₂} {S : K' → List Γ'} (e : splitAtPred p (S k) = (L₁, o, L₂)) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.clear p k q), s, S⟩ ⟨some q, o, update S k L₂⟩ := by
  induction' L₁ with a L₁ IH generalizing S s
  · refine' TransGen.head' rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    revert e; cases' S k with a Sk <;> intro e
    · cases e
      rfl
    simp only [splitAtPred, Option.elim, List.head?, List.tail_cons] at e ⊢
    revert e; cases p a <;> intro e <;>
      simp only [cond_false, cond_true, Prod.mk.injEq, true_and, false_and] at e ⊢
    · rcases e with ⟨e₁, e₂⟩
      rw [e₁, e₂]
  · refine' TransGen.head rfl _
    simp only [TM2.step, Option.mem_def, TM2.stepAux, Option.elim]
    cases' e₁ : S k with a' Sk <;> rw [e₁, splitAtPred] at e
    · cases e
    cases e₂ : p a' <;> simp only [e₂, cond] at e
    swap
    · cases e
    rcases e₃ : splitAtPred p Sk with ⟨_, _, _⟩
    rw [e₃] at e
    cases e
    simp only [List.head?_cons, e₂, List.tail_cons, cond_false]
    convert @IH _ (update S k Sk) _ using 2 <;> 

Proof state:
case cons.cons.false.mk.mk.refl.convert_2
p : Γ' → Bool
k : K'
q : Λ'
a : Γ'
s : Option Γ'
S : K' → List Γ'
Sk fst✝¹ : List Γ'
fst✝ : Option Γ'
snd✝ : List Γ'
e₃ : splitAtPred p Sk = (fst✝¹, fst✝, snd✝)
e₁ : S k = a :: Sk
e₂ : p a = false
IH :
  ∀ {s : Option Γ'} {S : K' → List Γ'},
    splitAtPred p (S k) = ((fst✝¹, fst✝, snd✝).1, (fst✝¹, fst✝, snd✝).2.1, (fst✝¹, fst✝, snd✝).2.2) →
      Reaches₁ (TM2.step tr) { l := some (Λ'.clear p k q), var := s, stk := S }
        { l := some q, var := (fst✝¹, fst✝, snd✝).2.1, stk := update S k (fst✝¹, fst✝, snd✝).2.2 }
⊢ splitAtPred p (update S k Sk k) = ((fst✝¹, fst✝, snd✝).1, (fst✝¹, fst✝, snd✝).2.1, (fst✝¹, fst✝, snd✝).2.2)

Next tactic:
simp [e₃]
theorem copy_ok (q s a b c d) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.copy q), s, K'.elim a b c d⟩
      ⟨some q, none, K'.elim (List.reverseAux b a) [] c (List.reverseAux b d)⟩ := by
  

Proof state:
q : Λ'
s : Option Γ'
a b c d : List Γ'
⊢ Reaches₁ (TM2.step tr) { l := some (Λ'.copy q), var := s, stk := elim a b c d }
    { l := some q, var := none, stk := elim (List.reverseAux b a) [] c (List.reverseAux b d) }

Next tactic:
induction' b with x b IH generalizing a d s
theorem copy_ok (q s a b c d) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.copy q), s, K'.elim a b c d⟩
      ⟨some q, none, K'.elim (List.reverseAux b a) [] c (List.reverseAux b d)⟩ := by
  induction' b with x b IH generalizing a d s
  · 

Proof state:
case nil
q : Λ'
c : List Γ'
s : Option Γ'
a d : List Γ'
⊢ Reaches₁ (TM2.step tr) { l := some (Λ'.copy q), var := s, stk := elim a [] c d }
    { l := some q, var := none, stk := elim (List.reverseAux [] a) [] c (List.reverseAux [] d) }

Next tactic:
refine' TransGen.single _
theorem copy_ok (q s a b c d) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.copy q), s, K'.elim a b c d⟩
      ⟨some q, none, K'.elim (List.reverseAux b a) [] c (List.reverseAux b d)⟩ := by
  induction' b with x b IH generalizing a d s
  · refine' TransGen.single _
    

Proof state:
case nil
q : Λ'
c : List Γ'
s : Option Γ'
a d : List Γ'
⊢ { l := some q, var := none, stk := elim (List.reverseAux [] a) [] c (List.reverseAux [] d) } ∈
    TM2.step tr { l := some (Λ'.copy q), var := s, stk := elim a [] c d }

Next tactic:
simp
theorem copy_ok (q s a b c d) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.copy q), s, K'.elim a b c d⟩
      ⟨some q, none, K'.elim (List.reverseAux b a) [] c (List.reverseAux b d)⟩ := by
  induction' b with x b IH generalizing a d s
  · refine' TransGen.single _
    simp
  

Proof state:
case cons
q : Λ'
c : List Γ'
x : Γ'
b : List Γ'
IH :
  ∀ (s : Option Γ') (a d : List Γ'),
    Reaches₁ (TM2.step tr) { l := some (Λ'.copy q), var := s, stk := elim a b c d }
      { l := some q, var := none, stk := elim (List.reverseAux b a) [] c (List.reverseAux b d) }
s : Option Γ'
a d : List Γ'
⊢ Reaches₁ (TM2.step tr) { l := some (Λ'.copy q), var := s, stk := elim a (x :: b) c d }
    { l := some q, var := none, stk := elim (List.reverseAux (x :: b) a) [] c (List.reverseAux (x :: b) d) }

Next tactic:
refine' TransGen.head rfl _
theorem copy_ok (q s a b c d) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.copy q), s, K'.elim a b c d⟩
      ⟨some q, none, K'.elim (List.reverseAux b a) [] c (List.reverseAux b d)⟩ := by
  induction' b with x b IH generalizing a d s
  · refine' TransGen.single _
    simp
  refine' TransGen.head rfl _
  

Proof state:
case cons
q : Λ'
c : List Γ'
x : Γ'
b : List Γ'
IH :
  ∀ (s : Option Γ') (a d : List Γ'),
    Reaches₁ (TM2.step tr) { l := some (Λ'.copy q), var := s, stk := elim a b c d }
      { l := some q, var := none, stk := elim (List.reverseAux b a) [] c (List.reverseAux b d) }
s : Option Γ'
a d : List Γ'
⊢ TransGen (fun a b => b ∈ TM2.step tr a) (TM2.stepAux (tr (Λ'.copy q)) s (elim a (x :: b) c d))
    { l := some q, var := none, stk := elim (List.reverseAux (x :: b) a) [] c (List.reverseAux (x :: b) d) }

Next tactic:
simp only [TM2.step, Option.mem_def, TM2.stepAux, elim_rev, List.head?_cons, Option.isSome_some,
    List.tail_cons, elim_update_rev, ne_eq, Function.update_noteq, elim_main, elim_update_main,
    elim_stack, elim_update_stack, cond_true, List.reverseAux_cons]
theorem copy_ok (q s a b c d) :
    Reaches₁ (TM2.step tr) ⟨some (Λ'.copy q), s, K'.elim a b c d⟩
      ⟨some q, none, K'.elim (List.reverseAux b a) [] c (List.reverseAux b d)⟩ := by
  induction' b with x b IH generalizing a d s
  · refine' TransGen.single _
    simp
  refine' TransGen.head rfl _
  simp only [TM2.step, Option.mem_def, TM2.stepAux, elim_rev, List.head?_cons, Option.isSome_some,
    List.tail_cons, elim_update_rev, ne_eq, Function.update_noteq, elim_main, elim_update_main,
    elim_stack, elim_update_stack, cond_true, List.reverseAux_cons]
  

Proof state:
case cons
q : Λ'
c : List Γ'
x : Γ'
b : List Γ'
IH :
  ∀ (s : Option Γ') (a d : List Γ'),
    Reaches₁ (TM2.step tr) { l := some (Λ'.copy q), var := s, stk := elim a b c d }
      { l := some q, var := none, stk := elim (List.reverseAux b a) [] c (List.reverseAux b d) }
s : Option Γ'
a d : List Γ'
⊢ TransGen
    (fun a b =>
      (match a with
        | { l := none, var := var, stk := stk } => none
        | { l := some l, var := v, stk := S } => some (TM2.stepAux (tr l) v S)) =
        some b)
    { l := some (Λ'.copy q), var := some x, stk := elim (Option.iget (some x) :: a) b c (Option.iget (some x) :: d) }
    { l := some q, var := none, stk := elim (List.reverseAux b (x :: a)) [] c (List.reverseAux b (x :: d)) }

Next tactic:
exact IH _ _ _
theorem trList_ne_consₗ : ∀ (l), ∀ x ∈ trList l, x ≠ Γ'.consₗ
  | a :: l, x, h => by
    

Proof state:
a : ℕ
l : List ℕ
x : Γ'
h : x ∈ trList (a :: l)
⊢ x ≠ Γ'.consₗ

Next tactic:
simp [trList] at h
theorem trList_ne_consₗ : ∀ (l), ∀ x ∈ trList l, x ≠ Γ'.consₗ
  | a :: l, x, h => by
    simp [trList] at h
    

Proof state:
a : ℕ
l : List ℕ
x : Γ'
h : x ∈ trNat a ∨ x = Γ'.cons ∨ x ∈ trList l
⊢ x ≠ Γ'.consₗ

Next tactic:
obtain h | rfl | h := h
theorem trList_ne_consₗ : ∀ (l), ∀ x ∈ trList l, x ≠ Γ'.consₗ
  | a :: l, x, h => by
    simp [trList] at h
    obtain h | rfl | h := h
    · 

Proof state:
case inl
a : ℕ
l : List ℕ
x : Γ'
h : x ∈ trNat a
⊢ x ≠ Γ'.consₗ

Next tactic:
rintro rfl
theorem trList_ne_consₗ : ∀ (l), ∀ x ∈ trList l, x ≠ Γ'.consₗ
  | a :: l, x, h => by
    simp [trList] at h
    obtain h | rfl | h := h
    · rintro rfl
      

Proof state:
case inl
a : ℕ
l : List ℕ
h : Γ'.consₗ ∈ trNat a
⊢ False

Next tactic:
cases trNat_natEnd _ _ h
theorem trList_ne_consₗ : ∀ (l), ∀ x ∈ trList l, x ≠ Γ'.consₗ
  | a :: l, x, h => by
    simp [trList] at h
    obtain h | rfl | h := h
    · rintro rfl
      cases trNat_natEnd _ _ h
    · 

Proof state:
case inr.inl
a : ℕ
l : List ℕ
⊢ Γ'.cons ≠ Γ'.consₗ

Next tactic:
rintro ⟨⟩
theorem trList_ne_consₗ : ∀ (l), ∀ x ∈ trList l, x ≠ Γ'.consₗ
  | a :: l, x, h => by
    simp [trList] at h
    obtain h | rfl | h := h
    · rintro rfl
      cases trNat_natEnd _ _ h
    · rintro ⟨⟩
    · 

Proof state:
case inr.inr
a : ℕ
l : List ℕ
x : Γ'
h : x ∈ trList l
⊢ x ≠ Γ'.consₗ

Next tactic:
exact trList_ne_consₗ l _ h
theorem head_main_ok {q s L} {c d : List Γ'} :
    Reaches₁ (TM2.step tr) ⟨some (head main q), s, K'.elim (trList L) [] c d⟩
      ⟨some q, none, K'.elim (trList [L.headI]) [] c d⟩ := by
  

Proof state:
q : Λ'
s : Option Γ'
L : List ℕ
c d : List Γ'
⊢ Reaches₁ (TM2.step tr) { l := some (head main q), var := s, stk := elim (trList L) [] c d }
    { l := some q, var := none, stk := elim (trList [List.headI L]) [] c d }

Next tactic:
let o : Option Γ' := List.casesOn L none fun _ _ => some Γ'.cons
theorem head_main_ok {q s L} {c d : List Γ'} :
    Reaches₁ (TM2.step tr) ⟨some (head main q), s, K'.elim (trList L) [] c d⟩
      ⟨some q, none, K'.elim (trList [L.headI]) [] c d⟩ := by
  let o : Option Γ' := List.casesOn L none fun _ _ => some Γ'.cons
  

Proof state:
q : Λ'
s : Option Γ'
L : List ℕ
c d : List Γ'
o : Option Γ' := List.casesOn L none fun x x => some Γ'.cons
⊢ Reaches₁ (TM2.step tr) { l := some (head main q), var := s, stk := elim (trList L) [] c d }
    { l := some q, var := none, stk := elim (trList [List.headI L]) [] c d }

Next tactic:
refine'
    (move_ok (by decide)
          (splitAtPred_eq _ _ (trNat L.headI) o (trList L.tail) (trNat_natEnd _) _)).trans
      (TransGen.head rfl (TransGen.head rfl _))
theorem head_main_ok {q s L} {c d : List Γ'} :
    Reaches₁ (TM2.step tr) ⟨some (head main q), s, K'.elim (trList L) [] c d⟩
      ⟨some q, none, K'.elim (trList [L.headI]) [] c d⟩ := by
  let o : Option Γ' := List.casesOn L none fun _ _ => some Γ'.cons
  refine'
    (move_ok (by 

Proof state:
q : Λ'
s : Option Γ'
L : List ℕ
c d : List Γ'
o : Option Γ' := List.casesOn L none fun x x => some Γ'.cons
⊢ main ≠ rev

Next tactic:
decide