l3lab/ntp-mathlib huggingface dataset:
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      

Proof state:
case intro
R : Type u_1
r✝ : R
inst✝ : CommRing R
P p : R[X]
r : R
hp₀ : coeff p 0 = 0
x✝ : r ≠ 0
i k : ℕ
hk : (p + C r) ^ k = 0
hp : eval 0 p = 0
⊢ r ^ k = 0

Next tactic:
simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
    

Proof state:
case refine'_2
R : Type u_1
r✝ : R
inst✝ : CommRing R
P p : R[X]
r : R
hp₀ : coeff p 0 = 0
x✝ : r ≠ 0
hp : IsNilpotent p → ∀ (i : ℕ), IsNilpotent (coeff p i)
hpr : IsNilpotent (p + C r)
i : ℕ
hr : IsNilpotent (C r)
⊢ IsNilpotent (coeff (p + C r) i)

Next tactic:
cases' i with i
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
    cases' i with i
    · 

Proof state:
case refine'_2.zero
R : Type u_1
r✝ : R
inst✝ : CommRing R
P p : R[X]
r : R
hp₀ : coeff p 0 = 0
x✝ : r ≠ 0
hp : IsNilpotent p → ∀ (i : ℕ), IsNilpotent (coeff p i)
hpr : IsNilpotent (p + C r)
hr : IsNilpotent (C r)
⊢ IsNilpotent (coeff (p + C r) Nat.zero)

Next tactic:
simpa [hp₀] using hr
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
    cases' i with i
    · simpa [hp₀] using hr
    

Proof state:
case refine'_2.succ
R : Type u_1
r✝ : R
inst✝ : CommRing R
P p : R[X]
r : R
hp₀ : coeff p 0 = 0
x✝ : r ≠ 0
hp : IsNilpotent p → ∀ (i : ℕ), IsNilpotent (coeff p i)
hpr : IsNilpotent (p + C r)
hr : IsNilpotent (C r)
i : ℕ
⊢ IsNilpotent (coeff (p + C r) (Nat.succ i))

Next tactic:
simp only [coeff_add, coeff_C_succ, add_zero]
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
    cases' i with i
    · simpa [hp₀] using hr
    simp only [coeff_add, coeff_C_succ, add_zero]
    

Proof state:
case refine'_2.succ
R : Type u_1
r✝ : R
inst✝ : CommRing R
P p : R[X]
r : R
hp₀ : coeff p 0 = 0
x✝ : r ≠ 0
hp : IsNilpotent p → ∀ (i : ℕ), IsNilpotent (coeff p i)
hpr : IsNilpotent (p + C r)
hr : IsNilpotent (C r)
i : ℕ
⊢ IsNilpotent (coeff p (Nat.succ i))

Next tactic:
apply hp
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
    cases' i with i
    · simpa [hp₀] using hr
    simp only [coeff_add, coeff_C_succ, add_zero]
    apply hp
    

Proof state:
case refine'_2.succ.a
R : Type u_1
r✝ : R
inst✝ : CommRing R
P p : R[X]
r : R
hp₀ : coeff p 0 = 0
x✝ : r ≠ 0
hp : IsNilpotent p → ∀ (i : ℕ), IsNilpotent (coeff p i)
hpr : IsNilpotent (p + C r)
hr : IsNilpotent (C r)
i : ℕ
⊢ IsNilpotent p

Next tactic:
simpa using Commute.isNilpotent_sub (Commute.all _ _) hpr hr
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
    cases' i with i
    · simpa [hp₀] using hr
    simp only [coeff_add, coeff_C_succ, add_zero]
    apply hp
    simpa using Commute.isNilpotent_sub (Commute.all _ _) hpr hr
  · 

Proof state:
case refine'_3
R : Type u_1
r : R
inst✝ : CommRing R
P p : R[X]
x✝ : p ≠ 0
hnp : IsNilpotent p → ∀ (i : ℕ), IsNilpotent (coeff p i)
hpX : IsNilpotent (p * X)
i : ℕ
⊢ IsNilpotent (coeff (p * X) i)

Next tactic:
cases' i with i
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
    cases' i with i
    · simpa [hp₀] using hr
    simp only [coeff_add, coeff_C_succ, add_zero]
    apply hp
    simpa using Commute.isNilpotent_sub (Commute.all _ _) hpr hr
  · cases' i with i
    · 

Proof state:
case refine'_3.zero
R : Type u_1
r : R
inst✝ : CommRing R
P p : R[X]
x✝ : p ≠ 0
hnp : IsNilpotent p → ∀ (i : ℕ), IsNilpotent (coeff p i)
hpX : IsNilpotent (p * X)
⊢ IsNilpotent (coeff (p * X) Nat.zero)

Next tactic:
simp
protected lemma isNilpotent_iff :
    IsNilpotent P ↔ ∀ i, IsNilpotent (coeff P i) := by
  refine' ⟨P.recOnHorner (by simp) (fun p r hp₀ _ hp hpr i ↦ _) (fun p _ hnp hpX i ↦ _), fun h ↦ _⟩
  · rw [← sum_monomial_eq P]
    exact isNilpotent_sum (fun i _ ↦ by simpa only [isNilpotent_monomial_iff] using h i)
  · have hr : IsNilpotent (C r) := by
      obtain ⟨k, hk⟩ := hpr
      replace hp : eval 0 p = 0 := by rwa [coeff_zero_eq_aeval_zero] at hp₀
      refine' isNilpotent_C_iff.mpr ⟨k, _⟩
      simpa [coeff_zero_eq_aeval_zero, hp] using congr_arg (fun q ↦ coeff q 0) hk
    cases' i with i
    · simpa [hp₀] using hr
    simp only [coeff_add, coeff_C_succ, add_zero]
    apply hp
    simpa using Commute.isNilpotent_sub (Commute.all _ _) hpr hr
  · cases' i with i
    · simp
    

Proof state:
case refine'_3.succ
R : Type u_1
r : R
inst✝ : CommRing R
P p : R[X]
x✝ : p ≠ 0
hnp : IsNilpotent p → ∀ (i : ℕ), IsNilpotent (coeff p i)
hpX : IsNilpotent (p * X)
i : ℕ
⊢ IsNilpotent (coeff (p * X) (Nat.succ i))

Next tactic:
simpa using hnp (isNilpotent_mul_X_iff.mp hpX) i
@[simp] lemma isNilpotent_reflect_iff {P : R[X]} {N : ℕ} (hN : P.natDegree ≤ N):
    IsNilpotent (reflect N P) ↔ IsNilpotent P := by
  

Proof state:
R : Type u_1
r : R
inst✝ : CommRing R
P✝ P : R[X]
N : ℕ
hN : natDegree P ≤ N
⊢ IsNilpotent (reflect N P) ↔ IsNilpotent P

Next tactic:
simp only [Polynomial.isNilpotent_iff, coeff_reverse]
@[simp] lemma isNilpotent_reflect_iff {P : R[X]} {N : ℕ} (hN : P.natDegree ≤ N):
    IsNilpotent (reflect N P) ↔ IsNilpotent P := by
  simp only [Polynomial.isNilpotent_iff, coeff_reverse]
  

Proof state:
R : Type u_1
r : R
inst✝ : CommRing R
P✝ P : R[X]
N : ℕ
hN : natDegree P ≤ N
⊢ (∀ (i : ℕ), IsNilpotent (coeff (reflect N P) i)) ↔ ∀ (i : ℕ), IsNilpotent (coeff P i)

Next tactic:
refine' ⟨fun h i ↦ _, fun h i ↦ _⟩
@[simp] lemma isNilpotent_reflect_iff {P : R[X]} {N : ℕ} (hN : P.natDegree ≤ N):
    IsNilpotent (reflect N P) ↔ IsNilpotent P := by
  simp only [Polynomial.isNilpotent_iff, coeff_reverse]
  refine' ⟨fun h i ↦ _, fun h i ↦ _⟩ <;> 

Proof state:
case refine'_1
R : Type u_1
r : R
inst✝ : CommRing R
P✝ P : R[X]
N : ℕ
hN : natDegree P ≤ N
h : ∀ (i : ℕ), IsNilpotent (coeff (reflect N P) i)
i : ℕ
⊢ IsNilpotent (coeff P i)

Next tactic:
rcases le_or_lt i N with hi | hi
@[simp] lemma isNilpotent_reflect_iff {P : R[X]} {N : ℕ} (hN : P.natDegree ≤ N):
    IsNilpotent (reflect N P) ↔ IsNilpotent P := by
  simp only [Polynomial.isNilpotent_iff, coeff_reverse]
  refine' ⟨fun h i ↦ _, fun h i ↦ _⟩ <;> 

Proof state:
case refine'_2
R : Type u_1
r : R
inst✝ : CommRing R
P✝ P : R[X]
N : ℕ
hN : natDegree P ≤ N
h : ∀ (i : ℕ), IsNilpotent (coeff P i)
i : ℕ
⊢ IsNilpotent (coeff (reflect N P) i)

Next tactic:
rcases le_or_lt i N with hi | hi
@[simp] lemma isNilpotent_reflect_iff {P : R[X]} {N : ℕ} (hN : P.natDegree ≤ N):
    IsNilpotent (reflect N P) ↔ IsNilpotent P := by
  simp only [Polynomial.isNilpotent_iff, coeff_reverse]
  refine' ⟨fun h i ↦ _, fun h i ↦ _⟩ <;> rcases le_or_lt i N with hi | hi
  · 

Proof state:
case refine'_1.inl
R : Type u_1
r : R
inst✝ : CommRing R
P✝ P : R[X]
N : ℕ
hN : natDegree P ≤ N
h : ∀ (i : ℕ), IsNilpotent (coeff (reflect N P) i)
i : ℕ
hi : i ≤ N
⊢ IsNilpotent (coeff P i)

Next tactic:
simpa [tsub_tsub_cancel_of_le hi] using h (N - i)
@[simp] lemma isNilpotent_reflect_iff {P : R[X]} {N : ℕ} (hN : P.natDegree ≤ N):
    IsNilpotent (reflect N P) ↔ IsNilpotent P := by
  simp only [Polynomial.isNilpotent_iff, coeff_reverse]
  refine' ⟨fun h i ↦ _, fun h i ↦ _⟩ <;> rcases le_or_lt i N with hi | hi
  · simpa [tsub_tsub_cancel_of_le hi] using h (N - i)
  · 

Proof state:
case refine'_1.inr
R : Type u_1
r : R
inst✝ : CommRing R
P✝ P : R[X]
N : ℕ
hN : natDegree P ≤ N
h : ∀ (i : ℕ), IsNilpotent (coeff (reflect N P) i)
i : ℕ
hi : N < i
⊢ IsNilpotent (coeff P i)

Next tactic:
simp [coeff_eq_zero_of_natDegree_lt $ lt_of_le_of_lt hN hi]
@[simp] lemma isNilpotent_reflect_iff {P : R[X]} {N : ℕ} (hN : P.natDegree ≤ N):
    IsNilpotent (reflect N P) ↔ IsNilpotent P := by
  simp only [Polynomial.isNilpotent_iff, coeff_reverse]
  refine' ⟨fun h i ↦ _, fun h i ↦ _⟩ <;> rcases le_or_lt i N with hi | hi
  · simpa [tsub_tsub_cancel_of_le hi] using h (N - i)
  · simp [coeff_eq_zero_of_natDegree_lt $ lt_of_le_of_lt hN hi]
  · 

Proof state:
case refine'_2.inl
R : Type u_1
r : R
inst✝ : CommRing R
P✝ P : R[X]
N : ℕ
hN : natDegree P ≤ N
h : ∀ (i : ℕ), IsNilpotent (coeff P i)
i : ℕ
hi : i ≤ N
⊢ IsNilpotent (coeff (reflect N P) i)

Next tactic:
simpa [hi, revAt_le] using h (N - i)
@[simp] lemma isNilpotent_reflect_iff {P : R[X]} {N : ℕ} (hN : P.natDegree ≤ N):
    IsNilpotent (reflect N P) ↔ IsNilpotent P := by
  simp only [Polynomial.isNilpotent_iff, coeff_reverse]
  refine' ⟨fun h i ↦ _, fun h i ↦ _⟩ <;> rcases le_or_lt i N with hi | hi
  · simpa [tsub_tsub_cancel_of_le hi] using h (N - i)
  · simp [coeff_eq_zero_of_natDegree_lt $ lt_of_le_of_lt hN hi]
  · simpa [hi, revAt_le] using h (N - i)
  · 

Proof state:
case refine'_2.inr
R : Type u_1
r : R
inst✝ : CommRing R
P✝ P : R[X]
N : ℕ
hN : natDegree P ≤ N
h : ∀ (i : ℕ), IsNilpotent (coeff P i)
i : ℕ
hi : N < i
⊢ IsNilpotent (coeff (reflect N P) i)

Next tactic:
simpa [revAt_eq_self_of_lt hi] using h i
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  

Proof state:
R : Type u_1
r : R
inst✝ : CommRing R
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
⊢ IsUnit P

Next tactic:
induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  

Proof state:
case h
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
⊢ IsUnit P

Next tactic:
by_cases hdeg : P.natDegree = 0
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  

Proof state:
case pos
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : natDegree P = 0
⊢ IsUnit P
case neg
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : ¬natDegree P = 0
⊢ IsUnit P

Next tactic:
{ rw [eq_C_of_natDegree_eq_zero hdeg]
    exact hunit.map C }
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  { 

Proof state:
case pos
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : natDegree P = 0
⊢ IsUnit P

Next tactic:
rw [eq_C_of_natDegree_eq_zero hdeg]
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  { rw [eq_C_of_natDegree_eq_zero hdeg]
    

Proof state:
case pos
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : natDegree P = 0
⊢ IsUnit (C (coeff P 0))

Next tactic:
exact hunit.map C
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  { rw [eq_C_of_natDegree_eq_zero hdeg]
    exact hunit.map C }
  

Proof state:
case neg
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : ¬natDegree P = 0
⊢ IsUnit P

Next tactic:
set P₁ := P.eraseLead with hP₁
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  { rw [eq_C_of_natDegree_eq_zero hdeg]
    exact hunit.map C }
  set P₁ := P.eraseLead with hP₁
  

Proof state:
case neg
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : ¬natDegree P = 0
P₁ : R[X] := eraseLead P
hP₁ : P₁ = eraseLead P
⊢ IsUnit P

Next tactic:
suffices IsUnit P₁ by
    rw [← eraseLead_add_monomial_natDegree_leadingCoeff P, ← C_mul_X_pow_eq_monomial]
    obtain ⟨Q, hQ⟩ := this
    rw [← hP₁, ← hQ]
    refine' Commute.IsNilpotent.add_isUnit (isNilpotent_C_mul_pow_X_of_isNilpotent _ (hnil _ hdeg))
      ((Commute.all _ _).mul_left (Commute.all _ _))
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  { rw [eq_C_of_natDegree_eq_zero hdeg]
    exact hunit.map C }
  set P₁ := P.eraseLead with hP₁
  suffices IsUnit P₁ by
    

Proof state:
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : ¬natDegree P = 0
P₁ : R[X] := eraseLead P
hP₁ : P₁ = eraseLead P
this : IsUnit P₁
⊢ IsUnit P

Next tactic:
rw [← eraseLead_add_monomial_natDegree_leadingCoeff P, ← C_mul_X_pow_eq_monomial]
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  { rw [eq_C_of_natDegree_eq_zero hdeg]
    exact hunit.map C }
  set P₁ := P.eraseLead with hP₁
  suffices IsUnit P₁ by
    rw [← eraseLead_add_monomial_natDegree_leadingCoeff P, ← C_mul_X_pow_eq_monomial]
    

Proof state:
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : ¬natDegree P = 0
P₁ : R[X] := eraseLead P
hP₁ : P₁ = eraseLead P
this : IsUnit P₁
⊢ IsUnit (eraseLead P + C (leadingCoeff P) * X ^ natDegree P)

Next tactic:
obtain ⟨Q, hQ⟩ := this
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  { rw [eq_C_of_natDegree_eq_zero hdeg]
    exact hunit.map C }
  set P₁ := P.eraseLead with hP₁
  suffices IsUnit P₁ by
    rw [← eraseLead_add_monomial_natDegree_leadingCoeff P, ← C_mul_X_pow_eq_monomial]
    obtain ⟨Q, hQ⟩ := this
    

Proof state:
case intro
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : ¬natDegree P = 0
P₁ : R[X] := eraseLead P
hP₁ : P₁ = eraseLead P
Q : R[X]ˣ
hQ : ↑Q = P₁
⊢ IsUnit (eraseLead P + C (leadingCoeff P) * X ^ natDegree P)

Next tactic:
rw [← hP₁, ← hQ]
/-- Let `P` be a polynomial over `R`. If its constant term is a unit and its other coefficients are
nilpotent, then `P` is a unit.

See also `Polynomial.isUnit_iff_coeff_isUnit_isNilpotent`. -/
theorem isUnit_of_coeff_isUnit_isNilpotent (hunit : IsUnit (P.coeff 0))
    (hnil : ∀ i, i ≠ 0 → IsNilpotent (P.coeff i)) : IsUnit P := by
  induction' h : P.natDegree using Nat.strong_induction_on with k hind generalizing P
  by_cases hdeg : P.natDegree = 0
  { rw [eq_C_of_natDegree_eq_zero hdeg]
    exact hunit.map C }
  set P₁ := P.eraseLead with hP₁
  suffices IsUnit P₁ by
    rw [← eraseLead_add_monomial_natDegree_leadingCoeff P, ← C_mul_X_pow_eq_monomial]
    obtain ⟨Q, hQ⟩ := this
    rw [← hP₁, ← hQ]
    

Proof state:
case intro
R : Type u_1
r : R
inst✝ : CommRing R
k : ℕ
hind :
  ∀ m < k, ∀ {P : R[X]}, IsUnit (coeff P 0) → (∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)) → natDegree P = m → IsUnit P
P : R[X]
hunit : IsUnit (coeff P 0)
hnil : ∀ (i : ℕ), i ≠ 0 → IsNilpotent (coeff P i)
h : natDegree P = k
hdeg : ¬natDegree P = 0
P₁ : R[X] := eraseLead P
hP₁ : P₁ = eraseLead P
Q : R[X]ˣ
hQ : ↑Q = P₁
⊢ IsUnit (↑Q + C (leadingCoeff P) * X ^ natDegree P)

Next tactic:
refine' Commute.IsNilpotent.add_isUnit (isNilpotent_C_mul_pow_X_of_isNilpotent _ (hnil _ hdeg))
      ((Commute.all _ _).mul_left (Commute.all _ _))