l3lab/ntp-mathlib huggingface dataset:
theorem add_factorial_succ_lt_factorial_add_succ {i : ℕ} (n : ℕ) (hi : 2 ≤ i) :
    i + (n + 1)! < (i + n + 1)! := by
  rw [factorial_succ (i + _), add_mul, one_mul]
  have : i ≤ i + n := le.intro rfl
  

Proof state:
m n✝ i n : ℕ
hi : 2 ≤ i
this : i ≤ i + n
⊢ i + (n + 1)! < (i + n) * (i + n)! + (i + n)!

Next tactic:
exact
    add_lt_add_of_lt_of_le
      (this.trans_lt
        ((lt_mul_iff_one_lt_right ((by decide : 0 < 2).trans_le (hi.trans this))).mpr
          (lt_iff_le_and_ne.mpr
            ⟨(i + n).factorial_pos, fun g =>
              Nat.not_succ_le_self 1 ((hi.trans this).trans (factorial_eq_one.mp g.symm))⟩)))
      (factorial_le
        ((le_of_eq (add_comm n 1)).trans
        ((add_le_add_iff_right n).mpr ((by decide : 1 ≤ 2).trans hi))))
theorem add_factorial_succ_lt_factorial_add_succ {i : ℕ} (n : ℕ) (hi : 2 ≤ i) :
    i + (n + 1)! < (i + n + 1)! := by
  rw [factorial_succ (i + _), add_mul, one_mul]
  have : i ≤ i + n := le.intro rfl
  exact
    add_lt_add_of_lt_of_le
      (this.trans_lt
        ((lt_mul_iff_one_lt_right ((by 

Proof state:
m n✝ i n : ℕ
hi : 2 ≤ i
this : i ≤ i + n
⊢ 0 < 2

Next tactic:
decide
theorem add_factorial_succ_lt_factorial_add_succ {i : ℕ} (n : ℕ) (hi : 2 ≤ i) :
    i + (n + 1)! < (i + n + 1)! := by
  rw [factorial_succ (i + _), add_mul, one_mul]
  have : i ≤ i + n := le.intro rfl
  exact
    add_lt_add_of_lt_of_le
      (this.trans_lt
        ((lt_mul_iff_one_lt_right ((by decide : 0 < 2).trans_le (hi.trans this))).mpr
          (lt_iff_le_and_ne.mpr
            ⟨(i + n).factorial_pos, fun g =>
              Nat.not_succ_le_self 1 ((hi.trans this).trans (factorial_eq_one.mp g.symm))⟩)))
      (factorial_le
        ((le_of_eq (add_comm n 1)).trans
        ((add_le_add_iff_right n).mpr ((by 

Proof state:
m n✝ i n : ℕ
hi : 2 ≤ i
this : i ≤ i + n
⊢ 1 ≤ 2

Next tactic:
decide
theorem add_factorial_lt_factorial_add {i n : ℕ} (hi : 2 ≤ i) (hn : 1 ≤ n) :
    i + n ! < (i + n)! := by
  

Proof state:
m n✝ i n : ℕ
hi : 2 ≤ i
hn : 1 ≤ n
⊢ i + n ! < (i + n)!

Next tactic:
cases hn
theorem add_factorial_lt_factorial_add {i n : ℕ} (hi : 2 ≤ i) (hn : 1 ≤ n) :
    i + n ! < (i + n)! := by
  cases hn
  · 

Proof state:
case refl
m n i : ℕ
hi : 2 ≤ i
⊢ i + 1! < (i + 1)!

Next tactic:
rw [factorial_one]
theorem add_factorial_lt_factorial_add {i n : ℕ} (hi : 2 ≤ i) (hn : 1 ≤ n) :
    i + n ! < (i + n)! := by
  cases hn
  · rw [factorial_one]
    

Proof state:
case refl
m n i : ℕ
hi : 2 ≤ i
⊢ i + 1 < (i + 1)!

Next tactic:
exact lt_factorial_self (succ_le_succ hi)
theorem add_factorial_lt_factorial_add {i n : ℕ} (hi : 2 ≤ i) (hn : 1 ≤ n) :
    i + n ! < (i + n)! := by
  cases hn
  · rw [factorial_one]
    exact lt_factorial_self (succ_le_succ hi)
  

Proof state:
case step
m n i : ℕ
hi : 2 ≤ i
m✝ : ℕ
a✝ : Nat.le 1 m✝
⊢ i + (succ m✝)! < (i + succ m✝)!

Next tactic:
exact add_factorial_succ_lt_factorial_add_succ _ hi
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  

Proof state:
m n✝ i n : ℕ
⊢ i + (n + 1)! ≤ (i + (n + 1))!

Next tactic:
cases (le_or_lt (2 : ℕ) i)
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · 

Proof state:
case inl
m n✝ i n : ℕ
h✝ : 2 ≤ i
⊢ i + (n + 1)! ≤ (i + (n + 1))!

Next tactic:
rw [← add_assoc]
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    

Proof state:
case inl
m n✝ i n : ℕ
h✝ : 2 ≤ i
⊢ i + (n + 1)! ≤ (i + n + 1)!

Next tactic:
apply Nat.le_of_lt
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    

Proof state:
case inl.h
m n✝ i n : ℕ
h✝ : 2 ≤ i
⊢ i + (n + 1)! < (i + n + 1)!

Next tactic:
apply add_factorial_succ_lt_factorial_add_succ
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    apply add_factorial_succ_lt_factorial_add_succ
    

Proof state:
case inl.h.hi
m n✝ i n : ℕ
h✝ : 2 ≤ i
⊢ 2 ≤ i

Next tactic:
assumption
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    apply add_factorial_succ_lt_factorial_add_succ
    assumption
  · 

Proof state:
case inr
m n✝ i n : ℕ
h✝ : i < 2
⊢ i + (n + 1)! ≤ (i + (n + 1))!

Next tactic:
match i with
    | 0 => simp
    | 1 =>
      rw [← add_assoc, factorial_succ (1 + n), add_mul, one_mul, add_comm 1 n, add_le_add_iff_right]
      apply one_le_mul
      · apply Nat.le_add_left
      · apply factorial_pos
    | succ (succ n) => contradiction
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    apply add_factorial_succ_lt_factorial_add_succ
    assumption
  · match i with
    | 0 => 

Proof state:
m n✝ i n : ℕ
h✝ : 0 < 2
⊢ 0 + (n + 1)! ≤ (0 + (n + 1))!

Next tactic:
simp
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    apply add_factorial_succ_lt_factorial_add_succ
    assumption
  · match i with
    | 0 => simp
    | 1 =>
      

Proof state:
m n✝ i n : ℕ
h✝ : 1 < 2
⊢ 1 + (n + 1)! ≤ (1 + (n + 1))!

Next tactic:
rw [← add_assoc, factorial_succ (1 + n), add_mul, one_mul, add_comm 1 n, add_le_add_iff_right]
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    apply add_factorial_succ_lt_factorial_add_succ
    assumption
  · match i with
    | 0 => simp
    | 1 =>
      rw [← add_assoc, factorial_succ (1 + n), add_mul, one_mul, add_comm 1 n, add_le_add_iff_right]
      

Proof state:
m n✝ i n : ℕ
h✝ : 1 < 2
⊢ 1 ≤ (n + 1) * (n + 1)!

Next tactic:
apply one_le_mul
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    apply add_factorial_succ_lt_factorial_add_succ
    assumption
  · match i with
    | 0 => simp
    | 1 =>
      rw [← add_assoc, factorial_succ (1 + n), add_mul, one_mul, add_comm 1 n, add_le_add_iff_right]
      apply one_le_mul
      · 

Proof state:
case ha
m n✝ i n : ℕ
h✝ : 1 < 2
⊢ 1 ≤ n + 1

Next tactic:
apply Nat.le_add_left
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    apply add_factorial_succ_lt_factorial_add_succ
    assumption
  · match i with
    | 0 => simp
    | 1 =>
      rw [← add_assoc, factorial_succ (1 + n), add_mul, one_mul, add_comm 1 n, add_le_add_iff_right]
      apply one_le_mul
      · apply Nat.le_add_left
      · 

Proof state:
case hb
m n✝ i n : ℕ
h✝ : 1 < 2
⊢ 1 ≤ (n + 1)!

Next tactic:
apply factorial_pos
theorem add_factorial_succ_le_factorial_add_succ (i : ℕ) (n : ℕ) :
    i + (n + 1)! ≤ (i + (n + 1))! := by
  cases (le_or_lt (2 : ℕ) i)
  · rw [← add_assoc]
    apply Nat.le_of_lt
    apply add_factorial_succ_lt_factorial_add_succ
    assumption
  · match i with
    | 0 => simp
    | 1 =>
      rw [← add_assoc, factorial_succ (1 + n), add_mul, one_mul, add_comm 1 n, add_le_add_iff_right]
      apply one_le_mul
      · apply Nat.le_add_left
      · apply factorial_pos
    | succ (succ n) => 

Proof state:
m n✝¹ i n✝ n : ℕ
h✝ : succ (succ n) < 2
⊢ succ (succ n) + (n✝ + 1)! ≤ (succ (succ n) + (n✝ + 1))!

Next tactic:
contradiction
theorem add_factorial_le_factorial_add (i : ℕ) {n : ℕ} (n1 : 1 ≤ n) : i + n ! ≤ (i + n)! := by
  

Proof state:
m n✝ i n : ℕ
n1 : 1 ≤ n
⊢ i + n ! ≤ (i + n)!

Next tactic:
cases' n1 with h
theorem add_factorial_le_factorial_add (i : ℕ) {n : ℕ} (n1 : 1 ≤ n) : i + n ! ≤ (i + n)! := by
  cases' n1 with h
  · 

Proof state:
case refl
m n i : ℕ
⊢ i + 1! ≤ (i + 1)!

Next tactic:
exact self_le_factorial _
theorem add_factorial_le_factorial_add (i : ℕ) {n : ℕ} (n1 : 1 ≤ n) : i + n ! ≤ (i + n)! := by
  cases' n1 with h
  · exact self_le_factorial _
  

Proof state:
case step
m n i h : ℕ
a✝ : Nat.le 1 h
⊢ i + (succ h)! ≤ (i + succ h)!

Next tactic:
exact add_factorial_succ_le_factorial_add_succ i h
theorem factorial_mul_pow_sub_le_factorial {n m : ℕ} (hnm : n ≤ m) : n ! * n ^ (m - n) ≤ m ! := by
  

Proof state:
m✝ n✝ n m : ℕ
hnm : n ≤ m
⊢ n ! * n ^ (m - n) ≤ m !

Next tactic:
calc
    _ ≤ n ! * (n + 1) ^ (m - n) := mul_le_mul_left' (Nat.pow_le_pow_left n.le_succ _) _
    _ ≤ _ := by simpa [hnm] using @Nat.factorial_mul_pow_le_factorial n (m - n)
theorem factorial_mul_pow_sub_le_factorial {n m : ℕ} (hnm : n ≤ m) : n ! * n ^ (m - n) ≤ m ! := by
  calc
    _ ≤ n ! * (n + 1) ^ (m - n) := mul_le_mul_left' (Nat.pow_le_pow_left n.le_succ _) _
    _ ≤ _ := by 

Proof state:
m✝ n✝ n m : ℕ
hnm : n ≤ m
⊢ n ! * (n + 1) ^ (m - n) ≤ m !

Next tactic:
simpa [hnm] using @Nat.factorial_mul_pow_le_factorial n (m - n)
@[simp]
theorem zero_ascFactorial (k : ℕ) : (0 : ℕ).ascFactorial k = k ! := by
  

Proof state:
k : ℕ
⊢ ascFactorial 0 k = k !

Next tactic:
induction' k with t ht
@[simp]
theorem zero_ascFactorial (k : ℕ) : (0 : ℕ).ascFactorial k = k ! := by
  induction' k with t ht
  · 

Proof state:
case zero
⊢ ascFactorial 0 zero = zero !

Next tactic:
rfl
@[simp]
theorem zero_ascFactorial (k : ℕ) : (0 : ℕ).ascFactorial k = k ! := by
  induction' k with t ht
  · rfl
  

Proof state:
case succ
t : ℕ
ht : ascFactorial 0 t = t !
⊢ ascFactorial 0 (succ t) = (succ t)!

Next tactic:
rw [ascFactorial, ht, zero_add, Nat.factorial_succ]
theorem succ_ascFactorial (n : ℕ) :
    ∀ k, (n + 1) * n.succ.ascFactorial k = (n + k + 1) * n.ascFactorial k
  | 0 => by 

Proof state:
n : ℕ
⊢ (n + 1) * ascFactorial (succ n) 0 = (n + 0 + 1) * ascFactorial n 0

Next tactic:
rw [add_zero, ascFactorial_zero, ascFactorial_zero]
theorem succ_ascFactorial (n : ℕ) :
    ∀ k, (n + 1) * n.succ.ascFactorial k = (n + k + 1) * n.ascFactorial k
  | 0 => by rw [add_zero, ascFactorial_zero, ascFactorial_zero]
  | k + 1 => by
    

Proof state:
n k : ℕ
⊢ (n + 1) * ascFactorial (succ n) (k + 1) = (n + (k + 1) + 1) * ascFactorial n (k + 1)

Next tactic:
rw [ascFactorial, mul_left_comm, succ_ascFactorial n k, ascFactorial, succ_add, ← add_assoc]
/-- `n.ascFactorial k = (n + k)! / n!` but without ℕ-division. See `Nat.ascFactorial_eq_div` for
the version with ℕ-division. -/
theorem factorial_mul_ascFactorial (n : ℕ) : ∀ k, n ! * n.ascFactorial k = (n + k)!
  | 0 => by 

Proof state:
n : ℕ
⊢ n ! * ascFactorial n 0 = (n + 0)!

Next tactic:
simp
/-- `n.ascFactorial k = (n + k)! / n!` but without ℕ-division. See `Nat.ascFactorial_eq_div` for
the version with ℕ-division. -/
theorem factorial_mul_ascFactorial (n : ℕ) : ∀ k, n ! * n.ascFactorial k = (n + k)!
  | 0 => by simp
  | k + 1 => by
    

Proof state:
n k : ℕ
⊢ n ! * ascFactorial n (k + 1) = (n + (k + 1))!

Next tactic:
rw [ascFactorial_succ, mul_left_comm, factorial_mul_ascFactorial n k, ← add_assoc, factorial]
/-- Avoid in favor of `Nat.factorial_mul_ascFactorial` if you can. ℕ-division isn't worth it. -/
theorem ascFactorial_eq_div (n k : ℕ) : n.ascFactorial k = (n + k)! / n ! := by
  

Proof state:
n k : ℕ
⊢ ascFactorial n k = (n + k)! / n !

Next tactic:
apply mul_left_cancel₀ n.factorial_ne_zero
/-- Avoid in favor of `Nat.factorial_mul_ascFactorial` if you can. ℕ-division isn't worth it. -/
theorem ascFactorial_eq_div (n k : ℕ) : n.ascFactorial k = (n + k)! / n ! := by
  apply mul_left_cancel₀ n.factorial_ne_zero
  

Proof state:
n k : ℕ
⊢ n ! * ascFactorial n k = n ! * ((n + k)! / n !)

Next tactic:
rw [factorial_mul_ascFactorial]
/-- Avoid in favor of `Nat.factorial_mul_ascFactorial` if you can. ℕ-division isn't worth it. -/
theorem ascFactorial_eq_div (n k : ℕ) : n.ascFactorial k = (n + k)! / n ! := by
  apply mul_left_cancel₀ n.factorial_ne_zero
  rw [factorial_mul_ascFactorial]
  

Proof state:
n k : ℕ
⊢ (n + k)! = n ! * ((n + k)! / n !)

Next tactic:
exact (Nat.mul_div_cancel' <| factorial_dvd_factorial <| le.intro rfl).symm
theorem ascFactorial_of_sub {n k : ℕ} (h : k < n) :
    (n - k) * (n - k).ascFactorial k = (n - (k + 1)).ascFactorial (k + 1) := by
  

Proof state:
n k : ℕ
h : k < n
⊢ (n - k) * ascFactorial (n - k) k = ascFactorial (n - (k + 1)) (k + 1)

Next tactic:
let t := n - (k + 1)
theorem ascFactorial_of_sub {n k : ℕ} (h : k < n) :
    (n - k) * (n - k).ascFactorial k = (n - (k + 1)).ascFactorial (k + 1) := by
  let t := n - (k + 1)
  

Proof state:
n k : ℕ
h : k < n
t : ℕ := n - (k + 1)
⊢ (n - k) * ascFactorial (n - k) k = ascFactorial (n - (k + 1)) (k + 1)

Next tactic:
suffices h' : n - k = t + 1 by rw [h', succ_ascFactorial, ascFactorial_succ]
theorem ascFactorial_of_sub {n k : ℕ} (h : k < n) :
    (n - k) * (n - k).ascFactorial k = (n - (k + 1)).ascFactorial (k + 1) := by
  let t := n - (k + 1)
  suffices h' : n - k = t + 1 by 

Proof state:
n k : ℕ
h : k < n
t : ℕ := n - (k + 1)
h' : n - k = t + 1
⊢ (n - k) * ascFactorial (n - k) k = ascFactorial (n - (k + 1)) (k + 1)

Next tactic:
rw [h', succ_ascFactorial, ascFactorial_succ]
theorem ascFactorial_of_sub {n k : ℕ} (h : k < n) :
    (n - k) * (n - k).ascFactorial k = (n - (k + 1)).ascFactorial (k + 1) := by
  let t := n - (k + 1)
  suffices h' : n - k = t + 1 by rw [h', succ_ascFactorial, ascFactorial_succ]
  

Proof state:
n k : ℕ
h : k < n
t : ℕ := n - (k + 1)
⊢ n - k = t + 1

Next tactic:
rw [← tsub_tsub_assoc (succ_le_of_lt h) (succ_pos k), succ_sub_one]
theorem pow_succ_le_ascFactorial (n : ℕ) : ∀ k : ℕ, (n + 1) ^ k ≤ n.ascFactorial k
  | 0 => by 

Proof state:
n : ℕ
⊢ (n + 1) ^ 0 ≤ ascFactorial n 0

Next tactic:
rw [ascFactorial_zero, pow_zero]
theorem pow_succ_le_ascFactorial (n : ℕ) : ∀ k : ℕ, (n + 1) ^ k ≤ n.ascFactorial k
  | 0 => by rw [ascFactorial_zero, pow_zero]
  | k + 1 => by
    

Proof state:
n k : ℕ
⊢ (n + 1) ^ (k + 1) ≤ ascFactorial n (k + 1)

Next tactic:
rw [pow_succ, mul_comm]
theorem pow_succ_le_ascFactorial (n : ℕ) : ∀ k : ℕ, (n + 1) ^ k ≤ n.ascFactorial k
  | 0 => by rw [ascFactorial_zero, pow_zero]
  | k + 1 => by
    rw [pow_succ, mul_comm]
    

Proof state:
n k : ℕ
⊢ (n + 1) * (n + 1) ^ k ≤ ascFactorial n (k + 1)

Next tactic:
exact Nat.mul_le_mul (Nat.add_le_add_right le_self_add _) (pow_succ_le_ascFactorial _ k)
theorem pow_lt_ascFactorial' (n k : ℕ) : (n + 1) ^ (k + 2) < n.ascFactorial (k + 2) := by
  

Proof state:
n k : ℕ
⊢ (n + 1) ^ (k + 2) < ascFactorial n (k + 2)

Next tactic:
rw [pow_succ, ascFactorial, mul_comm]
theorem pow_lt_ascFactorial' (n k : ℕ) : (n + 1) ^ (k + 2) < n.ascFactorial (k + 2) := by
  rw [pow_succ, ascFactorial, mul_comm]
  

Proof state:
n k : ℕ
⊢ (n + 1) * (n + 1) ^ (k + 1) < (n + (k + 1) + 1) * ascFactorial n (k + 1)

Next tactic:
exact
    Nat.mul_lt_mul (Nat.add_lt_add_right (Nat.lt_add_of_pos_right succ_pos') 1)
      (pow_succ_le_ascFactorial n _) (pow_pos succ_pos' _)
theorem pow_lt_ascFactorial (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → (n + 1) ^ k < n.ascFactorial k
  | 0 => by 

Proof state:
n : ℕ
⊢ 2 ≤ 0 → (n + 1) ^ 0 < ascFactorial n 0

Next tactic:
rintro ⟨⟩
theorem pow_lt_ascFactorial (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → (n + 1) ^ k < n.ascFactorial k
  | 0 => by rintro ⟨⟩
  | 1 => by 

Proof state:
n : ℕ
⊢ 2 ≤ 1 → (n + 1) ^ 1 < ascFactorial n 1

Next tactic:
intro
theorem pow_lt_ascFactorial (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → (n + 1) ^ k < n.ascFactorial k
  | 0 => by rintro ⟨⟩
  | 1 => by intro; 

Proof state:
n : ℕ
a✝ : 2 ≤ 1
⊢ (n + 1) ^ 1 < ascFactorial n 1

Next tactic:
contradiction
theorem ascFactorial_le_pow_add (n : ℕ) : ∀ k : ℕ, n.ascFactorial k ≤ (n + k) ^ k
  | 0 => by 

Proof state:
n : ℕ
⊢ ascFactorial n 0 ≤ (n + 0) ^ 0

Next tactic:
rw [ascFactorial_zero, pow_zero]
theorem ascFactorial_le_pow_add (n : ℕ) : ∀ k : ℕ, n.ascFactorial k ≤ (n + k) ^ k
  | 0 => by rw [ascFactorial_zero, pow_zero]
  | k + 1 => by
    

Proof state:
n k : ℕ
⊢ ascFactorial n (k + 1) ≤ (n + (k + 1)) ^ (k + 1)

Next tactic:
rw [ascFactorial_succ, pow_succ, ← add_assoc, mul_comm _ (succ (n + k))]
theorem ascFactorial_le_pow_add (n : ℕ) : ∀ k : ℕ, n.ascFactorial k ≤ (n + k) ^ k
  | 0 => by rw [ascFactorial_zero, pow_zero]
  | k + 1 => by
    rw [ascFactorial_succ, pow_succ, ← add_assoc, mul_comm _ (succ (n + k))]
    

Proof state:
n k : ℕ
⊢ (n + k + 1) * ascFactorial n k ≤ succ (n + k) * (n + k + 1) ^ k

Next tactic:
exact
      Nat.mul_le_mul_of_nonneg_left
        ((ascFactorial_le_pow_add _ k).trans (Nat.pow_le_pow_left (le_succ _) _))
theorem ascFactorial_lt_pow_add (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → n.ascFactorial k < (n + k) ^ k
  | 0 => by 

Proof state:
n : ℕ
⊢ 2 ≤ 0 → ascFactorial n 0 < (n + 0) ^ 0

Next tactic:
rintro ⟨⟩
theorem ascFactorial_lt_pow_add (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → n.ascFactorial k < (n + k) ^ k
  | 0 => by rintro ⟨⟩
  | 1 => by 

Proof state:
n : ℕ
⊢ 2 ≤ 1 → ascFactorial n 1 < (n + 1) ^ 1

Next tactic:
intro
theorem ascFactorial_lt_pow_add (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → n.ascFactorial k < (n + k) ^ k
  | 0 => by rintro ⟨⟩
  | 1 => by intro; 

Proof state:
n : ℕ
a✝ : 2 ≤ 1
⊢ ascFactorial n 1 < (n + 1) ^ 1

Next tactic:
contradiction
theorem ascFactorial_lt_pow_add (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → n.ascFactorial k < (n + k) ^ k
  | 0 => by rintro ⟨⟩
  | 1 => by intro; contradiction
  | k + 2 => fun _ => by
    

Proof state:
n k : ℕ
x✝ : 2 ≤ k + 2
⊢ ascFactorial n (k + 2) < (n + (k + 2)) ^ (k + 2)

Next tactic:
rw [ascFactorial_succ, pow_succ]
theorem ascFactorial_lt_pow_add (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → n.ascFactorial k < (n + k) ^ k
  | 0 => by rintro ⟨⟩
  | 1 => by intro; contradiction
  | k + 2 => fun _ => by
    rw [ascFactorial_succ, pow_succ]
    

Proof state:
n k : ℕ
x✝ : 2 ≤ k + 2
⊢ (n + (k + 1) + 1) * ascFactorial n (k + 1) < (n + (k + 2)) ^ (k + 1) * (n + (k + 2))

Next tactic:
rw [add_assoc n (k + 1) 1, mul_comm <| (n + (k + 2)) ^ (k + 1)]
theorem ascFactorial_lt_pow_add (n : ℕ) : ∀ {k : ℕ}, 2 ≤ k → n.ascFactorial k < (n + k) ^ k
  | 0 => by rintro ⟨⟩
  | 1 => by intro; contradiction
  | k + 2 => fun _ => by
    rw [ascFactorial_succ, pow_succ]
    rw [add_assoc n (k + 1) 1, mul_comm <| (n + (k + 2)) ^ (k + 1)]
    

Proof state:
n k : ℕ
x✝ : 2 ≤ k + 2
⊢ (n + (k + 1 + 1)) * ascFactorial n (k + 1) < (n + (k + 2)) * (n + (k + 2)) ^ (k + 1)

Next tactic:
exact mul_lt_mul_of_pos_left ((ascFactorial_le_pow_add n _).trans_lt $
      Nat.pow_lt_pow_left (lt_add_one _) k.succ_ne_zero) (succ_pos _)
theorem zero_descFactorial_succ (k : ℕ) : (0 : ℕ).descFactorial (k + 1) = 0 := by
  

Proof state:
k : ℕ
⊢ descFactorial 0 (k + 1) = 0

Next tactic:
rw [descFactorial_succ, zero_tsub, zero_mul]
theorem descFactorial_one (n : ℕ) : n.descFactorial 1 = n := by 

Proof state:
n : ℕ
⊢ descFactorial n 1 = n

Next tactic:
simp
theorem succ_descFactorial_succ (n : ℕ) :
    ∀ k : ℕ, (n + 1).descFactorial (k + 1) = (n + 1) * n.descFactorial k
  | 0 => by 

Proof state:
n : ℕ
⊢ descFactorial (n + 1) (0 + 1) = (n + 1) * descFactorial n 0

Next tactic:
rw [descFactorial_zero, descFactorial_one, mul_one]
theorem succ_descFactorial_succ (n : ℕ) :
    ∀ k : ℕ, (n + 1).descFactorial (k + 1) = (n + 1) * n.descFactorial k
  | 0 => by rw [descFactorial_zero, descFactorial_one, mul_one]
  | succ k => by
    

Proof state:
n k : ℕ
⊢ descFactorial (n + 1) (succ k + 1) = (n + 1) * descFactorial n (succ k)

Next tactic:
rw [descFactorial_succ, succ_descFactorial_succ _ k, descFactorial_succ, succ_sub_succ,
      mul_left_comm]
theorem succ_descFactorial (n : ℕ) :
    ∀ k, (n + 1 - k) * (n + 1).descFactorial k = (n + 1) * n.descFactorial k
  | 0 => by 

Proof state:
n : ℕ
⊢ (n + 1 - 0) * descFactorial (n + 1) 0 = (n + 1) * descFactorial n 0

Next tactic:
rw [tsub_zero, descFactorial_zero, descFactorial_zero]
theorem succ_descFactorial (n : ℕ) :
    ∀ k, (n + 1 - k) * (n + 1).descFactorial k = (n + 1) * n.descFactorial k
  | 0 => by rw [tsub_zero, descFactorial_zero, descFactorial_zero]
  | k + 1 => by
    

Proof state:
n k : ℕ
⊢ (n + 1 - (k + 1)) * descFactorial (n + 1) (k + 1) = (n + 1) * descFactorial n (k + 1)

Next tactic:
rw [descFactorial, succ_descFactorial _ k, descFactorial_succ, succ_sub_succ, mul_left_comm]
theorem descFactorial_self : ∀ n : ℕ, n.descFactorial n = n !
  | 0 => by 

Proof state:
⊢ descFactorial 0 0 = 0!

Next tactic:
rw [descFactorial_zero, factorial_zero]
theorem descFactorial_self : ∀ n : ℕ, n.descFactorial n = n !
  | 0 => by rw [descFactorial_zero, factorial_zero]
  | succ n => by 

Proof state:
n : ℕ
⊢ descFactorial (succ n) (succ n) = (succ n)!

Next tactic:
rw [succ_descFactorial_succ, descFactorial_self n, factorial_succ]
@[simp]
theorem descFactorial_eq_zero_iff_lt {n : ℕ} : ∀ {k : ℕ}, n.descFactorial k = 0 ↔ n < k
  | 0 => by 

Proof state:
n : ℕ
⊢ descFactorial n 0 = 0 ↔ n < 0

Next tactic:
simp only [descFactorial_zero, Nat.one_ne_zero, Nat.not_lt_zero]
@[simp]
theorem descFactorial_eq_zero_iff_lt {n : ℕ} : ∀ {k : ℕ}, n.descFactorial k = 0 ↔ n < k
  | 0 => by simp only [descFactorial_zero, Nat.one_ne_zero, Nat.not_lt_zero]
  | succ k => by
    

Proof state:
n k : ℕ
⊢ descFactorial n (succ k) = 0 ↔ n < succ k

Next tactic:
rw [descFactorial_succ, mul_eq_zero, descFactorial_eq_zero_iff_lt, lt_succ_iff,
      tsub_eq_zero_iff_le, lt_iff_le_and_ne, or_iff_left_iff_imp, and_imp]
@[simp]
theorem descFactorial_eq_zero_iff_lt {n : ℕ} : ∀ {k : ℕ}, n.descFactorial k = 0 ↔ n < k
  | 0 => by simp only [descFactorial_zero, Nat.one_ne_zero, Nat.not_lt_zero]
  | succ k => by
    rw [descFactorial_succ, mul_eq_zero, descFactorial_eq_zero_iff_lt, lt_succ_iff,
      tsub_eq_zero_iff_le, lt_iff_le_and_ne, or_iff_left_iff_imp, and_imp]
    

Proof state:
n k : ℕ
⊢ n ≤ k → n ≠ k → n ≤ k

Next tactic:
exact fun h _ => h
theorem add_descFactorial_eq_ascFactorial (n : ℕ) :
    ∀ k : ℕ, (n + k).descFactorial k = n.ascFactorial k
  | 0 => by 

Proof state:
n : ℕ
⊢ descFactorial (n + 0) 0 = ascFactorial n 0

Next tactic:
rw [ascFactorial_zero, descFactorial_zero]
theorem add_descFactorial_eq_ascFactorial (n : ℕ) :
    ∀ k : ℕ, (n + k).descFactorial k = n.ascFactorial k
  | 0 => by rw [ascFactorial_zero, descFactorial_zero]
  | succ k => by 

Proof state:
n k : ℕ
⊢ descFactorial (n + succ k) (succ k) = ascFactorial n (succ k)

Next tactic:
rw [Nat.add_succ, succ_descFactorial_succ, ascFactorial_succ,
    add_descFactorial_eq_ascFactorial _ k]
/-- `n.descFactorial k = n! / (n - k)!` but without ℕ-division. See `Nat.descFactorial_eq_div`
for the version using ℕ-division. -/
theorem factorial_mul_descFactorial : ∀ {n k : ℕ}, k ≤ n → (n - k)! * n.descFactorial k = n !
  | n, 0 => fun _ => by 

Proof state:
n : ℕ
x✝ : 0 ≤ n
⊢ (n - 0)! * descFactorial n 0 = n !

Next tactic:
rw [descFactorial_zero, mul_one, tsub_zero]
/-- `n.descFactorial k = n! / (n - k)!` but without ℕ-division. See `Nat.descFactorial_eq_div`
for the version using ℕ-division. -/
theorem factorial_mul_descFactorial : ∀ {n k : ℕ}, k ≤ n → (n - k)! * n.descFactorial k = n !
  | n, 0 => fun _ => by rw [descFactorial_zero, mul_one, tsub_zero]
  | 0, succ k => fun h => by
    

Proof state:
k : ℕ
h : succ k ≤ 0
⊢ (0 - succ k)! * descFactorial 0 (succ k) = 0!

Next tactic:
exfalso
/-- `n.descFactorial k = n! / (n - k)!` but without ℕ-division. See `Nat.descFactorial_eq_div`
for the version using ℕ-division. -/
theorem factorial_mul_descFactorial : ∀ {n k : ℕ}, k ≤ n → (n - k)! * n.descFactorial k = n !
  | n, 0 => fun _ => by rw [descFactorial_zero, mul_one, tsub_zero]
  | 0, succ k => fun h => by
    exfalso
    

Proof state:
case h
k : ℕ
h : succ k ≤ 0
⊢ False

Next tactic:
exact not_succ_le_zero k h