l3lab/ntp-mathlib huggingface dataset:
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · 

Proof state:
case mp.h₁
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hy : y ∈ cylinder x n
⊢ cylinder y n ⊆ cylinder x n

Next tactic:
intro z hz i hi
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · intro z hz i hi
      

Proof state:
case mp.h₁
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hy : y ∈ cylinder x n
z : (n : ℕ) → E n
hz : z ∈ cylinder y n
i : ℕ
hi : i < n
⊢ z i = x i

Next tactic:
rw [← hy i hi]
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · intro z hz i hi
      rw [← hy i hi]
      

Proof state:
case mp.h₁
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hy : y ∈ cylinder x n
z : (n : ℕ) → E n
hz : z ∈ cylinder y n
i : ℕ
hi : i < n
⊢ z i = y i

Next tactic:
exact hz i hi
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · intro z hz i hi
      rw [← hy i hi]
      exact hz i hi
    · 

Proof state:
case mp.h₂
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hy : y ∈ cylinder x n
⊢ cylinder x n ⊆ cylinder y n

Next tactic:
intro z hz i hi
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · intro z hz i hi
      rw [← hy i hi]
      exact hz i hi
    · intro z hz i hi
      

Proof state:
case mp.h₂
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hy : y ∈ cylinder x n
z : (n : ℕ) → E n
hz : z ∈ cylinder x n
i : ℕ
hi : i < n
⊢ z i = y i

Next tactic:
rw [hy i hi]
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · intro z hz i hi
      rw [← hy i hi]
      exact hz i hi
    · intro z hz i hi
      rw [hy i hi]
      

Proof state:
case mp.h₂
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hy : y ∈ cylinder x n
z : (n : ℕ) → E n
hz : z ∈ cylinder x n
i : ℕ
hi : i < n
⊢ z i = x i

Next tactic:
exact hz i hi
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · intro z hz i hi
      rw [← hy i hi]
      exact hz i hi
    · intro z hz i hi
      rw [hy i hi]
      exact hz i hi
  · 

Proof state:
case mpr
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
⊢ cylinder y n = cylinder x n → y ∈ cylinder x n

Next tactic:
intro h
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · intro z hz i hi
      rw [← hy i hi]
      exact hz i hi
    · intro z hz i hi
      rw [hy i hi]
      exact hz i hi
  · intro h
    

Proof state:
case mpr
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
h : cylinder y n = cylinder x n
⊢ y ∈ cylinder x n

Next tactic:
rw [← h]
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    apply Subset.antisymm
    · intro z hz i hi
      rw [← hy i hi]
      exact hz i hi
    · intro z hz i hi
      rw [hy i hi]
      exact hz i hi
  · intro h
    rw [← h]
    

Proof state:
case mpr
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
h : cylinder y n = cylinder x n
⊢ y ∈ cylinder y n

Next tactic:
exact self_mem_cylinder _ _
theorem mem_cylinder_comm (x y : ∀ n, E n) (n : ℕ) : y ∈ cylinder x n ↔ x ∈ cylinder y n := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
⊢ y ∈ cylinder x n ↔ x ∈ cylinder y n

Next tactic:
simp [mem_cylinder_iff_eq, eq_comm]
theorem mem_cylinder_iff_le_firstDiff {x y : ∀ n, E n} (hne : x ≠ y) (i : ℕ) :
    x ∈ cylinder y i ↔ i ≤ firstDiff x y := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
hne : x ≠ y
i : ℕ
⊢ x ∈ cylinder y i ↔ i ≤ firstDiff x y

Next tactic:
constructor
theorem mem_cylinder_iff_le_firstDiff {x y : ∀ n, E n} (hne : x ≠ y) (i : ℕ) :
    x ∈ cylinder y i ↔ i ≤ firstDiff x y := by
  constructor
  · 

Proof state:
case mp
E : ℕ → Type u_1
x y : (n : ℕ) → E n
hne : x ≠ y
i : ℕ
⊢ x ∈ cylinder y i → i ≤ firstDiff x y

Next tactic:
intro h
theorem mem_cylinder_iff_le_firstDiff {x y : ∀ n, E n} (hne : x ≠ y) (i : ℕ) :
    x ∈ cylinder y i ↔ i ≤ firstDiff x y := by
  constructor
  · intro h
    

Proof state:
case mp
E : ℕ → Type u_1
x y : (n : ℕ) → E n
hne : x ≠ y
i : ℕ
h : x ∈ cylinder y i
⊢ i ≤ firstDiff x y

Next tactic:
by_contra!
theorem mem_cylinder_iff_le_firstDiff {x y : ∀ n, E n} (hne : x ≠ y) (i : ℕ) :
    x ∈ cylinder y i ↔ i ≤ firstDiff x y := by
  constructor
  · intro h
    by_contra!
    

Proof state:
case mp
E : ℕ → Type u_1
x y : (n : ℕ) → E n
hne : x ≠ y
i : ℕ
h : x ∈ cylinder y i
this : firstDiff x y < i
⊢ False

Next tactic:
exact apply_firstDiff_ne hne (h _ this)
theorem mem_cylinder_iff_le_firstDiff {x y : ∀ n, E n} (hne : x ≠ y) (i : ℕ) :
    x ∈ cylinder y i ↔ i ≤ firstDiff x y := by
  constructor
  · intro h
    by_contra!
    exact apply_firstDiff_ne hne (h _ this)
  · 

Proof state:
case mpr
E : ℕ → Type u_1
x y : (n : ℕ) → E n
hne : x ≠ y
i : ℕ
⊢ i ≤ firstDiff x y → x ∈ cylinder y i

Next tactic:
intro hi j hj
theorem mem_cylinder_iff_le_firstDiff {x y : ∀ n, E n} (hne : x ≠ y) (i : ℕ) :
    x ∈ cylinder y i ↔ i ≤ firstDiff x y := by
  constructor
  · intro h
    by_contra!
    exact apply_firstDiff_ne hne (h _ this)
  · intro hi j hj
    

Proof state:
case mpr
E : ℕ → Type u_1
x y : (n : ℕ) → E n
hne : x ≠ y
i : ℕ
hi : i ≤ firstDiff x y
j : ℕ
hj : j < i
⊢ x j = y j

Next tactic:
exact apply_eq_of_lt_firstDiff (hj.trans_le hi)
theorem cylinder_eq_cylinder_of_le_firstDiff (x y : ∀ n, E n) {n : ℕ} (hn : n ≤ firstDiff x y) :
    cylinder x n = cylinder y n := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hn : n ≤ firstDiff x y
⊢ cylinder x n = cylinder y n

Next tactic:
rw [← mem_cylinder_iff_eq]
theorem cylinder_eq_cylinder_of_le_firstDiff (x y : ∀ n, E n) {n : ℕ} (hn : n ≤ firstDiff x y) :
    cylinder x n = cylinder y n := by
  rw [← mem_cylinder_iff_eq]
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hn : n ≤ firstDiff x y
⊢ x ∈ cylinder y n

Next tactic:
intro i hi
theorem cylinder_eq_cylinder_of_le_firstDiff (x y : ∀ n, E n) {n : ℕ} (hn : n ≤ firstDiff x y) :
    cylinder x n = cylinder y n := by
  rw [← mem_cylinder_iff_eq]
  intro i hi
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hn : n ≤ firstDiff x y
i : ℕ
hi : i < n
⊢ x i = y i

Next tactic:
exact apply_eq_of_lt_firstDiff (hi.trans_le hn)
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  

Proof state:
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
⊢ ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n

Next tactic:
ext y
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  

Proof state:
case h
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
⊢ y ∈ ⋃ k, cylinder (update x n k) (n + 1) ↔ y ∈ cylinder x n

Next tactic:
simp only [mem_cylinder_iff, mem_iUnion]
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  simp only [mem_cylinder_iff, mem_iUnion]
  

Proof state:
case h
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
⊢ (∃ i, ∀ i_1 < n + 1, y i_1 = update x n i i_1) ↔ ∀ i < n, y i = x i

Next tactic:
constructor
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  simp only [mem_cylinder_iff, mem_iUnion]
  constructor
  · 

Proof state:
case h.mp
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
⊢ (∃ i, ∀ i_1 < n + 1, y i_1 = update x n i i_1) → ∀ i < n, y i = x i

Next tactic:
rintro ⟨k, hk⟩ i hi
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  simp only [mem_cylinder_iff, mem_iUnion]
  constructor
  · rintro ⟨k, hk⟩ i hi
    

Proof state:
case h.mp.intro
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
k : E n
hk : ∀ i < n + 1, y i = update x n k i
i : ℕ
hi : i < n
⊢ y i = x i

Next tactic:
simpa [hi.ne] using hk i (Nat.lt_succ_of_lt hi)
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  simp only [mem_cylinder_iff, mem_iUnion]
  constructor
  · rintro ⟨k, hk⟩ i hi
    simpa [hi.ne] using hk i (Nat.lt_succ_of_lt hi)
  · 

Proof state:
case h.mpr
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
⊢ (∀ i < n, y i = x i) → ∃ i, ∀ i_1 < n + 1, y i_1 = update x n i i_1

Next tactic:
intro H
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  simp only [mem_cylinder_iff, mem_iUnion]
  constructor
  · rintro ⟨k, hk⟩ i hi
    simpa [hi.ne] using hk i (Nat.lt_succ_of_lt hi)
  · intro H
    

Proof state:
case h.mpr
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
H : ∀ i < n, y i = x i
⊢ ∃ i, ∀ i_1 < n + 1, y i_1 = update x n i i_1

Next tactic:
refine' ⟨y n, fun i hi => _⟩
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  simp only [mem_cylinder_iff, mem_iUnion]
  constructor
  · rintro ⟨k, hk⟩ i hi
    simpa [hi.ne] using hk i (Nat.lt_succ_of_lt hi)
  · intro H
    refine' ⟨y n, fun i hi => _⟩
    

Proof state:
case h.mpr
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
H : ∀ i < n, y i = x i
i : ℕ
hi : i < n + 1
⊢ y i = update x n (y n) i

Next tactic:
rcases Nat.lt_succ_iff_lt_or_eq.1 hi with (h'i | rfl)
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  simp only [mem_cylinder_iff, mem_iUnion]
  constructor
  · rintro ⟨k, hk⟩ i hi
    simpa [hi.ne] using hk i (Nat.lt_succ_of_lt hi)
  · intro H
    refine' ⟨y n, fun i hi => _⟩
    rcases Nat.lt_succ_iff_lt_or_eq.1 hi with (h'i | rfl)
    · 

Proof state:
case h.mpr.inl
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
H : ∀ i < n, y i = x i
i : ℕ
hi : i < n + 1
h'i : i < n
⊢ y i = update x n (y n) i

Next tactic:
simp [H i h'i, h'i.ne]
theorem iUnion_cylinder_update (x : ∀ n, E n) (n : ℕ) :
    ⋃ k, cylinder (update x n k) (n + 1) = cylinder x n := by
  ext y
  simp only [mem_cylinder_iff, mem_iUnion]
  constructor
  · rintro ⟨k, hk⟩ i hi
    simpa [hi.ne] using hk i (Nat.lt_succ_of_lt hi)
  · intro H
    refine' ⟨y n, fun i hi => _⟩
    rcases Nat.lt_succ_iff_lt_or_eq.1 hi with (h'i | rfl)
    · simp [H i h'i, h'i.ne]
    · 

Proof state:
case h.mpr.inr
E : ℕ → Type u_1
x y : (n : ℕ) → E n
i : ℕ
H : ∀ i_1 < i, y i_1 = x i_1
hi : i < i + 1
⊢ y i = update x i (y i) i

Next tactic:
simp
theorem update_mem_cylinder (x : ∀ n, E n) (n : ℕ) (y : E n) : update x n y ∈ cylinder x n :=
  mem_cylinder_iff.2 fun i hi => by 

Proof state:
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : E n
i : ℕ
hi : i < n
⊢ update x n y i = x i

Next tactic:
simp [hi.ne]
@[simp]
theorem res_length (x : ℕ → α) (n : ℕ) : (res x n).length = n := by 

Proof state:
E : ℕ → Type u_1
α : Type u_2
x : ℕ → α
n : ℕ
⊢ length (res x n) = n

Next tactic:
induction n
@[simp]
theorem res_length (x : ℕ → α) (n : ℕ) : (res x n).length = n := by induction n <;> 

Proof state:
case zero
E : ℕ → Type u_1
α : Type u_2
x : ℕ → α
⊢ length (res x Nat.zero) = Nat.zero

Next tactic:
simp [*]
@[simp]
theorem res_length (x : ℕ → α) (n : ℕ) : (res x n).length = n := by induction n <;> 

Proof state:
case succ
E : ℕ → Type u_1
α : Type u_2
x : ℕ → α
n✝ : ℕ
n_ih✝ : length (res x n✝) = n✝
⊢ length (res x (Nat.succ n✝)) = Nat.succ n✝

Next tactic:
simp [*]
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  

Proof state:
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
⊢ res x n = res y n ↔ ∀ ⦃m : ℕ⦄, m < n → x m = y m

Next tactic:
constructor
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> 

Proof state:
case mp
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
⊢ res x n = res y n → ∀ ⦃m : ℕ⦄, m < n → x m = y m

Next tactic:
intro h
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> 

Proof state:
case mpr
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
⊢ (∀ ⦃m : ℕ⦄, m < n → x m = y m) → res x n = res y n

Next tactic:
intro h
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> 

Proof state:
case mp
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
h : res x n = res y n
⊢ ∀ ⦃m : ℕ⦄, m < n → x m = y m

Next tactic:
induction' n with n ih
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> 

Proof state:
case mpr
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
h : ∀ ⦃m : ℕ⦄, m < n → x m = y m
⊢ res x n = res y n

Next tactic:
induction' n with n ih
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · 

Proof state:
case mp.zero
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
h : res x Nat.zero = res y Nat.zero
⊢ ∀ ⦃m : ℕ⦄, m < Nat.zero → x m = y m

Next tactic:
simp
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · 

Proof state:
case mp.succ
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : res x n = res y n → ∀ ⦃m : ℕ⦄, m < n → x m = y m
h : res x (Nat.succ n) = res y (Nat.succ n)
⊢ ∀ ⦃m : ℕ⦄, m < Nat.succ n → x m = y m

Next tactic:
intro m hm
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    

Proof state:
case mp.succ
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : res x n = res y n → ∀ ⦃m : ℕ⦄, m < n → x m = y m
h : res x (Nat.succ n) = res y (Nat.succ n)
m : ℕ
hm : m < Nat.succ n
⊢ x m = y m

Next tactic:
rw [Nat.lt_succ_iff_lt_or_eq] at hm
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    

Proof state:
case mp.succ
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : res x n = res y n → ∀ ⦃m : ℕ⦄, m < n → x m = y m
h : res x (Nat.succ n) = res y (Nat.succ n)
m : ℕ
hm : m < n ∨ m = n
⊢ x m = y m

Next tactic:
simp only [res_succ, cons.injEq] at h
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    simp only [res_succ, cons.injEq] at h
    

Proof state:
case mp.succ
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : res x n = res y n → ∀ ⦃m : ℕ⦄, m < n → x m = y m
m : ℕ
hm : m < n ∨ m = n
h : x n = y n ∧ res x n = res y n
⊢ x m = y m

Next tactic:
cases' hm with hm hm
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    simp only [res_succ, cons.injEq] at h
    cases' hm with hm hm
    · 

Proof state:
case mp.succ.inl
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : res x n = res y n → ∀ ⦃m : ℕ⦄, m < n → x m = y m
m : ℕ
h : x n = y n ∧ res x n = res y n
hm : m < n
⊢ x m = y m

Next tactic:
exact ih h.2 hm
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    simp only [res_succ, cons.injEq] at h
    cases' hm with hm hm
    · exact ih h.2 hm
    

Proof state:
case mp.succ.inr
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : res x n = res y n → ∀ ⦃m : ℕ⦄, m < n → x m = y m
m : ℕ
h : x n = y n ∧ res x n = res y n
hm : m = n
⊢ x m = y m

Next tactic:
rw [hm]
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    simp only [res_succ, cons.injEq] at h
    cases' hm with hm hm
    · exact ih h.2 hm
    rw [hm]
    

Proof state:
case mp.succ.inr
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : res x n = res y n → ∀ ⦃m : ℕ⦄, m < n → x m = y m
m : ℕ
h : x n = y n ∧ res x n = res y n
hm : m = n
⊢ x n = y n

Next tactic:
exact h.1
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    simp only [res_succ, cons.injEq] at h
    cases' hm with hm hm
    · exact ih h.2 hm
    rw [hm]
    exact h.1
  · 

Proof state:
case mpr.zero
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
h : ∀ ⦃m : ℕ⦄, m < Nat.zero → x m = y m
⊢ res x Nat.zero = res y Nat.zero

Next tactic:
simp
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    simp only [res_succ, cons.injEq] at h
    cases' hm with hm hm
    · exact ih h.2 hm
    rw [hm]
    exact h.1
  · simp
  

Proof state:
case mpr.succ
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : (∀ ⦃m : ℕ⦄, m < n → x m = y m) → res x n = res y n
h : ∀ ⦃m : ℕ⦄, m < Nat.succ n → x m = y m
⊢ res x (Nat.succ n) = res y (Nat.succ n)

Next tactic:
simp only [res_succ, cons.injEq]
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    simp only [res_succ, cons.injEq] at h
    cases' hm with hm hm
    · exact ih h.2 hm
    rw [hm]
    exact h.1
  · simp
  simp only [res_succ, cons.injEq]
  

Proof state:
case mpr.succ
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : (∀ ⦃m : ℕ⦄, m < n → x m = y m) → res x n = res y n
h : ∀ ⦃m : ℕ⦄, m < Nat.succ n → x m = y m
⊢ x n = y n ∧ res x n = res y n

Next tactic:
refine' ⟨h (Nat.lt_succ_self _), ih fun m hm => _⟩
/-- The restrictions of `x` and `y` to `n` are equal if and only if `x m = y m` for all `m < n`.-/
theorem res_eq_res {x y : ℕ → α} {n : ℕ} :
    res x n = res y n ↔ ∀ ⦃m⦄, m < n → x m = y m := by
  constructor <;> intro h <;> induction' n with n ih; · simp
  · intro m hm
    rw [Nat.lt_succ_iff_lt_or_eq] at hm
    simp only [res_succ, cons.injEq] at h
    cases' hm with hm hm
    · exact ih h.2 hm
    rw [hm]
    exact h.1
  · simp
  simp only [res_succ, cons.injEq]
  refine' ⟨h (Nat.lt_succ_self _), ih fun m hm => _⟩
  

Proof state:
case mpr.succ
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
n : ℕ
ih : (∀ ⦃m : ℕ⦄, m < n → x m = y m) → res x n = res y n
h : ∀ ⦃m : ℕ⦄, m < Nat.succ n → x m = y m
m : ℕ
hm : m < n
⊢ x m = y m

Next tactic:
exact h (hm.trans (Nat.lt_succ_self _))
theorem res_injective : Injective (@res α) := by
  

Proof state:
E : ℕ → Type u_1
α : Type u_2
⊢ Injective res

Next tactic:
intro x y h
theorem res_injective : Injective (@res α) := by
  intro x y h
  

Proof state:
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
h : res x = res y
⊢ x = y

Next tactic:
ext n
theorem res_injective : Injective (@res α) := by
  intro x y h
  ext n
  

Proof state:
case h
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
h : res x = res y
n : ℕ
⊢ x n = y n

Next tactic:
apply res_eq_res.mp _ (Nat.lt_succ_self _)
theorem res_injective : Injective (@res α) := by
  intro x y h
  ext n
  apply res_eq_res.mp _ (Nat.lt_succ_self _)
  

Proof state:
E : ℕ → Type u_1
α : Type u_2
x y : ℕ → α
h : res x = res y
n : ℕ
⊢ res x (Nat.succ n) = res (fun n => y n) (Nat.succ n)

Next tactic:
rw [h]
/-- `cylinder x n` is equal to the set of sequences `y` with the same restriction to `n` as `x`.-/
theorem cylinder_eq_res (x : ℕ → α) (n : ℕ) :
    cylinder x n = { y | res y n = res x n } := by
  

Proof state:
E : ℕ → Type u_1
α : Type u_2
x : ℕ → α
n : ℕ
⊢ cylinder x n = {y | res y n = res x n}

Next tactic:
ext y
/-- `cylinder x n` is equal to the set of sequences `y` with the same restriction to `n` as `x`.-/
theorem cylinder_eq_res (x : ℕ → α) (n : ℕ) :
    cylinder x n = { y | res y n = res x n } := by
  ext y
  

Proof state:
case h
E : ℕ → Type u_1
α : Type u_2
x : ℕ → α
n : ℕ
y : ℕ → α
⊢ y ∈ cylinder x n ↔ y ∈ {y | res y n = res x n}

Next tactic:
dsimp [cylinder]
/-- `cylinder x n` is equal to the set of sequences `y` with the same restriction to `n` as `x`.-/
theorem cylinder_eq_res (x : ℕ → α) (n : ℕ) :
    cylinder x n = { y | res y n = res x n } := by
  ext y
  dsimp [cylinder]
  

Proof state:
case h
E : ℕ → Type u_1
α : Type u_2
x : ℕ → α
n : ℕ
y : ℕ → α
⊢ (∀ i < n, y i = x i) ↔ res y n = res x n

Next tactic:
rw [res_eq_res]
theorem dist_eq_of_ne {x y : ∀ n, E n} (h : x ≠ y) : dist x y = (1 / 2 : ℝ) ^ firstDiff x y := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
h : x ≠ y
⊢ dist x y = (1 / 2) ^ firstDiff x y

Next tactic:
simp [dist, h]
protected theorem dist_self (x : ∀ n, E n) : dist x x = 0 := by 

Proof state:
E : ℕ → Type u_1
x : (n : ℕ) → E n
⊢ dist x x = 0

Next tactic:
simp [dist]
protected theorem dist_comm (x y : ∀ n, E n) : dist x y = dist y x := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
⊢ dist x y = dist y x

Next tactic:
simp [dist, @eq_comm _ x y, firstDiff_comm]
protected theorem dist_nonneg (x y : ∀ n, E n) : 0 ≤ dist x y := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
⊢ 0 ≤ dist x y

Next tactic:
rcases eq_or_ne x y with (rfl | h)
protected theorem dist_nonneg (x y : ∀ n, E n) : 0 ≤ dist x y := by
  rcases eq_or_ne x y with (rfl | h)
  · 

Proof state:
case inl
E : ℕ → Type u_1
x : (n : ℕ) → E n
⊢ 0 ≤ dist x x

Next tactic:
simp [dist]
protected theorem dist_nonneg (x y : ∀ n, E n) : 0 ≤ dist x y := by
  rcases eq_or_ne x y with (rfl | h)
  · simp [dist]
  · 

Proof state:
case inr
E : ℕ → Type u_1
x y : (n : ℕ) → E n
h : x ≠ y
⊢ 0 ≤ dist x y

Next tactic:
simp [dist, h, zero_le_two]