l3lab/ntp-mathlib huggingface dataset:
@[simp]
protected theorem areaForm (w z : ℂ) : Complex.orientation.areaForm w z = (conj w * z).im := by
  let o := Complex.orientation
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o✝ : Orientation ℝ E (Fin 2)
w z : ℂ
o : Orientation ℝ ℂ (Fin 2) := Complex.orientation
⊢ ((Orientation.areaForm Complex.orientation) w) z = ((starRingEnd ℂ) w * z).im

Next tactic:
simp only [o.areaForm_to_volumeForm, o.volumeForm_robust Complex.orthonormalBasisOneI rfl,
    (Basis.det_apply), Matrix.det_fin_two, (Basis.toMatrix_apply), toBasis_orthonormalBasisOneI,
    Matrix.cons_val_zero, coe_basisOneI_repr, Matrix.cons_val_one, Matrix.head_cons, mul_im,
    conj_re, conj_im]
@[simp]
protected theorem areaForm (w z : ℂ) : Complex.orientation.areaForm w z = (conj w * z).im := by
  let o := Complex.orientation
  simp only [o.areaForm_to_volumeForm, o.volumeForm_robust Complex.orthonormalBasisOneI rfl,
    (Basis.det_apply), Matrix.det_fin_two, (Basis.toMatrix_apply), toBasis_orthonormalBasisOneI,
    Matrix.cons_val_zero, coe_basisOneI_repr, Matrix.cons_val_one, Matrix.head_cons, mul_im,
    conj_re, conj_im]
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o✝ : Orientation ℝ E (Fin 2)
w z : ℂ
o : Orientation ℝ ℂ (Fin 2) := Complex.orientation
⊢ w.re * z.im - z.re * w.im = w.re * z.im + -w.im * z.re

Next tactic:
ring
@[simp]
protected theorem rightAngleRotation (z : ℂ) :
    Complex.orientation.rightAngleRotation z = I * z := by
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
z : ℂ
⊢ (Orientation.rightAngleRotation Complex.orientation) z = I * z

Next tactic:
apply ext_inner_right ℝ
@[simp]
protected theorem rightAngleRotation (z : ℂ) :
    Complex.orientation.rightAngleRotation z = I * z := by
  apply ext_inner_right ℝ
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
z : ℂ
⊢ ∀ (v : ℂ), inner ((Orientation.rightAngleRotation Complex.orientation) z) v = inner (I * z) v

Next tactic:
intro w
@[simp]
protected theorem rightAngleRotation (z : ℂ) :
    Complex.orientation.rightAngleRotation z = I * z := by
  apply ext_inner_right ℝ
  intro w
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
z w : ℂ
⊢ inner ((Orientation.rightAngleRotation Complex.orientation) z) w = inner (I * z) w

Next tactic:
rw [Orientation.inner_rightAngleRotation_left]
@[simp]
protected theorem rightAngleRotation (z : ℂ) :
    Complex.orientation.rightAngleRotation z = I * z := by
  apply ext_inner_right ℝ
  intro w
  rw [Orientation.inner_rightAngleRotation_left]
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
z w : ℂ
⊢ ((Orientation.areaForm Complex.orientation) z) w = inner (I * z) w

Next tactic:
simp only [Complex.areaForm, Complex.inner, mul_re, mul_im, conj_re, conj_im, map_mul, conj_I,
    neg_re, neg_im, I_re, I_im]
@[simp]
protected theorem rightAngleRotation (z : ℂ) :
    Complex.orientation.rightAngleRotation z = I * z := by
  apply ext_inner_right ℝ
  intro w
  rw [Orientation.inner_rightAngleRotation_left]
  simp only [Complex.areaForm, Complex.inner, mul_re, mul_im, conj_re, conj_im, map_mul, conj_I,
    neg_re, neg_im, I_re, I_im]
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
z w : ℂ
⊢ z.re * w.im + -z.im * w.re = (-0 * z.re - -1 * -z.im) * w.re - (-0 * -z.im + -1 * z.re) * w.im

Next tactic:
ring
@[simp]
protected theorem kahler (w z : ℂ) : Complex.orientation.kahler w z = conj w * z := by
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
w z : ℂ
⊢ ((Orientation.kahler Complex.orientation) w) z = (starRingEnd ℂ) w * z

Next tactic:
rw [Orientation.kahler_apply_apply]
@[simp]
protected theorem kahler (w z : ℂ) : Complex.orientation.kahler w z = conj w * z := by
  rw [Orientation.kahler_apply_apply]
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
w z : ℂ
⊢ ↑(inner w z) + ((Orientation.areaForm Complex.orientation) w) z • I = (starRingEnd ℂ) w * z

Next tactic:
apply Complex.ext
@[simp]
protected theorem kahler (w z : ℂ) : Complex.orientation.kahler w z = conj w * z := by
  rw [Orientation.kahler_apply_apply]
  apply Complex.ext <;> 

Proof state:
case a
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
w z : ℂ
⊢ (↑(inner w z) + ((Orientation.areaForm Complex.orientation) w) z • I).re = ((starRingEnd ℂ) w * z).re

Next tactic:
simp
@[simp]
protected theorem kahler (w z : ℂ) : Complex.orientation.kahler w z = conj w * z := by
  rw [Orientation.kahler_apply_apply]
  apply Complex.ext <;> 

Proof state:
case a
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
w z : ℂ
⊢ (↑(inner w z) + ((Orientation.areaForm Complex.orientation) w) z • I).im = ((starRingEnd ℂ) w * z).im

Next tactic:
simp
/-- The area form on an oriented real inner product space of dimension 2 can be evaluated in terms
of a complex-number representation of the space. -/
theorem areaForm_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x y : E) :
    ω x y = (conj (f x) * f y).im := by
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x y : E
⊢ ((areaForm o) x) y = ((starRingEnd ℂ) (f x) * f y).im

Next tactic:
rw [← Complex.areaForm, ← hf, areaForm_map (hF := _)]
/-- The area form on an oriented real inner product space of dimension 2 can be evaluated in terms
of a complex-number representation of the space. -/
theorem areaForm_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x y : E) :
    ω x y = (conj (f x) * f y).im := by
  rw [← Complex.areaForm, ← hf, areaForm_map (hF := _)]
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x y : E
⊢ ((areaForm o) x) y = ((areaForm o) ((LinearIsometryEquiv.symm f) (f x))) ((LinearIsometryEquiv.symm f) (f y))

Next tactic:
iterate 2 rw [LinearIsometryEquiv.symm_apply_apply]
/-- The area form on an oriented real inner product space of dimension 2 can be evaluated in terms
of a complex-number representation of the space. -/
theorem areaForm_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x y : E) :
    ω x y = (conj (f x) * f y).im := by
  rw [← Complex.areaForm, ← hf, areaForm_map (hF := _)]
  iterate 2 

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x y : E
⊢ ((areaForm o) x) y = ((areaForm o) ((LinearIsometryEquiv.symm f) (f x))) ((LinearIsometryEquiv.symm f) (f y))

Next tactic:
rw [LinearIsometryEquiv.symm_apply_apply]
/-- The area form on an oriented real inner product space of dimension 2 can be evaluated in terms
of a complex-number representation of the space. -/
theorem areaForm_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x y : E) :
    ω x y = (conj (f x) * f y).im := by
  rw [← Complex.areaForm, ← hf, areaForm_map (hF := _)]
  iterate 2 

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x y : E
⊢ ((areaForm o) x) y = ((areaForm o) x) ((LinearIsometryEquiv.symm f) (f y))

Next tactic:
rw [LinearIsometryEquiv.symm_apply_apply]
/-- The rotation by 90 degrees on an oriented real inner product space of dimension 2 can be
evaluated in terms of a complex-number representation of the space. -/
theorem rightAngleRotation_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x : E) :
    f (J x) = I * f x := by
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x : E
⊢ f ((rightAngleRotation o) x) = I * f x

Next tactic:
rw [← Complex.rightAngleRotation, ← hf, rightAngleRotation_map (hF := _),
    LinearIsometryEquiv.symm_apply_apply]
/-- The Kahler form on an oriented real inner product space of dimension 2 can be evaluated in terms
of a complex-number representation of the space. -/
theorem kahler_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x y : E) :
    o.kahler x y = conj (f x) * f y := by
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x y : E
⊢ ((kahler o) x) y = (starRingEnd ℂ) (f x) * f y

Next tactic:
rw [← Complex.kahler, ← hf, kahler_map (hF := _)]
/-- The Kahler form on an oriented real inner product space of dimension 2 can be evaluated in terms
of a complex-number representation of the space. -/
theorem kahler_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x y : E) :
    o.kahler x y = conj (f x) * f y := by
  rw [← Complex.kahler, ← hf, kahler_map (hF := _)]
  

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x y : E
⊢ ((kahler o) x) y = ((kahler o) ((LinearIsometryEquiv.symm f) (f x))) ((LinearIsometryEquiv.symm f) (f y))

Next tactic:
iterate 2 rw [LinearIsometryEquiv.symm_apply_apply]
/-- The Kahler form on an oriented real inner product space of dimension 2 can be evaluated in terms
of a complex-number representation of the space. -/
theorem kahler_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x y : E) :
    o.kahler x y = conj (f x) * f y := by
  rw [← Complex.kahler, ← hf, kahler_map (hF := _)]
  iterate 2 

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x y : E
⊢ ((kahler o) x) y = ((kahler o) ((LinearIsometryEquiv.symm f) (f x))) ((LinearIsometryEquiv.symm f) (f y))

Next tactic:
rw [LinearIsometryEquiv.symm_apply_apply]
/-- The Kahler form on an oriented real inner product space of dimension 2 can be evaluated in terms
of a complex-number representation of the space. -/
theorem kahler_map_complex (f : E ≃ₗᵢ[ℝ] ℂ)
    (hf : Orientation.map (Fin 2) f.toLinearEquiv o = Complex.orientation) (x y : E) :
    o.kahler x y = conj (f x) * f y := by
  rw [← Complex.kahler, ← hf, kahler_map (hF := _)]
  iterate 2 

Proof state:
E : Type u_1
inst✝² : NormedAddCommGroup E
inst✝¹ : InnerProductSpace ℝ E
inst✝ : Fact (finrank ℝ E = 2)
o : Orientation ℝ E (Fin 2)
f : E ≃ₗᵢ[ℝ] ℂ
hf : (map (Fin 2) f.toLinearEquiv) o = Complex.orientation
x y : E
⊢ ((kahler o) x) y = ((kahler o) x) ((LinearIsometryEquiv.symm f) (f y))

Next tactic:
rw [LinearIsometryEquiv.symm_apply_apply]
theorem factorial_dvd_factorial {m n} (h : m ≤ n) : m ! ∣ n ! := by
  

Proof state:
m✝ n✝ m n : ℕ
h : m ≤ n
⊢ m ! ∣ n !

Next tactic:
induction' n with n IH
theorem factorial_dvd_factorial {m n} (h : m ≤ n) : m ! ∣ n ! := by
  induction' n with n IH
  · 

Proof state:
case zero
m✝ n m : ℕ
h : m ≤ zero
⊢ m ! ∣ zero !

Next tactic:
simp [Nat.eq_zero_of_le_zero h]
theorem factorial_dvd_factorial {m n} (h : m ≤ n) : m ! ∣ n ! := by
  induction' n with n IH
  · simp [Nat.eq_zero_of_le_zero h]
  

Proof state:
case succ
m✝ n✝ m n : ℕ
IH : m ≤ n → m ! ∣ n !
h : m ≤ succ n
⊢ m ! ∣ (succ n)!

Next tactic:
obtain rfl | hl := h.eq_or_lt
theorem factorial_dvd_factorial {m n} (h : m ≤ n) : m ! ∣ n ! := by
  induction' n with n IH
  · simp [Nat.eq_zero_of_le_zero h]
  obtain rfl | hl := h.eq_or_lt
  · 

Proof state:
case succ.inl
m n✝ n : ℕ
IH : succ n ≤ n → (succ n)! ∣ n !
h : succ n ≤ succ n
⊢ (succ n)! ∣ (succ n)!

Next tactic:
simp
theorem factorial_dvd_factorial {m n} (h : m ≤ n) : m ! ∣ n ! := by
  induction' n with n IH
  · simp [Nat.eq_zero_of_le_zero h]
  obtain rfl | hl := h.eq_or_lt
  · simp
  

Proof state:
case succ.inr
m✝ n✝ m n : ℕ
IH : m ≤ n → m ! ∣ n !
h : m ≤ succ n
hl : m < succ n
⊢ m ! ∣ (succ n)!

Next tactic:
exact (IH (le_of_lt_succ hl)).mul_left _
theorem factorial_mul_pow_le_factorial : ∀ {m n : ℕ}, m ! * (m + 1) ^ n ≤ (m + n)!
  | m, 0 => by 

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

Next tactic:
simp
theorem factorial_mul_pow_le_factorial : ∀ {m n : ℕ}, m ! * (m + 1) ^ n ≤ (m + n)!
  | m, 0 => by simp
  | m, n + 1 => by
    

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

Next tactic:
rw [← add_assoc, factorial_succ, mul_comm (_ + 1), pow_succ, ← mul_assoc]
theorem factorial_mul_pow_le_factorial : ∀ {m n : ℕ}, m ! * (m + 1) ^ n ≤ (m + n)!
  | m, 0 => by simp
  | m, n + 1 => by
    rw [← add_assoc, factorial_succ, mul_comm (_ + 1), pow_succ, ← mul_assoc]
    

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

Next tactic:
exact Nat.mul_le_mul factorial_mul_pow_le_factorial (succ_le_succ (le_add_right _ _))
theorem factorial_lt (hn : 0 < n) : n ! < m ! ↔ n < m := by
  

Proof state:
m n : ℕ
hn : 0 < n
⊢ n ! < m ! ↔ n < m

Next tactic:
refine' ⟨fun h => not_le.mp fun hmn => not_le_of_lt h (factorial_le hmn), fun h => _⟩
theorem factorial_lt (hn : 0 < n) : n ! < m ! ↔ n < m := by
  refine' ⟨fun h => not_le.mp fun hmn => not_le_of_lt h (factorial_le hmn), fun h => _⟩
  

Proof state:
m n : ℕ
hn : 0 < n
h : n < m
⊢ n ! < m !

Next tactic:
have : ∀ {n}, 0 < n → n ! < (n + 1)! := by
    intro k hk
    rw [factorial_succ, succ_mul, lt_add_iff_pos_left]
    exact mul_pos hk k.factorial_pos
theorem factorial_lt (hn : 0 < n) : n ! < m ! ↔ n < m := by
  refine' ⟨fun h => not_le.mp fun hmn => not_le_of_lt h (factorial_le hmn), fun h => _⟩
  have : ∀ {n}, 0 < n → n ! < (n + 1)! := by
    

Proof state:
m n : ℕ
hn : 0 < n
h : n < m
⊢ ∀ {n : ℕ}, 0 < n → n ! < (n + 1)!

Next tactic:
intro k hk
theorem factorial_lt (hn : 0 < n) : n ! < m ! ↔ n < m := by
  refine' ⟨fun h => not_le.mp fun hmn => not_le_of_lt h (factorial_le hmn), fun h => _⟩
  have : ∀ {n}, 0 < n → n ! < (n + 1)! := by
    intro k hk
    

Proof state:
m n : ℕ
hn : 0 < n
h : n < m
k : ℕ
hk : 0 < k
⊢ k ! < (k + 1)!

Next tactic:
rw [factorial_succ, succ_mul, lt_add_iff_pos_left]
theorem factorial_lt (hn : 0 < n) : n ! < m ! ↔ n < m := by
  refine' ⟨fun h => not_le.mp fun hmn => not_le_of_lt h (factorial_le hmn), fun h => _⟩
  have : ∀ {n}, 0 < n → n ! < (n + 1)! := by
    intro k hk
    rw [factorial_succ, succ_mul, lt_add_iff_pos_left]
    

Proof state:
m n : ℕ
hn : 0 < n
h : n < m
k : ℕ
hk : 0 < k
⊢ 0 < k * k !

Next tactic:
exact mul_pos hk k.factorial_pos
theorem factorial_lt (hn : 0 < n) : n ! < m ! ↔ n < m := by
  refine' ⟨fun h => not_le.mp fun hmn => not_le_of_lt h (factorial_le hmn), fun h => _⟩
  have : ∀ {n}, 0 < n → n ! < (n + 1)! := by
    intro k hk
    rw [factorial_succ, succ_mul, lt_add_iff_pos_left]
    exact mul_pos hk k.factorial_pos
  

Proof state:
m n : ℕ
hn : 0 < n
h : n < m
this : ∀ {n : ℕ}, 0 < n → n ! < (n + 1)!
⊢ n ! < m !

Next tactic:
induction' h with k hnk ih generalizing hn
theorem factorial_lt (hn : 0 < n) : n ! < m ! ↔ n < m := by
  refine' ⟨fun h => not_le.mp fun hmn => not_le_of_lt h (factorial_le hmn), fun h => _⟩
  have : ∀ {n}, 0 < n → n ! < (n + 1)! := by
    intro k hk
    rw [factorial_succ, succ_mul, lt_add_iff_pos_left]
    exact mul_pos hk k.factorial_pos
  induction' h with k hnk ih generalizing hn
  · 

Proof state:
case refl
m n : ℕ
this : ∀ {n : ℕ}, 0 < n → n ! < (n + 1)!
hn : 0 < n
⊢ n ! < (succ n)!

Next tactic:
exact this hn
theorem factorial_lt (hn : 0 < n) : n ! < m ! ↔ n < m := by
  refine' ⟨fun h => not_le.mp fun hmn => not_le_of_lt h (factorial_le hmn), fun h => _⟩
  have : ∀ {n}, 0 < n → n ! < (n + 1)! := by
    intro k hk
    rw [factorial_succ, succ_mul, lt_add_iff_pos_left]
    exact mul_pos hk k.factorial_pos
  induction' h with k hnk ih generalizing hn
  · exact this hn
  · 

Proof state:
case step
m n : ℕ
this : ∀ {n : ℕ}, 0 < n → n ! < (n + 1)!
k : ℕ
hnk : Nat.le (succ n) k
ih : 0 < n → n ! < k !
hn : 0 < n
⊢ n ! < (succ k)!

Next tactic:
exact (ih hn).trans (this <| hn.trans <| lt_of_succ_le hnk)
@[simp]
theorem factorial_eq_one : n ! = 1 ↔ n ≤ 1 := by
  

Proof state:
m n : ℕ
⊢ n ! = 1 ↔ n ≤ 1

Next tactic:
constructor
@[simp]
theorem factorial_eq_one : n ! = 1 ↔ n ≤ 1 := by
  constructor
  · 

Proof state:
case mp
m n : ℕ
⊢ n ! = 1 → n ≤ 1

Next tactic:
intro h
@[simp]
theorem factorial_eq_one : n ! = 1 ↔ n ≤ 1 := by
  constructor
  · intro h
    

Proof state:
case mp
m n : ℕ
h : n ! = 1
⊢ n ≤ 1

Next tactic:
rw [← not_lt, ← one_lt_factorial, h]
@[simp]
theorem factorial_eq_one : n ! = 1 ↔ n ≤ 1 := by
  constructor
  · intro h
    rw [← not_lt, ← one_lt_factorial, h]
    

Proof state:
case mp
m n : ℕ
h : n ! = 1
⊢ ¬1 < 1

Next tactic:
apply lt_irrefl
@[simp]
theorem factorial_eq_one : n ! = 1 ↔ n ≤ 1 := by
  constructor
  · intro h
    rw [← not_lt, ← one_lt_factorial, h]
    apply lt_irrefl
  · 

Proof state:
case mpr
m n : ℕ
⊢ n ≤ 1 → n ! = 1

Next tactic:
rintro (_|_|_)
@[simp]
theorem factorial_eq_one : n ! = 1 ↔ n ≤ 1 := by
  constructor
  · intro h
    rw [← not_lt, ← one_lt_factorial, h]
    apply lt_irrefl
  · rintro (_|_|_) <;> 

Proof state:
case mpr.refl
m : ℕ
⊢ 1! = 1

Next tactic:
rfl
@[simp]
theorem factorial_eq_one : n ! = 1 ↔ n ≤ 1 := by
  constructor
  · intro h
    rw [← not_lt, ← one_lt_factorial, h]
    apply lt_irrefl
  · rintro (_|_|_) <;> 

Proof state:
case mpr.step.refl
m : ℕ
⊢ 0! = 1

Next tactic:
rfl
theorem factorial_inj (hn : 1 < n) : n ! = m ! ↔ n = m := by
  

Proof state:
m n : ℕ
hn : 1 < n
⊢ n ! = m ! ↔ n = m

Next tactic:
refine' ⟨fun h => _, congr_arg _⟩
theorem factorial_inj (hn : 1 < n) : n ! = m ! ↔ n = m := by
  refine' ⟨fun h => _, congr_arg _⟩
  

Proof state:
m n : ℕ
hn : 1 < n
h : n ! = m !
⊢ n = m

Next tactic:
obtain hnm | rfl | hnm := lt_trichotomy n m
theorem factorial_inj (hn : 1 < n) : n ! = m ! ↔ n = m := by
  refine' ⟨fun h => _, congr_arg _⟩
  obtain hnm | rfl | hnm := lt_trichotomy n m
  · 

Proof state:
case inl
m n : ℕ
hn : 1 < n
h : n ! = m !
hnm : n < m
⊢ n = m

Next tactic:
rw [← factorial_lt <| pos_of_gt hn, h] at hnm
theorem factorial_inj (hn : 1 < n) : n ! = m ! ↔ n = m := by
  refine' ⟨fun h => _, congr_arg _⟩
  obtain hnm | rfl | hnm := lt_trichotomy n m
  · rw [← factorial_lt <| pos_of_gt hn, h] at hnm
    

Proof state:
case inl
m n : ℕ
hn : 1 < n
h : n ! = m !
hnm : m ! < m !
⊢ n = m

Next tactic:
cases lt_irrefl _ hnm
theorem factorial_inj (hn : 1 < n) : n ! = m ! ↔ n = m := by
  refine' ⟨fun h => _, congr_arg _⟩
  obtain hnm | rfl | hnm := lt_trichotomy n m
  · rw [← factorial_lt <| pos_of_gt hn, h] at hnm
    cases lt_irrefl _ hnm
  · 

Proof state:
case inr.inl
n : ℕ
hn : 1 < n
h : n ! = n !
⊢ n = n

Next tactic:
rfl
theorem factorial_inj (hn : 1 < n) : n ! = m ! ↔ n = m := by
  refine' ⟨fun h => _, congr_arg _⟩
  obtain hnm | rfl | hnm := lt_trichotomy n m
  · rw [← factorial_lt <| pos_of_gt hn, h] at hnm
    cases lt_irrefl _ hnm
  · rfl
  

Proof state:
case inr.inr
m n : ℕ
hn : 1 < n
h : n ! = m !
hnm : m < n
⊢ n = m

Next tactic:
rw [← one_lt_factorial, h, one_lt_factorial] at hn
theorem factorial_inj (hn : 1 < n) : n ! = m ! ↔ n = m := by
  refine' ⟨fun h => _, congr_arg _⟩
  obtain hnm | rfl | hnm := lt_trichotomy n m
  · rw [← factorial_lt <| pos_of_gt hn, h] at hnm
    cases lt_irrefl _ hnm
  · rfl
  rw [← one_lt_factorial, h, one_lt_factorial] at hn
  

Proof state:
case inr.inr
m n : ℕ
hn : 1 < m
h : n ! = m !
hnm : m < n
⊢ n = m

Next tactic:
rw [← factorial_lt <| pos_of_gt hn, h] at hnm
theorem factorial_inj (hn : 1 < n) : n ! = m ! ↔ n = m := by
  refine' ⟨fun h => _, congr_arg _⟩
  obtain hnm | rfl | hnm := lt_trichotomy n m
  · rw [← factorial_lt <| pos_of_gt hn, h] at hnm
    cases lt_irrefl _ hnm
  · rfl
  rw [← one_lt_factorial, h, one_lt_factorial] at hn
  rw [← factorial_lt <| pos_of_gt hn, h] at hnm
  

Proof state:
case inr.inr
m n : ℕ
hn : 1 < m
h : n ! = m !
hnm : m ! < m !
⊢ n = m

Next tactic:
cases lt_irrefl _ hnm
theorem factorial_inj' (h : 1 < n ∨ 1 < m) : n ! = m ! ↔ n = m := by
  

Proof state:
m n : ℕ
h : 1 < n ∨ 1 < m
⊢ n ! = m ! ↔ n = m

Next tactic:
obtain hn|hm := h
theorem factorial_inj' (h : 1 < n ∨ 1 < m) : n ! = m ! ↔ n = m := by
  obtain hn|hm := h
  · 

Proof state:
case inl
m n : ℕ
hn : 1 < n
⊢ n ! = m ! ↔ n = m

Next tactic:
exact factorial_inj hn
theorem factorial_inj' (h : 1 < n ∨ 1 < m) : n ! = m ! ↔ n = m := by
  obtain hn|hm := h
  · exact factorial_inj hn
  · 

Proof state:
case inr
m n : ℕ
hm : 1 < m
⊢ n ! = m ! ↔ n = m

Next tactic:
rw [eq_comm, factorial_inj hm, eq_comm]
theorem lt_factorial_self {n : ℕ} (hi : 3 ≤ n) : n < n ! := by
  

Proof state:
m n✝ n : ℕ
hi : 3 ≤ n
⊢ n < n !

Next tactic:
have : 0 < n := (zero_lt_two (α := ℕ)).trans (succ_le_iff.mp hi)
theorem lt_factorial_self {n : ℕ} (hi : 3 ≤ n) : n < n ! := by
  have : 0 < n := (zero_lt_two (α := ℕ)).trans (succ_le_iff.mp hi)
  

Proof state:
m n✝ n : ℕ
hi : 3 ≤ n
this : 0 < n
⊢ n < n !

Next tactic:
have : 1 < pred n := le_pred_of_lt (succ_le_iff.mp hi)
theorem lt_factorial_self {n : ℕ} (hi : 3 ≤ n) : n < n ! := by
  have : 0 < n := (zero_lt_two (α := ℕ)).trans (succ_le_iff.mp hi)
  have : 1 < pred n := le_pred_of_lt (succ_le_iff.mp hi)
  

Proof state:
m n✝ n : ℕ
hi : 3 ≤ n
this✝ : 0 < n
this : 1 < pred n
⊢ n < n !

Next tactic:
rw [← succ_pred_eq_of_pos ‹0 < n›, factorial_succ]
theorem lt_factorial_self {n : ℕ} (hi : 3 ≤ n) : n < n ! := by
  have : 0 < n := (zero_lt_two (α := ℕ)).trans (succ_le_iff.mp hi)
  have : 1 < pred n := le_pred_of_lt (succ_le_iff.mp hi)
  rw [← succ_pred_eq_of_pos ‹0 < n›, factorial_succ]
  

Proof state:
m n✝ n : ℕ
hi : 3 ≤ n
this✝ : 0 < n
this : 1 < pred n
⊢ succ (pred n) < (pred n + 1) * (pred n)!

Next tactic:
exact
    lt_mul_of_one_lt_right (pred n).succ_pos
      ((‹1 < pred n›).trans_le (self_le_factorial _))
theorem add_factorial_succ_lt_factorial_add_succ {i : ℕ} (n : ℕ) (hi : 2 ≤ i) :
    i + (n + 1)! < (i + n + 1)! := by
  

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

Next tactic:
rw [factorial_succ (i + _), add_mul, one_mul]
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]
  

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

Next tactic:
have : i ≤ i + n := le.intro rfl