l3lab/ntp-mathlib huggingface dataset:
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n : Fin (Nat.succ m) → ℕ
f : (i : Fin (Nat.succ m)) → Fin (n i)
this :
  ∀ (n : Fin m → ℕ) (nn : ℕ) (f : (i : Fin m) → Fin (n i)) (fn : Fin nn),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) + ↑fn * ∏ j : Fin m, n j < (∏ i : Fin m, n i) * nn
⊢ ∑ i : Fin m,
        ↑(f (Fin.castSucc i)) * ∏ j : Fin ↑(Fin.castSucc i), n (Fin.castLE (_ : ↑(Fin.castSucc i) ≤ Nat.succ m) j) +
      ↑(f (Fin.last m)) * ∏ j : Fin ↑(Fin.last m), n (Fin.castLE (_ : ↑(Fin.last m) ≤ Nat.succ m) j) <
    (∏ i : Fin m, n (Fin.castSucc i)) * n (Fin.last m)

Next tactic:
replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n : Fin (Nat.succ m) → ℕ
f : (i : Fin (Nat.succ m)) → Fin (n i)
this :
  ∑ i : Fin m, ↑(Fin.init f i) * ∏ j : Fin ↑i, Fin.init n (Fin.castLE (_ : ↑i ≤ m) j) +
      ↑(f (Fin.last m)) * ∏ j : Fin m, Fin.init n j <
    (∏ i : Fin m, Fin.init n i) * n (Fin.last m)
⊢ ∑ i : Fin m,
        ↑(f (Fin.castSucc i)) * ∏ j : Fin ↑(Fin.castSucc i), n (Fin.castLE (_ : ↑(Fin.castSucc i) ≤ Nat.succ m) j) +
      ↑(f (Fin.last m)) * ∏ j : Fin ↑(Fin.last m), n (Fin.castLE (_ : ↑(Fin.last m) ≤ Nat.succ m) j) <
    (∏ i : Fin m, n (Fin.castSucc i)) * n (Fin.last m)

Next tactic:
rw [← Fin.snoc_init_self f]
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n : Fin (Nat.succ m) → ℕ
f : (i : Fin (Nat.succ m)) → Fin (n i)
this :
  ∑ i : Fin m, ↑(Fin.init f i) * ∏ j : Fin ↑i, Fin.init n (Fin.castLE (_ : ↑i ≤ m) j) +
      ↑(f (Fin.last m)) * ∏ j : Fin m, Fin.init n j <
    (∏ i : Fin m, Fin.init n i) * n (Fin.last m)
⊢ ∑ i : Fin m,
        ↑(Fin.snoc (Fin.init f) (f (Fin.last m)) (Fin.castSucc i)) *
          ∏ j : Fin ↑(Fin.castSucc i), n (Fin.castLE (_ : ↑(Fin.castSucc i) ≤ Nat.succ m) j) +
      ↑(Fin.snoc (Fin.init f) (f (Fin.last m)) (Fin.last m)) *
        ∏ j : Fin ↑(Fin.last m), n (Fin.castLE (_ : ↑(Fin.last m) ≤ Nat.succ m) j) <
    (∏ i : Fin m, n (Fin.castSucc i)) * n (Fin.last m)

Next tactic:
simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n : Fin (Nat.succ m) → ℕ
f : (i : Fin (Nat.succ m)) → Fin (n i)
this :
  ∑ i : Fin m, ↑(Fin.init f i) * ∏ j : Fin ↑i, Fin.init n (Fin.castLE (_ : ↑i ≤ m) j) +
      ↑(f (Fin.last m)) * ∏ j : Fin m, Fin.init n j <
    (∏ i : Fin m, Fin.init n i) * n (Fin.last m)
⊢ ∑ x : Fin m,
        ↑(Fin.snoc (Fin.init f) (f (Fin.last m)) (Fin.castSucc x)) *
          ∏ x_1 : Fin ↑(Fin.castSucc x),
            Fin.snoc (Fin.init n) (n (Fin.last m)) (Fin.castLE (_ : ↑(Fin.castSucc x) ≤ Nat.succ m) x_1) +
      ↑(Fin.snoc (Fin.init f) (f (Fin.last m)) (Fin.last m)) *
        ∏ x : Fin ↑(Fin.last m),
          Fin.snoc (Fin.init n) (n (Fin.last m)) (Fin.castLE (_ : ↑(Fin.last m) ≤ Nat.succ m) x) <
    (∏ x : Fin m, Fin.snoc (Fin.init n) (n (Fin.last m)) (Fin.castSucc x)) *
      Fin.snoc (Fin.init n) (n (Fin.last m)) (Fin.last m)

Next tactic:
simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n : Fin (Nat.succ m) → ℕ
f : (i : Fin (Nat.succ m)) → Fin (n i)
this :
  ∑ i : Fin m, ↑(Fin.init f i) * ∏ j : Fin ↑i, Fin.init n (Fin.castLE (_ : ↑i ≤ m) j) +
      ↑(f (Fin.last m)) * ∏ j : Fin m, Fin.init n j <
    (∏ i : Fin m, Fin.init n i) * n (Fin.last m)
⊢ ∑ x : Fin m,
        ↑(Fin.init f x) * ∏ x_1 : Fin ↑(Fin.castSucc x), n (Fin.castLE (_ : ↑(Fin.castSucc x) ≤ Nat.succ m) x_1) +
      ↑(f (Fin.last m)) * ∏ x : Fin ↑(Fin.last m), n (Fin.castLE (_ : ↑(Fin.last m) ≤ Nat.succ m) x) <
    (∏ x : Fin m, Fin.init n x) * n (Fin.last m)

Next tactic:
exact this
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      

Proof state:
case succ
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n : Fin (Nat.succ m) → ℕ
f : (i : Fin (Nat.succ m)) → Fin (n i)
⊢ ∀ (n : Fin m → ℕ) (nn : ℕ) (f : (i : Fin m) → Fin (n i)) (fn : Fin nn),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) + ↑fn * ∏ j : Fin m, n j < (∏ i : Fin m, n i) * nn

Next tactic:
intro n nn f fn
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      

Proof state:
case succ
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n✝ : Fin (Nat.succ m) → ℕ
f✝ : (i : Fin (Nat.succ m)) → Fin (n✝ i)
n : Fin m → ℕ
nn : ℕ
f : (i : Fin m) → Fin (n i)
fn : Fin nn
⊢ ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) + ↑fn * ∏ j : Fin m, n j < (∏ i : Fin m, n i) * nn

Next tactic:
cases nn
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      cases nn
      · 

Proof state:
case succ.zero
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n✝ : Fin (Nat.succ m) → ℕ
f✝ : (i : Fin (Nat.succ m)) → Fin (n✝ i)
n : Fin m → ℕ
f : (i : Fin m) → Fin (n i)
fn : Fin Nat.zero
⊢ ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) + ↑fn * ∏ j : Fin m, n j <
    (∏ i : Fin m, n i) * Nat.zero

Next tactic:
dsimp only [Nat.zero_eq] at fn
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      cases nn
      · dsimp only [Nat.zero_eq] at fn -- porting note: added, wrong zero
        

Proof state:
case succ.zero
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n✝ : Fin (Nat.succ m) → ℕ
f✝ : (i : Fin (Nat.succ m)) → Fin (n✝ i)
n : Fin m → ℕ
f : (i : Fin m) → Fin (n i)
fn : Fin 0
⊢ ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) + ↑fn * ∏ j : Fin m, n j <
    (∏ i : Fin m, n i) * Nat.zero

Next tactic:
exact isEmptyElim fn
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      cases nn
      · dsimp only [Nat.zero_eq] at fn -- porting note: added, wrong zero
        exact isEmptyElim fn
      

Proof state:
case succ.succ
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n✝¹ : Fin (Nat.succ m) → ℕ
f✝ : (i : Fin (Nat.succ m)) → Fin (n✝¹ i)
n : Fin m → ℕ
f : (i : Fin m) → Fin (n i)
n✝ : ℕ
fn : Fin (Nat.succ n✝)
⊢ ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) + ↑fn * ∏ j : Fin m, n j <
    (∏ i : Fin m, n i) * Nat.succ n✝

Next tactic:
refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      cases nn
      · dsimp only [Nat.zero_eq] at fn -- porting note: added, wrong zero
        exact isEmptyElim fn
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      

Proof state:
case succ.succ
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n✝¹ : Fin (Nat.succ m) → ℕ
f✝ : (i : Fin (Nat.succ m)) → Fin (n✝¹ i)
n : Fin m → ℕ
f : (i : Fin m) → Fin (n i)
n✝ : ℕ
fn : Fin (Nat.succ n✝)
⊢ ∏ i : Fin m, n i + n✝ * ∏ j : Fin m, n j = (∏ i : Fin m, n i) * Nat.succ n✝

Next tactic:
rw [← one_add_mul (_ : ℕ), mul_comm, add_comm]
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      cases nn
      · dsimp only [Nat.zero_eq] at fn -- porting note: added, wrong zero
        exact isEmptyElim fn
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), mul_comm, add_comm]
      -- porting note: added, wrong `succ`
      

Proof state:
case succ.succ
α : Type u_1
β : Type u_2
m : ℕ
ih :
  ∀ {n : Fin m → ℕ} (f : (i : Fin m) → Fin (n i)),
    ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i
n✝¹ : Fin (Nat.succ m) → ℕ
f✝ : (i : Fin (Nat.succ m)) → Fin (n✝¹ i)
n : Fin m → ℕ
f : (i : Fin m) → Fin (n i)
n✝ : ℕ
fn : Fin (Nat.succ n✝)
⊢ (∏ i : Fin m, n i) * (n✝ + 1) = (∏ i : Fin m, n i) * Nat.succ n✝

Next tactic:
rfl
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      cases nn
      · dsimp only [Nat.zero_eq] at fn -- porting note: added, wrong zero
        exact isEmptyElim fn
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), mul_comm, add_comm]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨(a / ∏ j : Fin b, n (Fin.castLE b.is_lt.le j)) % n b, by
      

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
a : Fin (∏ i : Fin m, n i)
b : Fin m
⊢ (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ m) j)) % n b < n b

Next tactic:
cases m
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      cases nn
      · dsimp only [Nat.zero_eq] at fn -- porting note: added, wrong zero
        exact isEmptyElim fn
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), mul_comm, add_comm]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨(a / ∏ j : Fin b, n (Fin.castLE b.is_lt.le j)) % n b, by
      cases m
      · 

Proof state:
case zero
α : Type u_1
β : Type u_2
n : Fin Nat.zero → ℕ
a : Fin (∏ i : Fin Nat.zero, n i)
b : Fin Nat.zero
⊢ (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ Nat.zero) j)) % n b < n b

Next tactic:
exact b.elim0
/-- Equivalence between `∀ i : Fin m, Fin (n i)` and `Fin (∏ i : Fin m, n i)`. -/
def finPiFinEquiv {m : ℕ} {n : Fin m → ℕ} : (∀ i : Fin m, Fin (n i)) ≃ Fin (∏ i : Fin m, n i) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_pi, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * ∏ j, n (Fin.castLE i.is_lt.le j), by
      induction' m with m ih
      · simp
      rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
      suffices
        ∀ (n : Fin m → ℕ) (nn : ℕ) (f : ∀ i : Fin m, Fin (n i)) (fn : Fin nn),
          ((∑ i : Fin m, ↑(f i) * ∏ j : Fin i, n (Fin.castLE i.prop.le j)) + ↑fn * ∏ j, n j) <
            (∏ i : Fin m, n i) * nn by
        replace := this (Fin.init n) (n (Fin.last _)) (Fin.init f) (f (Fin.last _))
        rw [← Fin.snoc_init_self f]
        simp (config := { singlePass := true }) only [← Fin.snoc_init_self n]
        simp_rw [Fin.snoc_castSucc, Fin.snoc_last, Fin.snoc_init_self n]
        exact this
      intro n nn f fn
      cases nn
      · dsimp only [Nat.zero_eq] at fn -- porting note: added, wrong zero
        exact isEmptyElim fn
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), mul_comm, add_comm]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨(a / ∏ j : Fin b, n (Fin.castLE b.is_lt.le j)) % n b, by
      cases m
      · exact b.elim0
      

Proof state:
case succ
α : Type u_1
β : Type u_2
n✝ : ℕ
n : Fin (Nat.succ n✝) → ℕ
a : Fin (∏ i : Fin (Nat.succ n✝), n i)
b : Fin (Nat.succ n✝)
⊢ (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ Nat.succ n✝) j)) % n b < n b

Next tactic:
cases' h : n b with nb