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
        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
      cases' h : n b with nb
      · 

Proof state:
case succ.zero
α : 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✝)
h : n b = Nat.zero
⊢ (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ Nat.succ n✝) j)) % Nat.zero < Nat.zero

Next tactic:
rw [prod_eq_zero (Finset.mem_univ _) h] at a
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        

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

Next tactic:
exact isEmptyElim a
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      

Proof state:
case succ.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✝)
nb : ℕ
h : n b = Nat.succ nb
⊢ (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ Nat.succ n✝) j)) % Nat.succ nb < Nat.succ nb

Next tactic:
exact Nat.mod_lt _ nb.succ_pos
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      exact Nat.mod_lt _ nb.succ_pos⟩)
    (by
      

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
⊢ Function.RightInverse
    (fun a b =>
      { val := (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ m) j)) % n b,
        isLt := (_ : (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ m) j)) % n b < n b) })
    fun f =>
    { val := ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j),
      isLt := (_ : ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i) }

Next tactic:
intro a
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      exact Nat.mod_lt _ nb.succ_pos⟩)
    (by
      intro a; 

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
a : Fin (∏ i : Fin m, n i)
⊢ (fun f =>
        { val := ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j),
          isLt := (_ : ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i) })
      ((fun a b =>
          { val := (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ m) j)) % n b,
            isLt := (_ : (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ m) j)) % n b < n b) })
        a) =
    a

Next tactic:
revert a
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      exact Nat.mod_lt _ nb.succ_pos⟩)
    (by
      intro a; revert a; 

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
⊢ ∀ (a : Fin (∏ i : Fin m, n i)),
    (fun f =>
          { val := ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j),
            isLt := (_ : ∑ i : Fin m, ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) < ∏ i : Fin m, n i) })
        ((fun a b =>
            { val := (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ m) j)) % n b,
              isLt := (_ : (↑a / ∏ j : Fin ↑b, n (Fin.castLE (_ : ↑b ≤ m) j)) % n b < n b) })
          a) =
      a

Next tactic:
dsimp only [Fin.val_mk]
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      exact Nat.mod_lt _ nb.succ_pos⟩)
    (by
      intro a; revert a; dsimp only [Fin.val_mk]
      

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
⊢ ∀ (a : Fin (∏ i : Fin m, n i)),
    {
        val :=
          ∑ i : Fin m,
            (↑a / ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j)) % n i * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j),
        isLt :=
          (_ :
            ∑ i : Fin m,
                ↑{ val := (↑a / ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j)) % n i,
                      isLt := (_ : (↑a / ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j)) % n i < n i) } *
                  ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ m) j) <
              ∏ i : Fin m, n i) } =
      a

Next tactic:
refine' Fin.consInduction _ _ 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]
        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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      exact Nat.mod_lt _ nb.succ_pos⟩)
    (by
      intro a; revert a; dsimp only [Fin.val_mk]
      refine' Fin.consInduction _ _ n
      · 

Proof state:
case refine'_1
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
⊢ ∀ (a : Fin (∏ i : Fin 0, Fin.elim0 i)),
    {
        val :=
          ∑ i : Fin 0,
            (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i *
              ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j),
        isLt :=
          (_ :
            ∑ i : Fin 0,
                ↑{ val := (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i,
                      isLt :=
                        (_ : (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i < Fin.elim0 i) } *
                  ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j) <
              ∏ i : Fin 0, Fin.elim0 i) } =
      a

Next tactic:
intro a
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      exact Nat.mod_lt _ nb.succ_pos⟩)
    (by
      intro a; revert a; dsimp only [Fin.val_mk]
      refine' Fin.consInduction _ _ n
      · intro a
        

Proof state:
case refine'_1
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
a : Fin (∏ i : Fin 0, Fin.elim0 i)
⊢ {
      val :=
        ∑ i : Fin 0,
          (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i *
            ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j),
      isLt :=
        (_ :
          ∑ i : Fin 0,
              ↑{ val := (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i,
                    isLt :=
                      (_ : (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i < Fin.elim0 i) } *
                ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j) <
            ∏ i : Fin 0, Fin.elim0 i) } =
    a

Next tactic:
haveI : Subsingleton (Fin (∏ i : Fin 0, i.elim0)) :=
          (Fin.castIso <| prod_empty).toEquiv.subsingleton
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      exact Nat.mod_lt _ nb.succ_pos⟩)
    (by
      intro a; revert a; dsimp only [Fin.val_mk]
      refine' Fin.consInduction _ _ n
      · intro a
        haveI : Subsingleton (Fin (∏ i : Fin 0, i.elim0)) :=
          (Fin.castIso <| prod_empty).toEquiv.subsingleton
        

Proof state:
case refine'_1
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
a : Fin (∏ i : Fin 0, Fin.elim0 i)
this : Subsingleton (Fin (∏ i : Fin 0, Fin.elim0 i))
⊢ {
      val :=
        ∑ i : Fin 0,
          (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i *
            ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j),
      isLt :=
        (_ :
          ∑ i : Fin 0,
              ↑{ val := (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i,
                    isLt :=
                      (_ : (↑a / ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j)) % Fin.elim0 i < Fin.elim0 i) } *
                ∏ j : Fin ↑i, Fin.elim0 (Fin.castLE (_ : ↑i ≤ 0) j) <
            ∏ i : Fin 0, Fin.elim0 i) } =
    a

Next tactic:
exact Subsingleton.elim _ _
/-- 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
      cases' h : n b with nb
      · rw [prod_eq_zero (Finset.mem_univ _) h] at a
        exact isEmptyElim a
      exact Nat.mod_lt _ nb.succ_pos⟩)
    (by
      intro a; revert a; dsimp only [Fin.val_mk]
      refine' Fin.consInduction _ _ n
      · intro a
        haveI : Subsingleton (Fin (∏ i : Fin 0, i.elim0)) :=
          (Fin.castIso <| prod_empty).toEquiv.subsingleton
        exact Subsingleton.elim _ _
      · intro n x xs ih a
        simp_rw [Fin.forall_iff, Fin.ext_iff] at ih
        

Proof state:
case refine'_2
α : Type u_1
β : Type u_2
m : ℕ
n✝ : Fin m → ℕ
n x : ℕ
xs : Fin n → ℕ
a : Fin (∏ i : Fin (n + 1), Fin.cons x xs i)
ih :
  ∀ i < ∏ i : Fin n, xs i,
    ∑ x : Fin n,
        (i / ∏ j : Fin ↑x, xs (Fin.castLE (_ : ↑x ≤ n) j)) % xs x * ∏ j : Fin ↑x, xs (Fin.castLE (_ : ↑x ≤ n) j) =
      i
⊢ {
      val :=
        ∑ i : Fin (n + 1),
          (↑a / ∏ j : Fin ↑i, Fin.cons x xs (Fin.castLE (_ : ↑i ≤ n + 1) j)) % Fin.cons x xs i *
            ∏ j : Fin ↑i, Fin.cons x xs (Fin.castLE (_ : ↑i ≤ n + 1) j),
      isLt :=
        (_ :
          ∑ i : Fin (n + 1),
              ↑{ val := (↑a / ∏ j : Fin ↑i, Fin.cons x xs (Fin.castLE (_ : ↑i ≤ n + 1) j)) % Fin.cons x xs i,
                    isLt :=
                      (_ :
                        (↑a / ∏ j : Fin ↑i, Fin.cons x xs (Fin.castLE (_ : ↑i ≤ n + 1) j)) % Fin.cons x xs i <
                          Fin.cons x xs i) } *
                ∏ j : Fin ↑i, Fin.cons x xs (Fin.castLE (_ : ↑i ≤ n + 1) j) <
            ∏ i : Fin (n + 1), Fin.cons x xs i) } =
    a

Next tactic:
ext