l3lab/ntp-mathlib huggingface dataset:
/-- The `bind` function on lists is well defined on `ListBlank`s provided that the default element
is sent to a sequence of default elements. -/
def ListBlank.bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ')
    (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by
  apply l.liftOn (fun l ↦ ListBlank.mk (List.bind l f))
  

Proof state:
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l : ListBlank Γ
f : Γ → List Γ'
hf : ∃ n, f default = List.replicate n default
⊢ ∀ (a b : List Γ), BlankExtends a b → mk (List.bind a f) = mk (List.bind b f)

Next tactic:
rintro l _ ⟨i, rfl⟩
/-- The `bind` function on lists is well defined on `ListBlank`s provided that the default element
is sent to a sequence of default elements. -/
def ListBlank.bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ')
    (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by
  apply l.liftOn (fun l ↦ ListBlank.mk (List.bind l f))
  rintro l _ ⟨i, rfl⟩; 

Proof state:
case intro
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l✝ : ListBlank Γ
f : Γ → List Γ'
hf : ∃ n, f default = List.replicate n default
l : List Γ
i : ℕ
⊢ mk (List.bind l f) = mk (List.bind (l ++ List.replicate i default) f)

Next tactic:
cases' hf with n e
/-- The `bind` function on lists is well defined on `ListBlank`s provided that the default element
is sent to a sequence of default elements. -/
def ListBlank.bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ')
    (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by
  apply l.liftOn (fun l ↦ ListBlank.mk (List.bind l f))
  rintro l _ ⟨i, rfl⟩; cases' hf with n e; 

Proof state:
case intro.intro
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l✝ : ListBlank Γ
f : Γ → List Γ'
l : List Γ
i n : ℕ
e : f default = List.replicate n default
⊢ mk (List.bind l f) = mk (List.bind (l ++ List.replicate i default) f)

Next tactic:
refine' Quotient.sound' (Or.inl ⟨i * n, _⟩)
/-- The `bind` function on lists is well defined on `ListBlank`s provided that the default element
is sent to a sequence of default elements. -/
def ListBlank.bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ')
    (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by
  apply l.liftOn (fun l ↦ ListBlank.mk (List.bind l f))
  rintro l _ ⟨i, rfl⟩; cases' hf with n e; refine' Quotient.sound' (Or.inl ⟨i * n, _⟩)
  

Proof state:
case intro.intro
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l✝ : ListBlank Γ
f : Γ → List Γ'
l : List Γ
i n : ℕ
e : f default = List.replicate n default
⊢ List.bind (l ++ List.replicate i default) f = List.bind l f ++ List.replicate (i * n) default

Next tactic:
rw [List.append_bind, mul_comm]
/-- The `bind` function on lists is well defined on `ListBlank`s provided that the default element
is sent to a sequence of default elements. -/
def ListBlank.bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ')
    (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by
  apply l.liftOn (fun l ↦ ListBlank.mk (List.bind l f))
  rintro l _ ⟨i, rfl⟩; cases' hf with n e; refine' Quotient.sound' (Or.inl ⟨i * n, _⟩)
  rw [List.append_bind, mul_comm]; 

Proof state:
case intro.intro
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l✝ : ListBlank Γ
f : Γ → List Γ'
l : List Γ
i n : ℕ
e : f default = List.replicate n default
⊢ List.bind l f ++ List.bind (List.replicate i default) f = List.bind l f ++ List.replicate (n * i) default

Next tactic:
congr
/-- The `bind` function on lists is well defined on `ListBlank`s provided that the default element
is sent to a sequence of default elements. -/
def ListBlank.bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ')
    (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by
  apply l.liftOn (fun l ↦ ListBlank.mk (List.bind l f))
  rintro l _ ⟨i, rfl⟩; cases' hf with n e; refine' Quotient.sound' (Or.inl ⟨i * n, _⟩)
  rw [List.append_bind, mul_comm]; congr
  

Proof state:
case intro.intro.e_a
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l✝ : ListBlank Γ
f : Γ → List Γ'
l : List Γ
i n : ℕ
e : f default = List.replicate n default
⊢ List.bind (List.replicate i default) f = List.replicate (n * i) default

Next tactic:
induction' i with i IH
/-- The `bind` function on lists is well defined on `ListBlank`s provided that the default element
is sent to a sequence of default elements. -/
def ListBlank.bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ')
    (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by
  apply l.liftOn (fun l ↦ ListBlank.mk (List.bind l f))
  rintro l _ ⟨i, rfl⟩; cases' hf with n e; refine' Quotient.sound' (Or.inl ⟨i * n, _⟩)
  rw [List.append_bind, mul_comm]; congr
  induction' i with i IH; 

Proof state:
case intro.intro.e_a.zero
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l✝ : ListBlank Γ
f : Γ → List Γ'
l : List Γ
n : ℕ
e : f default = List.replicate n default
⊢ List.bind (List.replicate Nat.zero default) f = List.replicate (n * Nat.zero) default
case intro.intro.e_a.succ
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l✝ : ListBlank Γ
f : Γ → List Γ'
l : List Γ
n : ℕ
e : f default = List.replicate n default
i : ℕ
IH : List.bind (List.replicate i default) f = List.replicate (n * i) default
⊢ List.bind (List.replicate (Nat.succ i) default) f = List.replicate (n * Nat.succ i) default

Next tactic:
rfl
/-- The `bind` function on lists is well defined on `ListBlank`s provided that the default element
is sent to a sequence of default elements. -/
def ListBlank.bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (l : ListBlank Γ) (f : Γ → List Γ')
    (hf : ∃ n, f default = List.replicate n default) : ListBlank Γ' := by
  apply l.liftOn (fun l ↦ ListBlank.mk (List.bind l f))
  rintro l _ ⟨i, rfl⟩; cases' hf with n e; refine' Quotient.sound' (Or.inl ⟨i * n, _⟩)
  rw [List.append_bind, mul_comm]; congr
  induction' i with i IH; rfl
  

Proof state:
case intro.intro.e_a.succ
Γ : Type ?u.37228
Γ' : Type ?u.37240
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
l✝ : ListBlank Γ
f : Γ → List Γ'
l : List Γ
n : ℕ
e : f default = List.replicate n default
i : ℕ
IH : List.bind (List.replicate i default) f = List.replicate (n * i) default
⊢ List.bind (List.replicate (Nat.succ i) default) f = List.replicate (n * Nat.succ i) default

Next tactic:
simp only [IH, e, List.replicate_add, Nat.mul_succ, add_comm, List.replicate_succ, List.cons_bind]
@[simp]
theorem ListBlank.cons_bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (a : Γ) (l : ListBlank Γ)
    (f : Γ → List Γ') (hf) : (l.cons a).bind f hf = (l.bind f hf).append (f a) := by
  

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
a : Γ
l : ListBlank Γ
f : Γ → List Γ'
hf : ∃ n, f default = List.replicate n default
⊢ bind (cons a l) f hf = append (f a) (bind l f hf)

Next tactic:
refine' l.inductionOn fun l ↦ _
@[simp]
theorem ListBlank.cons_bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (a : Γ) (l : ListBlank Γ)
    (f : Γ → List Γ') (hf) : (l.cons a).bind f hf = (l.bind f hf).append (f a) := by
  refine' l.inductionOn fun l ↦ _
  -- Porting note: Added `suffices` to get `simp` to work.
  

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
a : Γ
l✝ : ListBlank Γ
f : Γ → List Γ'
hf : ∃ n, f default = List.replicate n default
l : List Γ
⊢ bind (cons a ⟦l⟧) f hf = append (f a) (bind ⟦l⟧ f hf)

Next tactic:
suffices ((mk l).cons a).bind f hf = ((mk l).bind f hf).append (f a) by exact this
@[simp]
theorem ListBlank.cons_bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (a : Γ) (l : ListBlank Γ)
    (f : Γ → List Γ') (hf) : (l.cons a).bind f hf = (l.bind f hf).append (f a) := by
  refine' l.inductionOn fun l ↦ _
  -- Porting note: Added `suffices` to get `simp` to work.
  suffices ((mk l).cons a).bind f hf = ((mk l).bind f hf).append (f a) by 

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
a : Γ
l✝ : ListBlank Γ
f : Γ → List Γ'
hf : ∃ n, f default = List.replicate n default
l : List Γ
this : bind (cons a (mk l)) f hf = append (f a) (bind (mk l) f hf)
⊢ bind (cons a ⟦l⟧) f hf = append (f a) (bind ⟦l⟧ f hf)

Next tactic:
exact this
@[simp]
theorem ListBlank.cons_bind {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (a : Γ) (l : ListBlank Γ)
    (f : Γ → List Γ') (hf) : (l.cons a).bind f hf = (l.bind f hf).append (f a) := by
  refine' l.inductionOn fun l ↦ _
  -- Porting note: Added `suffices` to get `simp` to work.
  suffices ((mk l).cons a).bind f hf = ((mk l).bind f hf).append (f a) by exact this
  

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
a : Γ
l✝ : ListBlank Γ
f : Γ → List Γ'
hf : ∃ n, f default = List.replicate n default
l : List Γ
⊢ bind (cons a (mk l)) f hf = append (f a) (bind (mk l) f hf)

Next tactic:
simp only [ListBlank.append_mk, ListBlank.bind_mk, ListBlank.cons_mk, List.cons_bind]
instance Tape.inhabited {Γ} [Inhabited Γ] : Inhabited (Tape Γ) :=
  ⟨by 

Proof state:
Γ : Type ?u.41028
inst✝ : Inhabited Γ
⊢ Tape Γ

Next tactic:
constructor
instance Tape.inhabited {Γ} [Inhabited Γ] : Inhabited (Tape Γ) :=
  ⟨by constructor <;> 

Proof state:
case head
Γ : Type ?u.41028
inst✝ : Inhabited Γ
⊢ Γ

Next tactic:
apply default
instance Tape.inhabited {Γ} [Inhabited Γ] : Inhabited (Tape Γ) :=
  ⟨by constructor <;> 

Proof state:
case left
Γ : Type ?u.41028
inst✝ : Inhabited Γ
⊢ ListBlank Γ

Next tactic:
apply default
instance Tape.inhabited {Γ} [Inhabited Γ] : Inhabited (Tape Γ) :=
  ⟨by constructor <;> 

Proof state:
case right
Γ : Type ?u.41028
inst✝ : Inhabited Γ
⊢ ListBlank Γ

Next tactic:
apply default
@[simp]
theorem Tape.move_left_right {Γ} [Inhabited Γ] (T : Tape Γ) :
    (T.move Dir.left).move Dir.right = T := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
⊢ move Dir.right (move Dir.left T) = T

Next tactic:
cases T
@[simp]
theorem Tape.move_left_right {Γ} [Inhabited Γ] (T : Tape Γ) :
    (T.move Dir.left).move Dir.right = T := by
  cases T; 

Proof state:
case mk
Γ : Type u_1
inst✝ : Inhabited Γ
head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ move Dir.right (move Dir.left { head := head✝, left := left✝, right := right✝ }) =
    { head := head✝, left := left✝, right := right✝ }

Next tactic:
simp [Tape.move]
@[simp]
theorem Tape.move_right_left {Γ} [Inhabited Γ] (T : Tape Γ) :
    (T.move Dir.right).move Dir.left = T := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
⊢ move Dir.left (move Dir.right T) = T

Next tactic:
cases T
@[simp]
theorem Tape.move_right_left {Γ} [Inhabited Γ] (T : Tape Γ) :
    (T.move Dir.right).move Dir.left = T := by
  cases T; 

Proof state:
case mk
Γ : Type u_1
inst✝ : Inhabited Γ
head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ move Dir.left (move Dir.right { head := head✝, left := left✝, right := right✝ }) =
    { head := head✝, left := left✝, right := right✝ }

Next tactic:
simp [Tape.move]
@[simp]
theorem Tape.mk'_left_right₀ {Γ} [Inhabited Γ] (T : Tape Γ) : Tape.mk' T.left T.right₀ = T := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
⊢ mk' T.left (right₀ T) = T

Next tactic:
cases T
@[simp]
theorem Tape.mk'_left_right₀ {Γ} [Inhabited Γ] (T : Tape Γ) : Tape.mk' T.left T.right₀ = T := by
  cases T
  

Proof state:
case mk
Γ : Type u_1
inst✝ : Inhabited Γ
head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ mk' { head := head✝, left := left✝, right := right✝ }.left
      (right₀ { head := head✝, left := left✝, right := right✝ }) =
    { head := head✝, left := left✝, right := right✝ }

Next tactic:
simp only [Tape.right₀, Tape.mk', ListBlank.head_cons, ListBlank.tail_cons, eq_self_iff_true,
    and_self_iff]
@[simp]
theorem Tape.move_left_mk' {Γ} [Inhabited Γ] (L R : ListBlank Γ) :
    (Tape.mk' L R).move Dir.left = Tape.mk' L.tail (R.cons L.head) := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
L R : ListBlank Γ
⊢ move Dir.left (mk' L R) = mk' (ListBlank.tail L) (ListBlank.cons (ListBlank.head L) R)

Next tactic:
simp only [Tape.move, Tape.mk', ListBlank.head_cons, eq_self_iff_true, ListBlank.cons_head_tail,
    and_self_iff, ListBlank.tail_cons]
@[simp]
theorem Tape.move_right_mk' {Γ} [Inhabited Γ] (L R : ListBlank Γ) :
    (Tape.mk' L R).move Dir.right = Tape.mk' (L.cons R.head) R.tail := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
L R : ListBlank Γ
⊢ move Dir.right (mk' L R) = mk' (ListBlank.cons (ListBlank.head R) L) (ListBlank.tail R)

Next tactic:
simp only [Tape.move, Tape.mk', ListBlank.head_cons, eq_self_iff_true, ListBlank.cons_head_tail,
    and_self_iff, ListBlank.tail_cons]
theorem Tape.right₀_nth {Γ} [Inhabited Γ] (T : Tape Γ) (n : ℕ) : T.right₀.nth n = T.nth n := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
n : ℕ
⊢ ListBlank.nth (right₀ T) n = nth T ↑n

Next tactic:
cases n
theorem Tape.right₀_nth {Γ} [Inhabited Γ] (T : Tape Γ) (n : ℕ) : T.right₀.nth n = T.nth n := by
  cases n <;> 

Proof state:
case zero
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
⊢ ListBlank.nth (right₀ T) Nat.zero = nth T ↑Nat.zero

Next tactic:
simp only [Tape.nth, Tape.right₀, Int.ofNat_zero, ListBlank.nth_zero,
    ListBlank.nth_succ, ListBlank.head_cons, ListBlank.tail_cons, Nat.zero_eq]
theorem Tape.right₀_nth {Γ} [Inhabited Γ] (T : Tape Γ) (n : ℕ) : T.right₀.nth n = T.nth n := by
  cases n <;> 

Proof state:
case succ
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
n✝ : ℕ
⊢ ListBlank.nth (right₀ T) (Nat.succ n✝) = nth T ↑(Nat.succ n✝)

Next tactic:
simp only [Tape.nth, Tape.right₀, Int.ofNat_zero, ListBlank.nth_zero,
    ListBlank.nth_succ, ListBlank.head_cons, ListBlank.tail_cons, Nat.zero_eq]
@[simp]
theorem Tape.mk'_nth_nat {Γ} [Inhabited Γ] (L R : ListBlank Γ) (n : ℕ) :
    (Tape.mk' L R).nth n = R.nth n := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
L R : ListBlank Γ
n : ℕ
⊢ nth (mk' L R) ↑n = ListBlank.nth R n

Next tactic:
rw [← Tape.right₀_nth, Tape.mk'_right₀]
@[simp]
theorem Tape.move_left_nth {Γ} [Inhabited Γ] :
    ∀ (T : Tape Γ) (i : ℤ), (T.move Dir.left).nth i = T.nth (i - 1)
  | ⟨_, L, _⟩, -(n + 1 : ℕ) => (ListBlank.nth_succ _ _).symm
  | ⟨_, L, _⟩, 0 => (ListBlank.nth_zero _).symm
  | ⟨a, L, R⟩, 1 => (ListBlank.nth_zero _).trans (ListBlank.head_cons _ _)
  | ⟨a, L, R⟩, (n + 1 : ℕ) + 1 => by
    

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
a : Γ
L R : ListBlank Γ
n : ℕ
⊢ nth (move Dir.left { head := a, left := L, right := R }) (↑(n + 1) + 1) =
    nth { head := a, left := L, right := R } (↑(n + 1) + 1 - 1)

Next tactic:
rw [add_sub_cancel]
@[simp]
theorem Tape.move_left_nth {Γ} [Inhabited Γ] :
    ∀ (T : Tape Γ) (i : ℤ), (T.move Dir.left).nth i = T.nth (i - 1)
  | ⟨_, L, _⟩, -(n + 1 : ℕ) => (ListBlank.nth_succ _ _).symm
  | ⟨_, L, _⟩, 0 => (ListBlank.nth_zero _).symm
  | ⟨a, L, R⟩, 1 => (ListBlank.nth_zero _).trans (ListBlank.head_cons _ _)
  | ⟨a, L, R⟩, (n + 1 : ℕ) + 1 => by
    rw [add_sub_cancel]
    

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
a : Γ
L R : ListBlank Γ
n : ℕ
⊢ nth (move Dir.left { head := a, left := L, right := R }) (↑(n + 1) + 1) =
    nth { head := a, left := L, right := R } ↑(n + 1)

Next tactic:
change (R.cons a).nth (n + 1) = R.nth n
@[simp]
theorem Tape.move_left_nth {Γ} [Inhabited Γ] :
    ∀ (T : Tape Γ) (i : ℤ), (T.move Dir.left).nth i = T.nth (i - 1)
  | ⟨_, L, _⟩, -(n + 1 : ℕ) => (ListBlank.nth_succ _ _).symm
  | ⟨_, L, _⟩, 0 => (ListBlank.nth_zero _).symm
  | ⟨a, L, R⟩, 1 => (ListBlank.nth_zero _).trans (ListBlank.head_cons _ _)
  | ⟨a, L, R⟩, (n + 1 : ℕ) + 1 => by
    rw [add_sub_cancel]
    change (R.cons a).nth (n + 1) = R.nth n
    

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
a : Γ
L R : ListBlank Γ
n : ℕ
⊢ ListBlank.nth (ListBlank.cons a R) (n + 1) = ListBlank.nth R n

Next tactic:
rw [ListBlank.nth_succ, ListBlank.tail_cons]
@[simp]
theorem Tape.move_right_nth {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℤ) :
    (T.move Dir.right).nth i = T.nth (i + 1) := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
i : ℤ
⊢ nth (move Dir.right T) i = nth T (i + 1)

Next tactic:
conv => rhs; rw [← T.move_right_left]
@[simp]
theorem Tape.move_right_nth {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℤ) :
    (T.move Dir.right).nth i = T.nth (i + 1) := by
  conv => 

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
i : ℤ
| nth (move Dir.right T) i = nth T (i + 1)

Next tactic:
rhs; rw [← T.move_right_left]
@[simp]
theorem Tape.move_right_nth {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℤ) :
    (T.move Dir.right).nth i = T.nth (i + 1) := by
  conv => 

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
i : ℤ
| nth (move Dir.right T) i = nth T (i + 1)

Next tactic:
rhs
@[simp]
theorem Tape.move_right_nth {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℤ) :
    (T.move Dir.right).nth i = T.nth (i + 1) := by
  conv => rhs; 

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
i : ℤ
| nth T (i + 1)

Next tactic:
rw [← T.move_right_left]
@[simp]
theorem Tape.move_right_nth {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℤ) :
    (T.move Dir.right).nth i = T.nth (i + 1) := by
  conv => rhs; rw [← T.move_right_left]
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
i : ℤ
⊢ nth (move Dir.right T) i = nth (move Dir.left (move Dir.right T)) (i + 1)

Next tactic:
rw [Tape.move_left_nth, add_sub_cancel]
@[simp]
theorem Tape.move_right_n_head {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℕ) :
    ((Tape.move Dir.right)^[i] T).head = T.nth i := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
i : ℕ
⊢ ((move Dir.right)^[i] T).head = nth T ↑i

Next tactic:
induction i generalizing T
@[simp]
theorem Tape.move_right_n_head {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℕ) :
    ((Tape.move Dir.right)^[i] T).head = T.nth i := by
  induction i generalizing T
  · 

Proof state:
case zero
Γ : Type u_1
inst✝ : Inhabited Γ
T : Tape Γ
⊢ ((move Dir.right)^[Nat.zero] T).head = nth T ↑Nat.zero

Next tactic:
rfl
@[simp]
theorem Tape.move_right_n_head {Γ} [Inhabited Γ] (T : Tape Γ) (i : ℕ) :
    ((Tape.move Dir.right)^[i] T).head = T.nth i := by
  induction i generalizing T
  · rfl
  · 

Proof state:
case succ
Γ : Type u_1
inst✝ : Inhabited Γ
n✝ : ℕ
n_ih✝ : ∀ (T : Tape Γ), ((move Dir.right)^[n✝] T).head = nth T ↑n✝
T : Tape Γ
⊢ ((move Dir.right)^[Nat.succ n✝] T).head = nth T ↑(Nat.succ n✝)

Next tactic:
simp only [*, Tape.move_right_nth, Int.ofNat_succ, iterate_succ, Function.comp_apply]
@[simp]
theorem Tape.write_self {Γ} [Inhabited Γ] : ∀ T : Tape Γ, T.write T.1 = T := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
⊢ ∀ (T : Tape Γ), write T.head T = T

Next tactic:
rintro ⟨⟩
@[simp]
theorem Tape.write_self {Γ} [Inhabited Γ] : ∀ T : Tape Γ, T.write T.1 = T := by
  rintro ⟨⟩; 

Proof state:
case mk
Γ : Type u_1
inst✝ : Inhabited Γ
head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ write { head := head✝, left := left✝, right := right✝ }.head { head := head✝, left := left✝, right := right✝ } =
    { head := head✝, left := left✝, right := right✝ }

Next tactic:
rfl
@[simp]
theorem Tape.write_mk' {Γ} [Inhabited Γ] (a b : Γ) (L R : ListBlank Γ) :
    (Tape.mk' L (R.cons a)).write b = Tape.mk' L (R.cons b) := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
a b : Γ
L R : ListBlank Γ
⊢ write b (mk' L (ListBlank.cons a R)) = mk' L (ListBlank.cons b R)

Next tactic:
simp only [Tape.write, Tape.mk', ListBlank.head_cons, ListBlank.tail_cons, eq_self_iff_true,
    and_self_iff]
@[simp]
theorem Tape.map_fst {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') :
    ∀ T : Tape Γ, (T.map f).1 = f T.1 := by
  

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
⊢ ∀ (T : Tape Γ), (map f T).head = PointedMap.f f T.head

Next tactic:
rintro ⟨⟩
@[simp]
theorem Tape.map_fst {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') :
    ∀ T : Tape Γ, (T.map f).1 = f T.1 := by
  rintro ⟨⟩; 

Proof state:
case mk
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ (map f { head := head✝, left := left✝, right := right✝ }).head =
    PointedMap.f f { head := head✝, left := left✝, right := right✝ }.head

Next tactic:
rfl
@[simp]
theorem Tape.map_write {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (b : Γ) :
    ∀ T : Tape Γ, (T.write b).map f = (T.map f).write (f b) := by
  

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
b : Γ
⊢ ∀ (T : Tape Γ), map f (write b T) = write (PointedMap.f f b) (map f T)

Next tactic:
rintro ⟨⟩
@[simp]
theorem Tape.map_write {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (b : Γ) :
    ∀ T : Tape Γ, (T.write b).map f = (T.map f).write (f b) := by
  rintro ⟨⟩; 

Proof state:
case mk
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
b head✝ : Γ
left✝ right✝ : ListBlank Γ
⊢ map f (write b { head := head✝, left := left✝, right := right✝ }) =
    write (PointedMap.f f b) (map f { head := head✝, left := left✝, right := right✝ })

Next tactic:
rfl
@[simp, nolint simpNF]
theorem Tape.write_move_right_n {Γ} [Inhabited Γ] (f : Γ → Γ) (L R : ListBlank Γ) (n : ℕ) :
    ((Tape.move Dir.right)^[n] (Tape.mk' L R)).write (f (R.nth n)) =
      (Tape.move Dir.right)^[n] (Tape.mk' L (R.modifyNth f n)) := by
  

Proof state:
Γ : Type u_1
inst✝ : Inhabited Γ
f : Γ → Γ
L R : ListBlank Γ
n : ℕ
⊢ write (f (ListBlank.nth R n)) ((move Dir.right)^[n] (mk' L R)) =
    (move Dir.right)^[n] (mk' L (ListBlank.modifyNth f n R))

Next tactic:
induction' n with n IH generalizing L R
@[simp, nolint simpNF]
theorem Tape.write_move_right_n {Γ} [Inhabited Γ] (f : Γ → Γ) (L R : ListBlank Γ) (n : ℕ) :
    ((Tape.move Dir.right)^[n] (Tape.mk' L R)).write (f (R.nth n)) =
      (Tape.move Dir.right)^[n] (Tape.mk' L (R.modifyNth f n)) := by
  induction' n with n IH generalizing L R
  · 

Proof state:
case zero
Γ : Type u_1
inst✝ : Inhabited Γ
f : Γ → Γ
L R : ListBlank Γ
⊢ write (f (ListBlank.nth R Nat.zero)) ((move Dir.right)^[Nat.zero] (mk' L R)) =
    (move Dir.right)^[Nat.zero] (mk' L (ListBlank.modifyNth f Nat.zero R))

Next tactic:
simp only [ListBlank.nth_zero, ListBlank.modifyNth, iterate_zero_apply, Nat.zero_eq]
@[simp, nolint simpNF]
theorem Tape.write_move_right_n {Γ} [Inhabited Γ] (f : Γ → Γ) (L R : ListBlank Γ) (n : ℕ) :
    ((Tape.move Dir.right)^[n] (Tape.mk' L R)).write (f (R.nth n)) =
      (Tape.move Dir.right)^[n] (Tape.mk' L (R.modifyNth f n)) := by
  induction' n with n IH generalizing L R
  · simp only [ListBlank.nth_zero, ListBlank.modifyNth, iterate_zero_apply, Nat.zero_eq]
    

Proof state:
case zero
Γ : Type u_1
inst✝ : Inhabited Γ
f : Γ → Γ
L R : ListBlank Γ
⊢ write (f (ListBlank.head R)) (mk' L R) = mk' L (ListBlank.cons (f (ListBlank.head R)) (ListBlank.tail R))

Next tactic:
rw [← Tape.write_mk', ListBlank.cons_head_tail]
@[simp, nolint simpNF]
theorem Tape.write_move_right_n {Γ} [Inhabited Γ] (f : Γ → Γ) (L R : ListBlank Γ) (n : ℕ) :
    ((Tape.move Dir.right)^[n] (Tape.mk' L R)).write (f (R.nth n)) =
      (Tape.move Dir.right)^[n] (Tape.mk' L (R.modifyNth f n)) := by
  induction' n with n IH generalizing L R
  · simp only [ListBlank.nth_zero, ListBlank.modifyNth, iterate_zero_apply, Nat.zero_eq]
    rw [← Tape.write_mk', ListBlank.cons_head_tail]
  

Proof state:
case succ
Γ : Type u_1
inst✝ : Inhabited Γ
f : Γ → Γ
n : ℕ
IH :
  ∀ (L R : ListBlank Γ),
    write (f (ListBlank.nth R n)) ((move Dir.right)^[n] (mk' L R)) =
      (move Dir.right)^[n] (mk' L (ListBlank.modifyNth f n R))
L R : ListBlank Γ
⊢ write (f (ListBlank.nth R (Nat.succ n))) ((move Dir.right)^[Nat.succ n] (mk' L R)) =
    (move Dir.right)^[Nat.succ n] (mk' L (ListBlank.modifyNth f (Nat.succ n) R))

Next tactic:
simp only [ListBlank.head_cons, ListBlank.nth_succ, ListBlank.modifyNth, Tape.move_right_mk',
    ListBlank.tail_cons, iterate_succ_apply, IH]
theorem Tape.map_move {Γ Γ'} [Inhabited Γ] [Inhabited Γ'] (f : PointedMap Γ Γ') (T : Tape Γ) (d) :
    (T.move d).map f = (T.map f).move d := by
  

Proof state:
Γ : Type u_1
Γ' : Type u_2
inst✝¹ : Inhabited Γ
inst✝ : Inhabited Γ'
f : PointedMap Γ Γ'
T : Tape Γ
d : Dir
⊢ map f (move d T) = move d (map f T)

Next tactic:
cases T