l3lab/ntp-mathlib huggingface dataset:
theorem exists_enc_dec [Fintype Γ] : ∃ (n : ℕ) (enc : Γ → Vector Bool n) (dec : Vector Bool n → Γ),
    enc default = Vector.replicate n false ∧ ∀ a, dec (enc a) = a := by
  letI := Classical.decEq Γ
  let n := Fintype.card Γ
  obtain ⟨F⟩ := Fintype.truncEquivFin Γ
  let G : Fin n ↪ Fin n → Bool :=
    ⟨fun a b ↦ a = b, fun a b h ↦
      Bool.of_decide_true <| (congr_fun h b).trans <| Bool.decide_true rfl⟩
  let H := (F.toEmbedding.trans G).trans (Equiv.vectorEquivFin _ _).symm.toEmbedding
  classical
    let enc := H.setValue default (Vector.replicate n false)
    

Proof state:
case mk
Γ : Type u_1
inst✝¹ : Inhabited Γ
inst✝ : Fintype Γ
this : DecidableEq Γ := Classical.decEq Γ
n : ℕ := Fintype.card Γ
x✝ : Trunc (Γ ≃ Fin (Fintype.card Γ))
F : Γ ≃ Fin (Fintype.card Γ)
G : Fin n ↪ Fin n → Bool :=
  { toFun := fun a b => decide (a = b),
    inj' := (_ : ∀ (a b : Fin n), (fun a b => decide (a = b)) a = (fun a b => decide (a = b)) b → a = b) }
H : Γ ↪ Vector Bool n :=
  Function.Embedding.trans (Function.Embedding.trans (Equiv.toEmbedding F) G)
    (Equiv.toEmbedding (Equiv.vectorEquivFin Bool n).symm)
enc : Γ ↪ Vector Bool n := Function.Embedding.setValue H default (Vector.replicate n false)
⊢ ∃ n enc dec, enc default = Vector.replicate n false ∧ ∀ (a : Γ), dec (enc a) = a

Next tactic:
exact ⟨_, enc, Function.invFun enc, H.setValue_eq _ _, Function.leftInverse_invFun enc.2⟩
theorem stepAux_move (d : Dir) (q : Stmt'₁) (v : σ) (T : Tape Bool) :
    stepAux (moveₙ d q) v T = stepAux q v ((Tape.move d)^[n] T) := by
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
d : Dir
q : Stmt Bool Λ' σ
v : σ
T : Tape Bool
⊢ stepAux (move d q) v T = stepAux q v ((Tape.move d)^[n] T)

Next tactic:
suffices ∀ i, stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T) from this n
theorem stepAux_move (d : Dir) (q : Stmt'₁) (v : σ) (T : Tape Bool) :
    stepAux (moveₙ d q) v T = stepAux q v ((Tape.move d)^[n] T) := by
  suffices ∀ i, stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T) from this n
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
d : Dir
q : Stmt Bool Λ' σ
v : σ
T : Tape Bool
⊢ ∀ (i : ℕ), stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T)

Next tactic:
intro i
theorem stepAux_move (d : Dir) (q : Stmt'₁) (v : σ) (T : Tape Bool) :
    stepAux (moveₙ d q) v T = stepAux q v ((Tape.move d)^[n] T) := by
  suffices ∀ i, stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T) from this n
  intro i; 

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
d : Dir
q : Stmt Bool Λ' σ
v : σ
T : Tape Bool
i : ℕ
⊢ stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T)

Next tactic:
induction' i with i IH generalizing T
theorem stepAux_move (d : Dir) (q : Stmt'₁) (v : σ) (T : Tape Bool) :
    stepAux (moveₙ d q) v T = stepAux q v ((Tape.move d)^[n] T) := by
  suffices ∀ i, stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T) from this n
  intro i; induction' i with i IH generalizing T; · 

Proof state:
case zero
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
d : Dir
q : Stmt Bool Λ' σ
v : σ
T : Tape Bool
⊢ stepAux ((Stmt.move d)^[Nat.zero] q) v T = stepAux q v ((Tape.move d)^[Nat.zero] T)

Next tactic:
rfl
theorem stepAux_move (d : Dir) (q : Stmt'₁) (v : σ) (T : Tape Bool) :
    stepAux (moveₙ d q) v T = stepAux q v ((Tape.move d)^[n] T) := by
  suffices ∀ i, stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T) from this n
  intro i; induction' i with i IH generalizing T; · rfl
  

Proof state:
case succ
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
d : Dir
q : Stmt Bool Λ' σ
v : σ
i : ℕ
IH : ∀ (T : Tape Bool), stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T)
T : Tape Bool
⊢ stepAux ((Stmt.move d)^[Nat.succ i] q) v T = stepAux q v ((Tape.move d)^[Nat.succ i] T)

Next tactic:
rw [iterate_succ', iterate_succ]
theorem stepAux_move (d : Dir) (q : Stmt'₁) (v : σ) (T : Tape Bool) :
    stepAux (moveₙ d q) v T = stepAux q v ((Tape.move d)^[n] T) := by
  suffices ∀ i, stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T) from this n
  intro i; induction' i with i IH generalizing T; · rfl
  rw [iterate_succ', iterate_succ]
  

Proof state:
case succ
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
d : Dir
q : Stmt Bool Λ' σ
v : σ
i : ℕ
IH : ∀ (T : Tape Bool), stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T)
T : Tape Bool
⊢ stepAux ((Stmt.move d ∘ (Stmt.move d)^[i]) q) v T = stepAux q v (((Tape.move d)^[i] ∘ Tape.move d) T)

Next tactic:
simp only [stepAux, Function.comp_apply]
theorem stepAux_move (d : Dir) (q : Stmt'₁) (v : σ) (T : Tape Bool) :
    stepAux (moveₙ d q) v T = stepAux q v ((Tape.move d)^[n] T) := by
  suffices ∀ i, stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T) from this n
  intro i; induction' i with i IH generalizing T; · rfl
  rw [iterate_succ', iterate_succ]
  simp only [stepAux, Function.comp_apply]
  

Proof state:
case succ
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
d : Dir
q : Stmt Bool Λ' σ
v : σ
i : ℕ
IH : ∀ (T : Tape Bool), stepAux ((Stmt.move d)^[i] q) v T = stepAux q v ((Tape.move d)^[i] T)
T : Tape Bool
⊢ stepAux ((Stmt.move d)^[i] q) v (Tape.move d T) = stepAux q v ((Tape.move d)^[i] (Tape.move d T))

Next tactic:
rw [IH]
theorem supportsStmt_move {S : Finset Λ'₁} {d : Dir} {q : Stmt'₁} :
    SupportsStmt S (moveₙ d q) = SupportsStmt S q := by
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
d : Dir
q : Stmt Bool Λ' σ
⊢ SupportsStmt S (move d q) = SupportsStmt S q

Next tactic:
suffices ∀ {i}, SupportsStmt S ((Stmt.move d)^[i] q) = _ from this
theorem supportsStmt_move {S : Finset Λ'₁} {d : Dir} {q : Stmt'₁} :
    SupportsStmt S (moveₙ d q) = SupportsStmt S q := by
  suffices ∀ {i}, SupportsStmt S ((Stmt.move d)^[i] q) = _ from this
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
d : Dir
q : Stmt Bool Λ' σ
⊢ ∀ {i : ℕ}, SupportsStmt S ((Stmt.move d)^[i] q) = SupportsStmt S q

Next tactic:
intro i
theorem supportsStmt_move {S : Finset Λ'₁} {d : Dir} {q : Stmt'₁} :
    SupportsStmt S (moveₙ d q) = SupportsStmt S q := by
  suffices ∀ {i}, SupportsStmt S ((Stmt.move d)^[i] q) = _ from this
  intro i; 

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
d : Dir
q : Stmt Bool Λ' σ
i : ℕ
⊢ SupportsStmt S ((Stmt.move d)^[i] q) = SupportsStmt S q

Next tactic:
induction i generalizing q
theorem supportsStmt_move {S : Finset Λ'₁} {d : Dir} {q : Stmt'₁} :
    SupportsStmt S (moveₙ d q) = SupportsStmt S q := by
  suffices ∀ {i}, SupportsStmt S ((Stmt.move d)^[i] q) = _ from this
  intro i; induction i generalizing q <;> 

Proof state:
case zero
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
d : Dir
q : Stmt Bool Λ' σ
⊢ SupportsStmt S ((Stmt.move d)^[Nat.zero] q) = SupportsStmt S q

Next tactic:
simp only [*, iterate]
theorem supportsStmt_move {S : Finset Λ'₁} {d : Dir} {q : Stmt'₁} :
    SupportsStmt S (moveₙ d q) = SupportsStmt S q := by
  suffices ∀ {i}, SupportsStmt S ((Stmt.move d)^[i] q) = _ from this
  intro i; induction i generalizing q <;> 

Proof state:
case succ
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
d : Dir
n✝ : ℕ
n_ih✝ : ∀ {q : Stmt Bool Λ' σ}, SupportsStmt S ((Stmt.move d)^[n✝] q) = SupportsStmt S q
q : Stmt Bool Λ' σ
⊢ SupportsStmt S ((Stmt.move d)^[Nat.succ n✝] q) = SupportsStmt S q

Next tactic:
simp only [*, iterate]
theorem supportsStmt_move {S : Finset Λ'₁} {d : Dir} {q : Stmt'₁} :
    SupportsStmt S (moveₙ d q) = SupportsStmt S q := by
  suffices ∀ {i}, SupportsStmt S ((Stmt.move d)^[i] q) = _ from this
  intro i; induction i generalizing q <;> simp only [*, iterate]; 

Proof state:
case succ
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
d : Dir
n✝ : ℕ
n_ih✝ : ∀ {q : Stmt Bool Λ' σ}, SupportsStmt S ((Stmt.move d)^[n✝] q) = SupportsStmt S q
q : Stmt Bool Λ' σ
⊢ SupportsStmt S (Stmt.move d q) = SupportsStmt S q

Next tactic:
rfl
theorem supportsStmt_write {S : Finset Λ'₁} {l : List Bool} {q : Stmt'₁} :
    SupportsStmt S (write l q) = SupportsStmt S q := by
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
l : List Bool
q : Stmt Bool Λ' σ
⊢ SupportsStmt S (write l q) = SupportsStmt S q

Next tactic:
induction' l with _ l IH
theorem supportsStmt_write {S : Finset Λ'₁} {l : List Bool} {q : Stmt'₁} :
    SupportsStmt S (write l q) = SupportsStmt S q := by
  induction' l with _ l IH <;> 

Proof state:
case nil
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
q : Stmt Bool Λ' σ
⊢ SupportsStmt S (write [] q) = SupportsStmt S q

Next tactic:
simp only [write, SupportsStmt, *]
theorem supportsStmt_write {S : Finset Λ'₁} {l : List Bool} {q : Stmt'₁} :
    SupportsStmt S (write l q) = SupportsStmt S q := by
  induction' l with _ l IH <;> 

Proof state:
case cons
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
q : Stmt Bool Λ' σ
head✝ : Bool
l : List Bool
IH : SupportsStmt S (write l q) = SupportsStmt S q
⊢ SupportsStmt S (write (head✝ :: l) q) = SupportsStmt S q

Next tactic:
simp only [write, SupportsStmt, *]
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
i : ℕ
f : Vector Bool i → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool i), SupportsStmt S (f v)
⊢ SupportsStmt S (readAux i f)

Next tactic:
induction' i with i IH
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  induction' i with i IH; · 

Proof state:
case zero
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
f : Vector Bool Nat.zero → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool Nat.zero), SupportsStmt S (f v)
⊢ SupportsStmt S (readAux Nat.zero f)

Next tactic:
exact hf _
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  induction' i with i IH; · exact hf _
  

Proof state:
case succ
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
i : ℕ
IH :
  ∀ (f : Vector Bool i → Stmt Bool Λ' σ), (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
f : Vector Bool (Nat.succ i) → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool (Nat.succ i)), SupportsStmt S (f v)
⊢ SupportsStmt S (readAux (Nat.succ i) f)

Next tactic:
constructor
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  induction' i with i IH; · exact hf _
  constructor <;> 

Proof state:
case succ.left
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
i : ℕ
IH :
  ∀ (f : Vector Bool i → Stmt Bool Λ' σ), (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
f : Vector Bool (Nat.succ i) → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool (Nat.succ i)), SupportsStmt S (f v)
⊢ SupportsStmt S (Stmt.move Dir.right (readAux i fun v => f (true ::ᵥ v)))

Next tactic:
apply IH
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  induction' i with i IH; · exact hf _
  constructor <;> 

Proof state:
case succ.right
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
i : ℕ
IH :
  ∀ (f : Vector Bool i → Stmt Bool Λ' σ), (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
f : Vector Bool (Nat.succ i) → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool (Nat.succ i)), SupportsStmt S (f v)
⊢ SupportsStmt S (Stmt.move Dir.right (readAux i fun v => f (false ::ᵥ v)))

Next tactic:
apply IH
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  induction' i with i IH; · exact hf _
  constructor <;> apply IH <;> 

Proof state:
case succ.left.hf
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
i : ℕ
IH :
  ∀ (f : Vector Bool i → Stmt Bool Λ' σ), (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
f : Vector Bool (Nat.succ i) → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool (Nat.succ i)), SupportsStmt S (f v)
⊢ ∀ (v : Vector Bool i), SupportsStmt S (f (true ::ᵥ v))

Next tactic:
intro
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  induction' i with i IH; · exact hf _
  constructor <;> apply IH <;> 

Proof state:
case succ.right.hf
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
i : ℕ
IH :
  ∀ (f : Vector Bool i → Stmt Bool Λ' σ), (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
f : Vector Bool (Nat.succ i) → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool (Nat.succ i)), SupportsStmt S (f v)
⊢ ∀ (v : Vector Bool i), SupportsStmt S (f (false ::ᵥ v))

Next tactic:
intro
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  induction' i with i IH; · exact hf _
  constructor <;> apply IH <;> intro <;> 

Proof state:
case succ.left.hf
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
i : ℕ
IH :
  ∀ (f : Vector Bool i → Stmt Bool Λ' σ), (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
f : Vector Bool (Nat.succ i) → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool (Nat.succ i)), SupportsStmt S (f v)
v✝ : Vector Bool i
⊢ SupportsStmt S (f (true ::ᵥ v✝))

Next tactic:
apply hf
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; simp only [supportsStmt_move, hf])
  fun i f hf ↦ by
  induction' i with i IH; · exact hf _
  constructor <;> apply IH <;> intro <;> 

Proof state:
case succ.right.hf
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
i : ℕ
IH :
  ∀ (f : Vector Bool i → Stmt Bool Λ' σ), (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
f : Vector Bool (Nat.succ i) → Stmt Bool Λ' σ
hf : ∀ (v : Vector Bool (Nat.succ i)), SupportsStmt S (f v)
v✝ : Vector Bool i
⊢ SupportsStmt S (f (false ::ᵥ v✝))

Next tactic:
apply hf
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by 

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
this :
  ∀ (i : ℕ) (f : Vector Bool i → Stmt Bool Λ' σ),
    (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
hf : ∀ (a : Γ), SupportsStmt S (f✝ a)
⊢ ∀ (v : Vector Bool n), SupportsStmt S (move Dir.left (f✝ (dec v)))

Next tactic:
intro
theorem supportsStmt_read {S : Finset Λ'₁} :
    ∀ {f : Γ → Stmt'₁}, (∀ a, SupportsStmt S (f a)) → SupportsStmt S (read dec f) :=
  suffices
    ∀ (i) (f : Vector Bool i → Stmt'₁), (∀ v, SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
    from fun hf ↦ this n _ (by intro; 

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
S : Finset Λ'
f✝ : Γ → Stmt Bool Λ' σ
this :
  ∀ (i : ℕ) (f : Vector Bool i → Stmt Bool Λ' σ),
    (∀ (v : Vector Bool i), SupportsStmt S (f v)) → SupportsStmt S (readAux i f)
hf : ∀ (a : Γ), SupportsStmt S (f✝ a)
v✝ : Vector Bool n
⊢ SupportsStmt S (move Dir.left (f✝ (dec v✝)))

Next tactic:
simp only [supportsStmt_move, hf]
/-- The low level tape corresponding to the given tape over alphabet `Γ`. -/
def trTape' (L R : ListBlank Γ) : Tape Bool := by
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
enc0 : enc default = Vector.replicate n false
L R : ListBlank Γ
⊢ Tape Bool

Next tactic:
refine'
      Tape.mk' (L.bind (fun x ↦ (enc x).toList.reverse) ⟨n, _⟩)
        (R.bind (fun x ↦ (enc x).toList) ⟨n, _⟩)
/-- The low level tape corresponding to the given tape over alphabet `Γ`. -/
def trTape' (L R : ListBlank Γ) : Tape Bool := by
  refine'
      Tape.mk' (L.bind (fun x ↦ (enc x).toList.reverse) ⟨n, _⟩)
        (R.bind (fun x ↦ (enc x).toList) ⟨n, _⟩) <;>
    

Proof state:
case refine'_1
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
enc0 : enc default = Vector.replicate n false
L R : ListBlank Γ
⊢ (fun x => List.reverse (Vector.toList (enc x))) default = List.replicate n default

Next tactic:
simp only [enc0, Vector.replicate, List.reverse_replicate, Bool.default_bool, Vector.toList_mk]
/-- The low level tape corresponding to the given tape over alphabet `Γ`. -/
def trTape' (L R : ListBlank Γ) : Tape Bool := by
  refine'
      Tape.mk' (L.bind (fun x ↦ (enc x).toList.reverse) ⟨n, _⟩)
        (R.bind (fun x ↦ (enc x).toList) ⟨n, _⟩) <;>
    

Proof state:
case refine'_2
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
enc0 : enc default = Vector.replicate n false
L R : ListBlank Γ
⊢ (fun x => Vector.toList (enc x)) default = List.replicate n default

Next tactic:
simp only [enc0, Vector.replicate, List.reverse_replicate, Bool.default_bool, Vector.toList_mk]
theorem trTape_mk' (L R : ListBlank Γ) : trTape enc0 (Tape.mk' L R) = trTape' enc0 L R := by
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
enc0 : enc default = Vector.replicate n false
L R : ListBlank Γ
⊢ trTape enc0 (Tape.mk' L R) = trTape' enc0 L R

Next tactic:
simp only [trTape, Tape.mk'_left, Tape.mk'_right₀]
theorem trTape'_move_left (L R : ListBlank Γ) :
    (Tape.move Dir.left)^[n] (trTape' enc0 L R) = trTape' enc0 L.tail (R.cons L.head) := by
  

Proof state:
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
enc0 : enc default = Vector.replicate n false
M : Λ → Stmt₁
L R : ListBlank Γ
⊢ (Tape.move Dir.left)^[n] (trTape' enc0 L R) = trTape' enc0 (ListBlank.tail L) (ListBlank.cons (ListBlank.head L) R)

Next tactic:
obtain ⟨a, L, rfl⟩ := L.exists_cons
theorem trTape'_move_left (L R : ListBlank Γ) :
    (Tape.move Dir.left)^[n] (trTape' enc0 L R) = trTape' enc0 L.tail (R.cons L.head) := by
  obtain ⟨a, L, rfl⟩ := L.exists_cons
  

Proof state:
case intro.intro
Γ : Type u_1
inst✝² : Inhabited Γ
Λ : Type u_2
inst✝¹ : Inhabited Λ
σ : Type u_3
inst✝ : Inhabited σ
n : ℕ
enc : Γ → Vector Bool n
dec : Vector Bool n → Γ
enc0 : enc default = Vector.replicate n false
M : Λ → Stmt₁
R : ListBlank Γ
a : Γ
L : ListBlank Γ
⊢ (Tape.move Dir.left)^[n] (trTape' enc0 (ListBlank.cons a L) R) =
    trTape' enc0 (ListBlank.tail (ListBlank.cons a L)) (ListBlank.cons (ListBlank.head (ListBlank.cons a L)) R)

Next tactic:
simp only [trTape', ListBlank.cons_bind, ListBlank.head_cons, ListBlank.tail_cons]