l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem finSuccEquiv'_at (i : Fin (n + 1)) : (finSuccEquiv' i) i = none := by
  

Proof state:
m n : ℕ
i : Fin (n + 1)
⊢ (finSuccEquiv' i) i = none

Next tactic:
simp [finSuccEquiv']
theorem finSuccEquiv'_below {i : Fin (n + 1)} {m : Fin n} (h : Fin.castSucc m < i) :
    (finSuccEquiv' i) (Fin.castSucc m) = m := by
  

Proof state:
m✝ n : ℕ
i : Fin (n + 1)
m : Fin n
h : Fin.castSucc m < i
⊢ (finSuccEquiv' i) (Fin.castSucc m) = some m

Next tactic:
rw [← Fin.succAbove_below _ _ h, finSuccEquiv'_succAbove]
theorem finSuccEquiv'_above {i : Fin (n + 1)} {m : Fin n} (h : i ≤ Fin.castSucc m) :
    (finSuccEquiv' i) m.succ = some m := by
  

Proof state:
m✝ n : ℕ
i : Fin (n + 1)
m : Fin n
h : i ≤ Fin.castSucc m
⊢ (finSuccEquiv' i) (Fin.succ m) = some m

Next tactic:
rw [← Fin.succAbove_above _ _ h, finSuccEquiv'_succAbove]
theorem finSuccEquiv'_last_apply_castSucc (i : Fin n) :
    finSuccEquiv' (Fin.last n) (Fin.castSucc i) = i := by
  

Proof state:
m n : ℕ
i : Fin n
⊢ (finSuccEquiv' (Fin.last n)) (Fin.castSucc i) = some i

Next tactic:
rw [← Fin.succAbove_last, finSuccEquiv'_succAbove]
theorem finSuccEquiv'_last_apply {i : Fin (n + 1)} (h : i ≠ Fin.last n) :
    finSuccEquiv' (Fin.last n) i = Fin.castLT i (Fin.val_lt_last h) := by
  

Proof state:
m n : ℕ
i : Fin (n + 1)
h : i ≠ Fin.last n
⊢ (finSuccEquiv' (Fin.last n)) i = some (Fin.castLT i (_ : ↑i < n))

Next tactic:
rcases Fin.exists_castSucc_eq.2 h with ⟨i, rfl⟩
theorem finSuccEquiv'_last_apply {i : Fin (n + 1)} (h : i ≠ Fin.last n) :
    finSuccEquiv' (Fin.last n) i = Fin.castLT i (Fin.val_lt_last h) := by
  rcases Fin.exists_castSucc_eq.2 h with ⟨i, rfl⟩
  

Proof state:
case intro
m n : ℕ
i : Fin n
h : Fin.castSucc i ≠ Fin.last n
⊢ (finSuccEquiv' (Fin.last n)) (Fin.castSucc i) = some (Fin.castLT (Fin.castSucc i) (_ : ↑(Fin.castSucc i) < n))

Next tactic:
rw [finSuccEquiv'_last_apply_castSucc]
theorem finSuccEquiv'_last_apply {i : Fin (n + 1)} (h : i ≠ Fin.last n) :
    finSuccEquiv' (Fin.last n) i = Fin.castLT i (Fin.val_lt_last h) := by
  rcases Fin.exists_castSucc_eq.2 h with ⟨i, rfl⟩
  rw [finSuccEquiv'_last_apply_castSucc]
  

Proof state:
case intro
m n : ℕ
i : Fin n
h : Fin.castSucc i ≠ Fin.last n
⊢ some i = some (Fin.castLT (Fin.castSucc i) (_ : ↑(Fin.castSucc i) < n))

Next tactic:
rfl
theorem finSuccEquiv'_ne_last_apply {i j : Fin (n + 1)} (hi : i ≠ Fin.last n) (hj : j ≠ i) :
    finSuccEquiv' i j = (i.castLT (Fin.val_lt_last hi)).predAbove j := by
  

Proof state:
m n : ℕ
i j : Fin (n + 1)
hi : i ≠ Fin.last n
hj : j ≠ i
⊢ (finSuccEquiv' i) j = some (Fin.predAbove (Fin.castLT i (_ : ↑i < n)) j)

Next tactic:
rcases Fin.exists_succAbove_eq hj with ⟨j, rfl⟩
theorem finSuccEquiv'_ne_last_apply {i j : Fin (n + 1)} (hi : i ≠ Fin.last n) (hj : j ≠ i) :
    finSuccEquiv' i j = (i.castLT (Fin.val_lt_last hi)).predAbove j := by
  rcases Fin.exists_succAbove_eq hj with ⟨j, rfl⟩
  

Proof state:
case intro
m n : ℕ
i : Fin (n + 1)
hi : i ≠ Fin.last n
j : Fin n
hj : Fin.succAbove i j ≠ i
⊢ (finSuccEquiv' i) (Fin.succAbove i j) = some (Fin.predAbove (Fin.castLT i (_ : ↑i < n)) (Fin.succAbove i j))

Next tactic:
rcases Fin.exists_castSucc_eq.2 hi with ⟨i, rfl⟩
theorem finSuccEquiv'_ne_last_apply {i j : Fin (n + 1)} (hi : i ≠ Fin.last n) (hj : j ≠ i) :
    finSuccEquiv' i j = (i.castLT (Fin.val_lt_last hi)).predAbove j := by
  rcases Fin.exists_succAbove_eq hj with ⟨j, rfl⟩
  rcases Fin.exists_castSucc_eq.2 hi with ⟨i, rfl⟩
  

Proof state:
case intro.intro
m n : ℕ
j i : Fin n
hi : Fin.castSucc i ≠ Fin.last n
hj : Fin.succAbove (Fin.castSucc i) j ≠ Fin.castSucc i
⊢ (finSuccEquiv' (Fin.castSucc i)) (Fin.succAbove (Fin.castSucc i) j) =
    some (Fin.predAbove (Fin.castLT (Fin.castSucc i) (_ : ↑(Fin.castSucc i) < n)) (Fin.succAbove (Fin.castSucc i) j))

Next tactic:
simp
theorem finSuccAboveEquiv_symm_apply_last (x : { x : Fin (n + 1) // x ≠ Fin.last n }) :
    (finSuccAboveEquiv (Fin.last n)).symm x = Fin.castLT x.1 (Fin.val_lt_last x.2) := by
  

Proof state:
m n : ℕ
x : { x // x ≠ Fin.last n }
⊢ (OrderIso.symm (finSuccAboveEquiv (Fin.last n))) x = Fin.castLT ↑x (_ : ↑↑x < n)

Next tactic:
rw [← Option.some_inj]
theorem finSuccAboveEquiv_symm_apply_last (x : { x : Fin (n + 1) // x ≠ Fin.last n }) :
    (finSuccAboveEquiv (Fin.last n)).symm x = Fin.castLT x.1 (Fin.val_lt_last x.2) := by
  rw [← Option.some_inj]
  

Proof state:
m n : ℕ
x : { x // x ≠ Fin.last n }
⊢ some ((OrderIso.symm (finSuccAboveEquiv (Fin.last n))) x) = some (Fin.castLT ↑x (_ : ↑↑x < n))

Next tactic:
simpa [finSuccAboveEquiv, OrderIso.symm] using finSuccEquiv'_last_apply x.property
theorem finSuccAboveEquiv_symm_apply_ne_last {p : Fin (n + 1)} (h : p ≠ Fin.last n)
    (x : { x : Fin (n + 1) // x ≠ p }) :
    (finSuccAboveEquiv p).symm x = (p.castLT (Fin.val_lt_last h)).predAbove x := by
  

Proof state:
m n : ℕ
p : Fin (n + 1)
h : p ≠ Fin.last n
x : { x // x ≠ p }
⊢ (OrderIso.symm (finSuccAboveEquiv p)) x = Fin.predAbove (Fin.castLT p (_ : ↑p < n)) ↑x

Next tactic:
rw [← Option.some_inj]
theorem finSuccAboveEquiv_symm_apply_ne_last {p : Fin (n + 1)} (h : p ≠ Fin.last n)
    (x : { x : Fin (n + 1) // x ≠ p }) :
    (finSuccAboveEquiv p).symm x = (p.castLT (Fin.val_lt_last h)).predAbove x := by
  rw [← Option.some_inj]
  

Proof state:
m n : ℕ
p : Fin (n + 1)
h : p ≠ Fin.last n
x : { x // x ≠ p }
⊢ some ((OrderIso.symm (finSuccAboveEquiv p)) x) = some (Fin.predAbove (Fin.castLT p (_ : ↑p < n)) ↑x)

Next tactic:
simpa [finSuccAboveEquiv, OrderIso.symm] using finSuccEquiv'_ne_last_apply h x.property
@[simp]
theorem finSuccEquivLast_last : finSuccEquivLast (Fin.last n) = none := by
  

Proof state:
m n : ℕ
⊢ finSuccEquivLast (Fin.last n) = none

Next tactic:
simp [finSuccEquivLast]
/-- Equivalence between `Π j : Fin (n + 1), α j` and `α i × Π j : Fin n, α (Fin.succAbove i j)`. -/
@[simps (config := .asFn)]
def Equiv.piFinSuccAbove (α : Fin (n + 1) → Type u) (i : Fin (n + 1)) :
    (∀ j, α j) ≃ α i × ∀ j, α (i.succAbove j) where
  toFun f := (f i, fun j => f (i.succAbove j))
  invFun f := i.insertNth f.1 f.2
  left_inv f := by 

Proof state:
m n : ℕ
α : Fin (n + 1) → Type u
i : Fin (n + 1)
f : (j : Fin (n + 1)) → α j
⊢ (fun f => Fin.insertNth i f.1 f.2) ((fun f => (f i, fun j => f (Fin.succAbove i j))) f) = f

Next tactic:
simp [Fin.insertNth_eq_iff]
/-- Equivalence between `Π j : Fin (n + 1), α j` and `α i × Π j : Fin n, α (Fin.succAbove i j)`. -/
@[simps (config := .asFn)]
def Equiv.piFinSuccAbove (α : Fin (n + 1) → Type u) (i : Fin (n + 1)) :
    (∀ j, α j) ≃ α i × ∀ j, α (i.succAbove j) where
  toFun f := (f i, fun j => f (i.succAbove j))
  invFun f := i.insertNth f.1 f.2
  left_inv f := by simp [Fin.insertNth_eq_iff]
  right_inv f := by 

Proof state:
m n : ℕ
α : Fin (n + 1) → Type u
i : Fin (n + 1)
f : α i × ((j : Fin n) → α (Fin.succAbove i j))
⊢ (fun f => (f i, fun j => f (Fin.succAbove i j))) ((fun f => Fin.insertNth i f.1 f.2) f) = f

Next tactic:
simp
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : Sum (Fin m) (Fin n) ≃ Fin (m + n)
    where
  toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
  invFun i := @Fin.addCases m n (fun _ => Sum (Fin m) (Fin n)) Sum.inl Sum.inr i
  left_inv x := by 

Proof state:
m n : ℕ
x : Fin m ⊕ Fin n
⊢ (fun i => Fin.addCases Sum.inl Sum.inr i) (Sum.elim (Fin.castAdd n) (Fin.natAdd m) x) = x

Next tactic:
cases' x with y y
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : Sum (Fin m) (Fin n) ≃ Fin (m + n)
    where
  toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
  invFun i := @Fin.addCases m n (fun _ => Sum (Fin m) (Fin n)) Sum.inl Sum.inr i
  left_inv x := by cases' x with y y <;> 

Proof state:
case inl
m n : ℕ
y : Fin m
⊢ (fun i => Fin.addCases Sum.inl Sum.inr i) (Sum.elim (Fin.castAdd n) (Fin.natAdd m) (Sum.inl y)) = Sum.inl y

Next tactic:
dsimp
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : Sum (Fin m) (Fin n) ≃ Fin (m + n)
    where
  toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
  invFun i := @Fin.addCases m n (fun _ => Sum (Fin m) (Fin n)) Sum.inl Sum.inr i
  left_inv x := by cases' x with y y <;> 

Proof state:
case inr
m n : ℕ
y : Fin n
⊢ (fun i => Fin.addCases Sum.inl Sum.inr i) (Sum.elim (Fin.castAdd n) (Fin.natAdd m) (Sum.inr y)) = Sum.inr y

Next tactic:
dsimp
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : Sum (Fin m) (Fin n) ≃ Fin (m + n)
    where
  toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
  invFun i := @Fin.addCases m n (fun _ => Sum (Fin m) (Fin n)) Sum.inl Sum.inr i
  left_inv x := by cases' x with y y <;> dsimp <;> 

Proof state:
case inl
m n : ℕ
y : Fin m
⊢ Fin.addCases Sum.inl Sum.inr (Fin.castAdd n y) = Sum.inl y

Next tactic:
simp
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : Sum (Fin m) (Fin n) ≃ Fin (m + n)
    where
  toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
  invFun i := @Fin.addCases m n (fun _ => Sum (Fin m) (Fin n)) Sum.inl Sum.inr i
  left_inv x := by cases' x with y y <;> dsimp <;> 

Proof state:
case inr
m n : ℕ
y : Fin n
⊢ Fin.addCases Sum.inl Sum.inr (Fin.natAdd m y) = Sum.inr y

Next tactic:
simp
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : Sum (Fin m) (Fin n) ≃ Fin (m + n)
    where
  toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
  invFun i := @Fin.addCases m n (fun _ => Sum (Fin m) (Fin n)) Sum.inl Sum.inr i
  left_inv x := by cases' x with y y <;> dsimp <;> simp
  right_inv x := by 

Proof state:
m n : ℕ
x : Fin (m + n)
⊢ Sum.elim (Fin.castAdd n) (Fin.natAdd m) ((fun i => Fin.addCases Sum.inl Sum.inr i) x) = x

Next tactic:
refine' Fin.addCases (fun i => _) (fun i => _) x
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : Sum (Fin m) (Fin n) ≃ Fin (m + n)
    where
  toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
  invFun i := @Fin.addCases m n (fun _ => Sum (Fin m) (Fin n)) Sum.inl Sum.inr i
  left_inv x := by cases' x with y y <;> dsimp <;> simp
  right_inv x := by refine' Fin.addCases (fun i => _) (fun i => _) x <;> 

Proof state:
case refine'_1
m n : ℕ
x : Fin (m + n)
i : Fin m
⊢ Sum.elim (Fin.castAdd n) (Fin.natAdd m) ((fun i => Fin.addCases Sum.inl Sum.inr i) (Fin.castAdd n i)) =
    Fin.castAdd n i

Next tactic:
simp
/-- Equivalence between `Fin m ⊕ Fin n` and `Fin (m + n)` -/
def finSumFinEquiv : Sum (Fin m) (Fin n) ≃ Fin (m + n)
    where
  toFun := Sum.elim (Fin.castAdd n) (Fin.natAdd m)
  invFun i := @Fin.addCases m n (fun _ => Sum (Fin m) (Fin n)) Sum.inl Sum.inr i
  left_inv x := by cases' x with y y <;> dsimp <;> simp
  right_inv x := by refine' Fin.addCases (fun i => _) (fun i => _) x <;> 

Proof state:
case refine'_2
m n : ℕ
x : Fin (m + n)
i : Fin n
⊢ Sum.elim (Fin.castAdd n) (Fin.natAdd m) ((fun i => Fin.addCases Sum.inl Sum.inr i) (Fin.natAdd m i)) = Fin.natAdd m i

Next tactic:
simp
@[simp]
theorem finAddFlip_apply_castAdd (k : Fin m) (n : ℕ) :
    finAddFlip (Fin.castAdd n k) = Fin.natAdd n k := by 

Proof state:
m n✝ : ℕ
k : Fin m
n : ℕ
⊢ finAddFlip (Fin.castAdd n k) = Fin.natAdd n k

Next tactic:
simp [finAddFlip]
@[simp]
theorem finAddFlip_apply_natAdd (k : Fin n) (m : ℕ) :
    finAddFlip (Fin.natAdd m k) = Fin.castAdd m k := by 

Proof state:
m✝ n : ℕ
k : Fin n
m : ℕ
⊢ finAddFlip (Fin.natAdd m k) = Fin.castAdd m k

Next tactic:
simp [finAddFlip]
@[simp]
theorem finAddFlip_apply_mk_left {k : ℕ} (h : k < m) (hk : k < m + n := Nat.lt_add_right n h)
    (hnk : n + k < n + m := add_lt_add_left h n) :
    finAddFlip (⟨k, hk⟩ : Fin (m + n)) = ⟨n + k, hnk⟩ := by
  

Proof state:
m n k : ℕ
h : k < m
hk : optParam (k < m + n) (_ : k < m + n)
hnk : optParam (n + k < n + m) (_ : n + k < n + m)
⊢ finAddFlip { val := k, isLt := hk } = { val := n + k, isLt := hnk }

Next tactic:
convert finAddFlip_apply_castAdd ⟨k, h⟩ n
@[simp]
theorem finAddFlip_apply_mk_right {k : ℕ} (h₁ : m ≤ k) (h₂ : k < m + n) :
    finAddFlip (⟨k, h₂⟩ : Fin (m + n)) = ⟨k - m, tsub_le_self.trans_lt <| add_comm m n ▸ h₂⟩ := by
  

Proof state:
m n k : ℕ
h₁ : m ≤ k
h₂ : k < m + n
⊢ finAddFlip { val := k, isLt := h₂ } = { val := k - m, isLt := (_ : k - m < n + m) }

Next tactic:
convert @finAddFlip_apply_natAdd n ⟨k - m, (tsub_lt_iff_right h₁).2 ?_⟩ m
@[simp]
theorem finAddFlip_apply_mk_right {k : ℕ} (h₁ : m ≤ k) (h₂ : k < m + n) :
    finAddFlip (⟨k, h₂⟩ : Fin (m + n)) = ⟨k - m, tsub_le_self.trans_lt <| add_comm m n ▸ h₂⟩ := by
  convert @finAddFlip_apply_natAdd n ⟨k - m, (tsub_lt_iff_right h₁).2 ?_⟩ m
  · 

Proof state:
case h.e'_2.h.e'_6.h.e'_2
m n k : ℕ
h₁ : m ≤ k
h₂ : k < m + n
⊢ k = ↑(Fin.natAdd m { val := k - m, isLt := (_ : k - m < n) })

Next tactic:
simp [add_tsub_cancel_of_le h₁]
@[simp]
theorem finAddFlip_apply_mk_right {k : ℕ} (h₁ : m ≤ k) (h₂ : k < m + n) :
    finAddFlip (⟨k, h₂⟩ : Fin (m + n)) = ⟨k - m, tsub_le_self.trans_lt <| add_comm m n ▸ h₂⟩ := by
  convert @finAddFlip_apply_natAdd n ⟨k - m, (tsub_lt_iff_right h₁).2 ?_⟩ m
  · simp [add_tsub_cancel_of_le h₁]
  · 

Proof state:
m n k : ℕ
h₁ : m ≤ k
h₂ : k < m + n
⊢ k < n + m

Next tactic:
rwa [add_comm]
theorem finRotate_of_lt {k : ℕ} (h : k < n) :
    finRotate (n + 1) ⟨k, h.trans_le n.le_succ⟩ = ⟨k + 1, Nat.succ_lt_succ h⟩ := by
  

Proof state:
m n k : ℕ
h : k < n
⊢ (finRotate (n + 1)) { val := k, isLt := (_ : k < n + 1) } = { val := k + 1, isLt := (_ : Nat.succ k < Nat.succ n) }

Next tactic:
ext
theorem finRotate_of_lt {k : ℕ} (h : k < n) :
    finRotate (n + 1) ⟨k, h.trans_le n.le_succ⟩ = ⟨k + 1, Nat.succ_lt_succ h⟩ := by
  ext
  

Proof state:
case h
m n k : ℕ
h : k < n
⊢ ↑((finRotate (n + 1)) { val := k, isLt := (_ : k < n + 1) }) =
    ↑{ val := k + 1, isLt := (_ : Nat.succ k < Nat.succ n) }

Next tactic:
dsimp [finRotate_succ]
theorem finRotate_of_lt {k : ℕ} (h : k < n) :
    finRotate (n + 1) ⟨k, h.trans_le n.le_succ⟩ = ⟨k + 1, Nat.succ_lt_succ h⟩ := by
  ext
  dsimp [finRotate_succ]
  

Proof state:
case h
m n k : ℕ
h : k < n
⊢ ↑(finAddFlip { val := k, isLt := (_ : k < n + 1) }) = k + 1

Next tactic:
simp [finAddFlip_apply_mk_left h, add_comm]
theorem finRotate_last' : finRotate (n + 1) ⟨n, lt_add_one _⟩ = ⟨0, Nat.zero_lt_succ _⟩ := by
  

Proof state:
m n : ℕ
⊢ (finRotate (n + 1)) { val := n, isLt := (_ : n < n + 1) } = { val := 0, isLt := (_ : 0 < Nat.succ n) }

Next tactic:
dsimp [finRotate_succ]
theorem finRotate_last' : finRotate (n + 1) ⟨n, lt_add_one _⟩ = ⟨0, Nat.zero_lt_succ _⟩ := by
  dsimp [finRotate_succ]
  

Proof state:
m n : ℕ
⊢ (finCongr (_ : 1 + n = n + 1)) (finAddFlip { val := n, isLt := (_ : n < n + 1) }) = 0

Next tactic:
rw [finAddFlip_apply_mk_right le_rfl]
theorem finRotate_last' : finRotate (n + 1) ⟨n, lt_add_one _⟩ = ⟨0, Nat.zero_lt_succ _⟩ := by
  dsimp [finRotate_succ]
  rw [finAddFlip_apply_mk_right le_rfl]
  

Proof state:
m n : ℕ
⊢ (finCongr (_ : 1 + n = n + 1)) { val := n - n, isLt := (_ : n - n < 1 + n) } = 0

Next tactic:
simp
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  

Proof state:
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
⊢ snoc v a = fun i => cons a v ((finRotate (n + 1)) i)

Next tactic:
ext ⟨i, h⟩
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  

Proof state:
case h.mk
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
i : ℕ
h : i < n + 1
⊢ snoc v a { val := i, isLt := h } = cons a v ((finRotate (n + 1)) { val := i, isLt := h })

Next tactic:
by_cases h' : i < n
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  by_cases h' : i < n
  · 

Proof state:
case pos
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
i : ℕ
h : i < n + 1
h' : i < n
⊢ snoc v a { val := i, isLt := h } = cons a v ((finRotate (n + 1)) { val := i, isLt := h })

Next tactic:
rw [finRotate_of_lt h', Fin.snoc, Fin.cons, dif_pos h']
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  by_cases h' : i < n
  · rw [finRotate_of_lt h', Fin.snoc, Fin.cons, dif_pos h']
    

Proof state:
case pos
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
i : ℕ
h : i < n + 1
h' : i < n
⊢ _root_.cast (_ : α = α) (v (castLT { val := i, isLt := h } h')) =
    cases a v { val := i + 1, isLt := (_ : Nat.succ i < Nat.succ n) }

Next tactic:
rfl
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  by_cases h' : i < n
  · rw [finRotate_of_lt h', Fin.snoc, Fin.cons, dif_pos h']
    rfl
  · 

Proof state:
case neg
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
i : ℕ
h : i < n + 1
h' : ¬i < n
⊢ snoc v a { val := i, isLt := h } = cons a v ((finRotate (n + 1)) { val := i, isLt := h })

Next tactic:
have h'' : n = i := by
      simp only [not_lt] at h'
      exact (Nat.eq_of_le_of_lt_succ h' h).symm
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  by_cases h' : i < n
  · rw [finRotate_of_lt h', Fin.snoc, Fin.cons, dif_pos h']
    rfl
  · have h'' : n = i := by
      

Proof state:
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
i : ℕ
h : i < n + 1
h' : ¬i < n
⊢ n = i

Next tactic:
simp only [not_lt] at h'
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  by_cases h' : i < n
  · rw [finRotate_of_lt h', Fin.snoc, Fin.cons, dif_pos h']
    rfl
  · have h'' : n = i := by
      simp only [not_lt] at h'
      

Proof state:
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
i : ℕ
h : i < n + 1
h' : n ≤ i
⊢ n = i

Next tactic:
exact (Nat.eq_of_le_of_lt_succ h' h).symm
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  by_cases h' : i < n
  · rw [finRotate_of_lt h', Fin.snoc, Fin.cons, dif_pos h']
    rfl
  · have h'' : n = i := by
      simp only [not_lt] at h'
      exact (Nat.eq_of_le_of_lt_succ h' h).symm
    

Proof state:
case neg
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
i : ℕ
h : i < n + 1
h' : ¬i < n
h'' : n = i
⊢ snoc v a { val := i, isLt := h } = cons a v ((finRotate (n + 1)) { val := i, isLt := h })

Next tactic:
subst h''
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  by_cases h' : i < n
  · rw [finRotate_of_lt h', Fin.snoc, Fin.cons, dif_pos h']
    rfl
  · have h'' : n = i := by
      simp only [not_lt] at h'
      exact (Nat.eq_of_le_of_lt_succ h' h).symm
    subst h''
    

Proof state:
case neg
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
h : n < n + 1
h' : ¬n < n
⊢ snoc v a { val := n, isLt := h } = cons a v ((finRotate (n + 1)) { val := n, isLt := h })

Next tactic:
rw [finRotate_last', Fin.snoc, Fin.cons, dif_neg (lt_irrefl _)]
theorem Fin.snoc_eq_cons_rotate {α : Type*} (v : Fin n → α) (a : α) :
    @Fin.snoc _ (fun _ => α) v a = fun i => @Fin.cons _ (fun _ => α) a v (finRotate _ i) := by
  ext ⟨i, h⟩
  by_cases h' : i < n
  · rw [finRotate_of_lt h', Fin.snoc, Fin.cons, dif_pos h']
    rfl
  · have h'' : n = i := by
      simp only [not_lt] at h'
      exact (Nat.eq_of_le_of_lt_succ h' h).symm
    subst h''
    rw [finRotate_last', Fin.snoc, Fin.cons, dif_neg (lt_irrefl _)]
    

Proof state:
case neg
m n : ℕ
α : Type u_1
v : Fin n → α
a : α
h : n < n + 1
h' : ¬n < n
⊢ _root_.cast (_ : α = α) a = cases a v { val := 0, isLt := (_ : 0 < Nat.succ n) }

Next tactic:
rfl
@[simp] theorem finRotate_succ_apply (i : Fin (n + 1)) : finRotate (n + 1) i = i + 1 := by
  

Proof state:
m n : ℕ
i : Fin (n + 1)
⊢ (finRotate (n + 1)) i = i + 1

Next tactic:
cases n
@[simp] theorem finRotate_succ_apply (i : Fin (n + 1)) : finRotate (n + 1) i = i + 1 := by
  cases n
  · 

Proof state:
case zero
m : ℕ
i : Fin (Nat.zero + 1)
⊢ (finRotate (Nat.zero + 1)) i = i + 1

Next tactic:
exact @Subsingleton.elim (Fin 1) _ _ _
@[simp] theorem finRotate_succ_apply (i : Fin (n + 1)) : finRotate (n + 1) i = i + 1 := by
  cases n
  · exact @Subsingleton.elim (Fin 1) _ _ _
  

Proof state:
case succ
m n✝ : ℕ
i : Fin (Nat.succ n✝ + 1)
⊢ (finRotate (Nat.succ n✝ + 1)) i = i + 1

Next tactic:
rcases i.le_last.eq_or_lt with (rfl | h)
@[simp] theorem finRotate_succ_apply (i : Fin (n + 1)) : finRotate (n + 1) i = i + 1 := by
  cases n
  · exact @Subsingleton.elim (Fin 1) _ _ _
  rcases i.le_last.eq_or_lt with (rfl | h)
  · 

Proof state:
case succ.inl
m n✝ : ℕ
⊢ (finRotate (Nat.succ n✝ + 1)) (Fin.last (n✝ + 1)) = Fin.last (n✝ + 1) + 1

Next tactic:
simp [finRotate_last]
@[simp] theorem finRotate_succ_apply (i : Fin (n + 1)) : finRotate (n + 1) i = i + 1 := by
  cases n
  · exact @Subsingleton.elim (Fin 1) _ _ _
  rcases i.le_last.eq_or_lt with (rfl | h)
  · simp [finRotate_last]
  · 

Proof state:
case succ.inr
m n✝ : ℕ
i : Fin (Nat.succ n✝ + 1)
h : i < Fin.last (n✝ + 1)
⊢ (finRotate (Nat.succ n✝ + 1)) i = i + 1

Next tactic:
cases i
@[simp] theorem finRotate_succ_apply (i : Fin (n + 1)) : finRotate (n + 1) i = i + 1 := by
  cases n
  · exact @Subsingleton.elim (Fin 1) _ _ _
  rcases i.le_last.eq_or_lt with (rfl | h)
  · simp [finRotate_last]
  · cases i
    

Proof state:
case succ.inr.mk
m n✝ val✝ : ℕ
isLt✝ : val✝ < Nat.succ n✝ + 1
h : { val := val✝, isLt := isLt✝ } < Fin.last (n✝ + 1)
⊢ (finRotate (Nat.succ n✝ + 1)) { val := val✝, isLt := isLt✝ } = { val := val✝, isLt := isLt✝ } + 1

Next tactic:
simp only [Fin.lt_iff_val_lt_val, Fin.val_last, Fin.val_mk] at h
@[simp] theorem finRotate_succ_apply (i : Fin (n + 1)) : finRotate (n + 1) i = i + 1 := by
  cases n
  · exact @Subsingleton.elim (Fin 1) _ _ _
  rcases i.le_last.eq_or_lt with (rfl | h)
  · simp [finRotate_last]
  · cases i
    simp only [Fin.lt_iff_val_lt_val, Fin.val_last, Fin.val_mk] at h
    

Proof state:
case succ.inr.mk
m n✝ val✝ : ℕ
isLt✝ : val✝ < Nat.succ n✝ + 1
h : val✝ < n✝ + 1
⊢ (finRotate (Nat.succ n✝ + 1)) { val := val✝, isLt := isLt✝ } = { val := val✝, isLt := isLt✝ } + 1

Next tactic:
simp [finRotate_of_lt h, Fin.eq_iff_veq, Fin.add_def, Nat.mod_eq_of_lt (Nat.succ_lt_succ h)]
theorem finRotate_apply_zero : finRotate n.succ 0 = 1 := by
  

Proof state:
m n : ℕ
⊢ (finRotate (Nat.succ n)) 0 = 1

Next tactic:
rw [finRotate_succ_apply, zero_add]
theorem coe_finRotate_of_ne_last {i : Fin n.succ} (h : i ≠ Fin.last n) :
    (finRotate (n + 1) i : ℕ) = i + 1 := by
  

Proof state:
m n : ℕ
i : Fin (Nat.succ n)
h : i ≠ Fin.last n
⊢ ↑((finRotate (n + 1)) i) = ↑i + 1

Next tactic:
rw [finRotate_succ_apply]
theorem coe_finRotate_of_ne_last {i : Fin n.succ} (h : i ≠ Fin.last n) :
    (finRotate (n + 1) i : ℕ) = i + 1 := by
  rw [finRotate_succ_apply]
  

Proof state:
m n : ℕ
i : Fin (Nat.succ n)
h : i ≠ Fin.last n
⊢ ↑(i + 1) = ↑i + 1

Next tactic:
have : (i : ℕ) < n := Fin.val_lt_last h
theorem coe_finRotate_of_ne_last {i : Fin n.succ} (h : i ≠ Fin.last n) :
    (finRotate (n + 1) i : ℕ) = i + 1 := by
  rw [finRotate_succ_apply]
  have : (i : ℕ) < n := Fin.val_lt_last h
  

Proof state:
m n : ℕ
i : Fin (Nat.succ n)
h : i ≠ Fin.last n
this : ↑i < n
⊢ ↑(i + 1) = ↑i + 1

Next tactic:
exact Fin.val_add_one_of_lt this
theorem coe_finRotate (i : Fin n.succ) :
    (finRotate n.succ i : ℕ) = if i = Fin.last n then (0 : ℕ) else i + 1 := by
  

Proof state:
m n : ℕ
i : Fin (Nat.succ n)
⊢ ↑((finRotate (Nat.succ n)) i) = if i = Fin.last n then 0 else ↑i + 1

Next tactic:
rw [finRotate_succ_apply, Fin.val_add_one i]
/-- Equivalence between `Fin m × Fin n` and `Fin (m * n)` -/
@[simps]
def finProdFinEquiv : Fin m × Fin n ≃ Fin (m * n)
    where
  toFun x :=
    ⟨x.2 + n * x.1,
      calc
        x.2.1 + n * x.1.1 + 1 = x.1.1 * n + x.2.1 + 1 := by 

Proof state:
m n : ℕ
x : Fin m × Fin n
⊢ ↑x.2 + n * ↑x.1 + 1 = ↑x.1 * n + ↑x.2 + 1

Next tactic:
ac_rfl