l3lab/ntp-mathlib huggingface dataset:
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · 

Proof state:
case succ.zero
α : Type u_1
β : Type u_2
n : ℕ
b : Fin (Nat.succ n)
a : Fin (Nat.zero ^ Nat.succ n)
⊢ ↑a / Nat.zero ^ ↑b % Nat.zero < Nat.zero

Next tactic:
dsimp only [Nat.zero_eq] at a
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        

Proof state:
case succ.zero
α : Type u_1
β : Type u_2
n : ℕ
b : Fin (Nat.succ n)
a : Fin (0 ^ Nat.succ n)
⊢ ↑a / Nat.zero ^ ↑b % Nat.zero < Nat.zero

Next tactic:
rw [zero_pow n.succ_pos] at a
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        

Proof state:
case succ.zero
α : Type u_1
β : Type u_2
n : ℕ
b : Fin (Nat.succ n)
a✝ : Fin (0 ^ Nat.succ n)
a : Fin 0
⊢ ↑a✝ / Nat.zero ^ ↑b % Nat.zero < Nat.zero

Next tactic:
exact a.elim0
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · 

Proof state:
case succ.succ
α : Type u_1
β : Type u_2
n : ℕ
b : Fin (Nat.succ n)
m : ℕ
a : Fin (Nat.succ m ^ Nat.succ n)
⊢ ↑a / Nat.succ m ^ ↑b % Nat.succ m < Nat.succ m

Next tactic:
exact Nat.mod_lt _ m.succ_pos
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      

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

Next tactic:
dsimp
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      dsimp
      

Proof state:
α : Type u_1
β : Type u_2
m n : ℕ
a : Fin (m ^ n)
⊢ { val := ∑ i : Fin n, ↑a / m ^ ↑i % m * m ^ ↑i,
      isLt := (_ : ∑ i : Fin n, ↑{ val := ↑a / m ^ ↑i % m, isLt := (_ : ↑a / m ^ ↑i % m < m) } * m ^ ↑i < m ^ n) } =
    a

Next tactic:
induction' n with n ih
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      dsimp
      induction' n with n ih
      · 

Proof state:
case zero
α : Type u_1
β : Type u_2
m : ℕ
a : Fin (m ^ Nat.zero)
⊢ { val := ∑ i : Fin Nat.zero, ↑a / m ^ ↑i % m * m ^ ↑i,
      isLt :=
        (_ :
          ∑ i : Fin Nat.zero, ↑{ val := ↑a / m ^ ↑i % m, isLt := (_ : ↑a / m ^ ↑i % m < m) } * m ^ ↑i <
            m ^ Nat.zero) } =
    a

Next tactic:
haveI : Subsingleton (Fin (m ^ 0)) := (Fin.castIso <| pow_zero _).toEquiv.subsingleton
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      dsimp
      induction' n with n ih
      · haveI : Subsingleton (Fin (m ^ 0)) := (Fin.castIso <| pow_zero _).toEquiv.subsingleton
        

Proof state:
case zero
α : Type u_1
β : Type u_2
m : ℕ
a : Fin (m ^ Nat.zero)
this : Subsingleton (Fin (m ^ 0))
⊢ { val := ∑ i : Fin Nat.zero, ↑a / m ^ ↑i % m * m ^ ↑i,
      isLt :=
        (_ :
          ∑ i : Fin Nat.zero, ↑{ val := ↑a / m ^ ↑i % m, isLt := (_ : ↑a / m ^ ↑i % m < m) } * m ^ ↑i <
            m ^ Nat.zero) } =
    a

Next tactic:
exact Subsingleton.elim _ _
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      dsimp
      induction' n with n ih
      · haveI : Subsingleton (Fin (m ^ 0)) := (Fin.castIso <| pow_zero _).toEquiv.subsingleton
        exact Subsingleton.elim _ _
      

Proof state:
case succ
α : Type u_1
β : Type u_2
m n : ℕ
ih :
  ∀ (a : Fin (m ^ n)),
    { val := ∑ i : Fin n, ↑a / m ^ ↑i % m * m ^ ↑i,
        isLt := (_ : ∑ i : Fin n, ↑{ val := ↑a / m ^ ↑i % m, isLt := (_ : ↑a / m ^ ↑i % m < m) } * m ^ ↑i < m ^ n) } =
      a
a : Fin (m ^ Nat.succ n)
⊢ { val := ∑ i : Fin (Nat.succ n), ↑a / m ^ ↑i % m * m ^ ↑i,
      isLt :=
        (_ :
          ∑ i : Fin (Nat.succ n), ↑{ val := ↑a / m ^ ↑i % m, isLt := (_ : ↑a / m ^ ↑i % m < m) } * m ^ ↑i <
            m ^ Nat.succ n) } =
    a

Next tactic:
simp_rw [Fin.forall_iff, Fin.ext_iff] at ih
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      dsimp
      induction' n with n ih
      · haveI : Subsingleton (Fin (m ^ 0)) := (Fin.castIso <| pow_zero _).toEquiv.subsingleton
        exact Subsingleton.elim _ _
      simp_rw [Fin.forall_iff, Fin.ext_iff] at ih
      

Proof state:
case succ
α : Type u_1
β : Type u_2
m n : ℕ
a : Fin (m ^ Nat.succ n)
ih : ∀ i < m ^ n, ∑ x : Fin n, i / m ^ ↑x % m * m ^ ↑x = i
⊢ { val := ∑ i : Fin (Nat.succ n), ↑a / m ^ ↑i % m * m ^ ↑i,
      isLt :=
        (_ :
          ∑ i : Fin (Nat.succ n), ↑{ val := ↑a / m ^ ↑i % m, isLt := (_ : ↑a / m ^ ↑i % m < m) } * m ^ ↑i <
            m ^ Nat.succ n) } =
    a

Next tactic:
ext
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      dsimp
      induction' n with n ih
      · haveI : Subsingleton (Fin (m ^ 0)) := (Fin.castIso <| pow_zero _).toEquiv.subsingleton
        exact Subsingleton.elim _ _
      simp_rw [Fin.forall_iff, Fin.ext_iff] at ih
      ext
      

Proof state:
case succ.h
α : Type u_1
β : Type u_2
m n : ℕ
a : Fin (m ^ Nat.succ n)
ih : ∀ i < m ^ n, ∑ x : Fin n, i / m ^ ↑x % m * m ^ ↑x = i
⊢ ↑{ val := ∑ i : Fin (Nat.succ n), ↑a / m ^ ↑i % m * m ^ ↑i,
        isLt :=
          (_ :
            ∑ i : Fin (Nat.succ n), ↑{ val := ↑a / m ^ ↑i % m, isLt := (_ : ↑a / m ^ ↑i % m < m) } * m ^ ↑i <
              m ^ Nat.succ n) } =
    ↑a

Next tactic:
simp_rw [Fin.sum_univ_succ, Fin.val_zero, Fin.val_succ, pow_zero, Nat.div_one,
        mul_one, pow_succ, ← Nat.div_div_eq_div_mul, mul_left_comm _ m, ← mul_sum]
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      dsimp
      induction' n with n ih
      · haveI : Subsingleton (Fin (m ^ 0)) := (Fin.castIso <| pow_zero _).toEquiv.subsingleton
        exact Subsingleton.elim _ _
      simp_rw [Fin.forall_iff, Fin.ext_iff] at ih
      ext
      simp_rw [Fin.sum_univ_succ, Fin.val_zero, Fin.val_succ, pow_zero, Nat.div_one,
        mul_one, pow_succ, ← Nat.div_div_eq_div_mul, mul_left_comm _ m, ← mul_sum]
      

Proof state:
case succ.h
α : Type u_1
β : Type u_2
m n : ℕ
a : Fin (m ^ Nat.succ n)
ih : ∀ i < m ^ n, ∑ x : Fin n, i / m ^ ↑x % m * m ^ ↑x = i
⊢ ↑a % m + m * ∑ x : Fin n, ↑a / m / m ^ ↑x % m * m ^ ↑x = ↑a

Next tactic:
rw [ih _ (Nat.div_lt_of_lt_mul ?_), Nat.mod_add_div]
/-- Equivalence between `Fin n → Fin m` and `Fin (m ^ n)`. -/
@[simps!]
def finFunctionFinEquiv {m n : ℕ} : (Fin n → Fin m) ≃ Fin (m ^ n) :=
  Equiv.ofRightInverseOfCardLE (le_of_eq <| by simp_rw [Fintype.card_fun, Fintype.card_fin])
    (fun f => ⟨∑ i, f i * m ^ (i : ℕ), by
      induction' n with n ih
      · simp
      cases m
      · dsimp only [Nat.zero_eq] at f -- porting note: added, wrong zero
        exact isEmptyElim (f <| Fin.last _)
      simp_rw [Fin.sum_univ_castSucc, Fin.coe_castSucc, Fin.val_last]
      refine' (add_lt_add_of_lt_of_le (ih _) <| mul_le_mul_right' (Fin.is_le _) _).trans_eq _
      rw [← one_add_mul (_ : ℕ), add_comm, pow_succ]
      -- porting note: added, wrong `succ`
      rfl⟩)
    (fun a b => ⟨a / m ^ (b : ℕ) % m, by
      cases' n with n
      · exact b.elim0
      cases' m with m
      · dsimp only [Nat.zero_eq] at a -- porting note: added, wrong zero
        rw [zero_pow n.succ_pos] at a
        exact a.elim0
      · exact Nat.mod_lt _ m.succ_pos⟩)
    fun a => by
      dsimp
      induction' n with n ih
      · haveI : Subsingleton (Fin (m ^ 0)) := (Fin.castIso <| pow_zero _).toEquiv.subsingleton
        exact Subsingleton.elim _ _
      simp_rw [Fin.forall_iff, Fin.ext_iff] at ih
      ext
      simp_rw [Fin.sum_univ_succ, Fin.val_zero, Fin.val_succ, pow_zero, Nat.div_one,
        mul_one, pow_succ, ← Nat.div_div_eq_div_mul, mul_left_comm _ m, ← mul_sum]
      rw [ih _ (Nat.div_lt_of_lt_mul ?_), Nat.mod_add_div]
      -- porting note: replaces `a.is_lt` in the wildcard above. Caused by a refactor of the `npow`
      -- instance for `Fin`.
      

Proof state:
α : Type u_1
β : Type u_2
m n : ℕ
a : Fin (m ^ Nat.succ n)
ih : ∀ i < m ^ n, ∑ x : Fin n, i / m ^ ↑x % m * m ^ ↑x = i
⊢ ↑a < m * m ^ n

Next tactic:
exact a.is_lt.trans_eq (pow_succ _ _)
theorem finFunctionFinEquiv_single {m n : ℕ} [NeZero m] (i : Fin n) (j : Fin m) :
    (finFunctionFinEquiv (Pi.single i j) : ℕ) = j * m ^ (i : ℕ) := by
  

Proof state:
α : Type u_1
β : Type u_2
m n : ℕ
inst✝ : NeZero m
i : Fin n
j : Fin m
⊢ ↑(finFunctionFinEquiv (Pi.single i j)) = ↑j * m ^ ↑i

Next tactic:
rw [finFunctionFinEquiv_apply, Fintype.sum_eq_single i, Pi.single_eq_same]
theorem finFunctionFinEquiv_single {m n : ℕ} [NeZero m] (i : Fin n) (j : Fin m) :
    (finFunctionFinEquiv (Pi.single i j) : ℕ) = j * m ^ (i : ℕ) := by
  rw [finFunctionFinEquiv_apply, Fintype.sum_eq_single i, Pi.single_eq_same]
  

Proof state:
α : Type u_1
β : Type u_2
m n : ℕ
inst✝ : NeZero m
i : Fin n
j : Fin m
⊢ ∀ (x : Fin n), x ≠ i → ↑(Pi.single i j x) * m ^ ↑x = 0

Next tactic:
rintro x hx
theorem finFunctionFinEquiv_single {m n : ℕ} [NeZero m] (i : Fin n) (j : Fin m) :
    (finFunctionFinEquiv (Pi.single i j) : ℕ) = j * m ^ (i : ℕ) := by
  rw [finFunctionFinEquiv_apply, Fintype.sum_eq_single i, Pi.single_eq_same]
  rintro x hx
  

Proof state:
α : Type u_1
β : Type u_2
m n : ℕ
inst✝ : NeZero m
i : Fin n
j : Fin m
x : Fin n
hx : x ≠ i
⊢ ↑(Pi.single i j x) * m ^ ↑x = 0

Next tactic:
rw [Pi.single_eq_of_ne hx, Fin.val_zero', zero_mul]
/-- 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 

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
n : Fin m → ℕ
⊢ Fintype.card ((i : Fin m) → Fin (n i)) = Fintype.card (Fin (∏ i : Fin m, n i))

Next tactic:
simp_rw [Fintype.card_pi, Fintype.card_fin]
/-- 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
      

Proof state:
α : Type u_1
β : Type u_2
m : ℕ
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

Next tactic:
induction' m with m ih
/-- 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
      · 

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

Next tactic:
simp
/-- 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
      

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)
⊢ ∑ i : Fin (Nat.succ m), ↑(f i) * ∏ j : Fin ↑i, n (Fin.castLE (_ : ↑i ≤ Nat.succ m) j) < ∏ i : Fin (Nat.succ m), n i

Next tactic:
rw [Fin.prod_univ_castSucc, Fin.sum_univ_castSucc]
/-- 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]
      

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)
⊢ ∑ 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:
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