l3lab/ntp-mathlib huggingface dataset:
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    

Proof state:
case intro
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
⊢ p %ₘ q = 0

Next tactic:
by_contra hpq0
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    

Proof state:
case intro
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
⊢ False

Next tactic:
have hmod : p %ₘ q = q * (r - p /ₘ q) := by rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    have hmod : p %ₘ q = q * (r - p /ₘ q) := by 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
⊢ p %ₘ q = q * (r - p /ₘ q)

Next tactic:
rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    have hmod : p %ₘ q = q * (r - p /ₘ q) := by rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
    

Proof state:
case intro
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
hmod : p %ₘ q = q * (r - p /ₘ q)
⊢ False

Next tactic:
have : degree (q * (r - p /ₘ q)) < degree q := hmod ▸ degree_modByMonic_lt _ hq
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    have hmod : p %ₘ q = q * (r - p /ₘ q) := by rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
    have : degree (q * (r - p /ₘ q)) < degree q := hmod ▸ degree_modByMonic_lt _ hq
    

Proof state:
case intro
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
hmod : p %ₘ q = q * (r - p /ₘ q)
this : degree (q * (r - p /ₘ q)) < degree q
⊢ False

Next tactic:
have hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0 := fun h =>
      hpq0 <|
        leadingCoeff_eq_zero.1
          (by rw [hmod, leadingCoeff_eq_zero.1 h, mul_zero, leadingCoeff_zero])
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    have hmod : p %ₘ q = q * (r - p /ₘ q) := by rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
    have : degree (q * (r - p /ₘ q)) < degree q := hmod ▸ degree_modByMonic_lt _ hq
    have hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0 := fun h =>
      hpq0 <|
        leadingCoeff_eq_zero.1
          (by 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h✝ : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
hmod : p %ₘ q = q * (r - p /ₘ q)
this : degree (q * (r - p /ₘ q)) < degree q
h : leadingCoeff (r - p /ₘ q) = 0
⊢ leadingCoeff (p %ₘ q) = 0

Next tactic:
rw [hmod, leadingCoeff_eq_zero.1 h, mul_zero, leadingCoeff_zero]
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    have hmod : p %ₘ q = q * (r - p /ₘ q) := by rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
    have : degree (q * (r - p /ₘ q)) < degree q := hmod ▸ degree_modByMonic_lt _ hq
    have hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0 := fun h =>
      hpq0 <|
        leadingCoeff_eq_zero.1
          (by rw [hmod, leadingCoeff_eq_zero.1 h, mul_zero, leadingCoeff_zero])
    

Proof state:
case intro
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
hmod : p %ₘ q = q * (r - p /ₘ q)
this : degree (q * (r - p /ₘ q)) < degree q
hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0
⊢ False

Next tactic:
have hlc : leadingCoeff q * leadingCoeff (r - p /ₘ q) ≠ 0 := by rwa [Monic.def.1 hq, one_mul]
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    have hmod : p %ₘ q = q * (r - p /ₘ q) := by rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
    have : degree (q * (r - p /ₘ q)) < degree q := hmod ▸ degree_modByMonic_lt _ hq
    have hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0 := fun h =>
      hpq0 <|
        leadingCoeff_eq_zero.1
          (by rw [hmod, leadingCoeff_eq_zero.1 h, mul_zero, leadingCoeff_zero])
    have hlc : leadingCoeff q * leadingCoeff (r - p /ₘ q) ≠ 0 := by 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
hmod : p %ₘ q = q * (r - p /ₘ q)
this : degree (q * (r - p /ₘ q)) < degree q
hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0
⊢ leadingCoeff q * leadingCoeff (r - p /ₘ q) ≠ 0

Next tactic:
rwa [Monic.def.1 hq, one_mul]
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    have hmod : p %ₘ q = q * (r - p /ₘ q) := by rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
    have : degree (q * (r - p /ₘ q)) < degree q := hmod ▸ degree_modByMonic_lt _ hq
    have hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0 := fun h =>
      hpq0 <|
        leadingCoeff_eq_zero.1
          (by rw [hmod, leadingCoeff_eq_zero.1 h, mul_zero, leadingCoeff_zero])
    have hlc : leadingCoeff q * leadingCoeff (r - p /ₘ q) ≠ 0 := by rwa [Monic.def.1 hq, one_mul]
    

Proof state:
case intro
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
hmod : p %ₘ q = q * (r - p /ₘ q)
this : degree (q * (r - p /ₘ q)) < degree q
hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0
hlc : leadingCoeff q * leadingCoeff (r - p /ₘ q) ≠ 0
⊢ False

Next tactic:
rw [degree_mul' hlc, degree_eq_natDegree hq.ne_zero,
      degree_eq_natDegree (mt leadingCoeff_eq_zero.2 hrpq0)] at this
theorem dvd_iff_modByMonic_eq_zero (hq : Monic q) : p %ₘ q = 0 ↔ q ∣ p :=
  ⟨fun h => by rw [← modByMonic_add_div p hq, h, zero_add]; exact dvd_mul_right _ _, fun h => by
    nontriviality R
    obtain ⟨r, hr⟩ := exists_eq_mul_right_of_dvd h
    by_contra hpq0
    have hmod : p %ₘ q = q * (r - p /ₘ q) := by rw [modByMonic_eq_sub_mul_div _ hq, mul_sub, ← hr]
    have : degree (q * (r - p /ₘ q)) < degree q := hmod ▸ degree_modByMonic_lt _ hq
    have hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0 := fun h =>
      hpq0 <|
        leadingCoeff_eq_zero.1
          (by rw [hmod, leadingCoeff_eq_zero.1 h, mul_zero, leadingCoeff_zero])
    have hlc : leadingCoeff q * leadingCoeff (r - p /ₘ q) ≠ 0 := by rwa [Monic.def.1 hq, one_mul]
    rw [degree_mul' hlc, degree_eq_natDegree hq.ne_zero,
      degree_eq_natDegree (mt leadingCoeff_eq_zero.2 hrpq0)] at this
    

Proof state:
case intro
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
h : q ∣ p
✝ : Nontrivial R
r : R[X]
hr : p = q * r
hpq0 : ¬p %ₘ q = 0
hmod : p %ₘ q = q * (r - p /ₘ q)
this : ↑(natDegree q) + ↑(natDegree (r - p /ₘ q)) < ↑(natDegree q)
hrpq0 : leadingCoeff (r - p /ₘ q) ≠ 0
hlc : leadingCoeff q * leadingCoeff (r - p /ₘ q) ≠ 0
⊢ False

Next tactic:
exact not_lt_of_ge (Nat.le_add_right _ _) (WithBot.some_lt_some.1 this)
theorem map_dvd_map [Ring S] (f : R →+* S) (hf : Function.Injective f) {x y : R[X]}
    (hx : x.Monic) : x.map f ∣ y.map f ↔ x ∣ y := by
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝¹ : Ring R
p q : R[X]
inst✝ : Ring S
f : R →+* S
hf : Function.Injective ⇑f
x y : R[X]
hx : Monic x
⊢ map f x ∣ map f y ↔ x ∣ y

Next tactic:
rw [← dvd_iff_modByMonic_eq_zero hx, ← dvd_iff_modByMonic_eq_zero (hx.map f), ←
    map_modByMonic f hx]
theorem map_dvd_map [Ring S] (f : R →+* S) (hf : Function.Injective f) {x y : R[X]}
    (hx : x.Monic) : x.map f ∣ y.map f ↔ x ∣ y := by
  rw [← dvd_iff_modByMonic_eq_zero hx, ← dvd_iff_modByMonic_eq_zero (hx.map f), ←
    map_modByMonic f hx]
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝¹ : Ring R
p q : R[X]
inst✝ : Ring S
f : R →+* S
hf : Function.Injective ⇑f
x y : R[X]
hx : Monic x
⊢ map f (y %ₘ x) = 0 ↔ y %ₘ x = 0

Next tactic:
exact
    ⟨fun H => map_injective f hf <| by rw [H, Polynomial.map_zero], fun H => by
      rw [H, Polynomial.map_zero]⟩
theorem map_dvd_map [Ring S] (f : R →+* S) (hf : Function.Injective f) {x y : R[X]}
    (hx : x.Monic) : x.map f ∣ y.map f ↔ x ∣ y := by
  rw [← dvd_iff_modByMonic_eq_zero hx, ← dvd_iff_modByMonic_eq_zero (hx.map f), ←
    map_modByMonic f hx]
  exact
    ⟨fun H => map_injective f hf <| by 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝¹ : Ring R
p q : R[X]
inst✝ : Ring S
f : R →+* S
hf : Function.Injective ⇑f
x y : R[X]
hx : Monic x
H : map f (y %ₘ x) = 0
⊢ map f (y %ₘ x) = map f 0

Next tactic:
rw [H, Polynomial.map_zero]
theorem map_dvd_map [Ring S] (f : R →+* S) (hf : Function.Injective f) {x y : R[X]}
    (hx : x.Monic) : x.map f ∣ y.map f ↔ x ∣ y := by
  rw [← dvd_iff_modByMonic_eq_zero hx, ← dvd_iff_modByMonic_eq_zero (hx.map f), ←
    map_modByMonic f hx]
  exact
    ⟨fun H => map_injective f hf <| by rw [H, Polynomial.map_zero], fun H => by
      

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝¹ : Ring R
p q : R[X]
inst✝ : Ring S
f : R →+* S
hf : Function.Injective ⇑f
x y : R[X]
hx : Monic x
H : y %ₘ x = 0
⊢ map f (y %ₘ x) = 0

Next tactic:
rw [H, Polynomial.map_zero]
@[simp]
theorem modByMonic_one (p : R[X]) : p %ₘ 1 = 0 :=
  (dvd_iff_modByMonic_eq_zero (by 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q p : R[X]
⊢ Monic 1

Next tactic:
convert monic_one (R := R)
@[simp]
theorem divByMonic_one (p : R[X]) : p /ₘ 1 = p := by
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q p : R[X]
⊢ p /ₘ 1 = p

Next tactic:
conv_rhs => rw [← modByMonic_add_div p monic_one]; simp
@[simp]
theorem divByMonic_one (p : R[X]) : p /ₘ 1 = p := by
  conv_rhs => 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q p : R[X]
| p

Next tactic:
rw [← modByMonic_add_div p monic_one]; simp
@[simp]
theorem divByMonic_one (p : R[X]) : p /ₘ 1 = p := by
  conv_rhs => 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q p : R[X]
| p

Next tactic:
rw [← modByMonic_add_div p monic_one]
@[simp]
theorem divByMonic_one (p : R[X]) : p /ₘ 1 = p := by
  conv_rhs => rw [← modByMonic_add_div p monic_one]; 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q p : R[X]
| p %ₘ 1 + 1 * (p /ₘ 1)

Next tactic:
simp
theorem sum_modByMonic_coeff (hq : q.Monic) {n : ℕ} (hn : q.degree ≤ n) :
    (∑ i : Fin n, monomial i ((p %ₘ q).coeff i)) = p %ₘ q := by
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
n : ℕ
hn : degree q ≤ ↑n
⊢ ∑ i : Fin n, (monomial ↑i) (coeff (p %ₘ q) ↑i) = p %ₘ q

Next tactic:
nontriviality R
theorem sum_modByMonic_coeff (hq : q.Monic) {n : ℕ} (hn : q.degree ≤ n) :
    (∑ i : Fin n, monomial i ((p %ₘ q).coeff i)) = p %ₘ q := by
  nontriviality R
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
n : ℕ
hn : degree q ≤ ↑n
✝ : Nontrivial R
⊢ ∑ i : Fin n, (monomial ↑i) (coeff (p %ₘ q) ↑i) = p %ₘ q

Next tactic:
exact
    (sum_fin (fun i c => monomial i c) (by simp) ((degree_modByMonic_lt _ hq).trans_le hn)).trans
      (sum_monomial_eq _)
theorem sum_modByMonic_coeff (hq : q.Monic) {n : ℕ} (hn : q.degree ≤ n) :
    (∑ i : Fin n, monomial i ((p %ₘ q).coeff i)) = p %ₘ q := by
  nontriviality R
  exact
    (sum_fin (fun i c => monomial i c) (by 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n✝ : ℕ
inst✝ : Ring R
p q : R[X]
hq : Monic q
n : ℕ
hn : degree q ≤ ↑n
✝ : Nontrivial R
⊢ ∀ (i : ℕ), (fun i c => (monomial i) c) i 0 = 0

Next tactic:
simp
theorem mul_div_mod_by_monic_cancel_left (p : R[X]) {q : R[X]} (hmo : q.Monic) :
    q * p /ₘ q = p := by
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q✝ p q : R[X]
hmo : Monic q
⊢ q * p /ₘ q = p

Next tactic:
nontriviality R
theorem mul_div_mod_by_monic_cancel_left (p : R[X]) {q : R[X]} (hmo : q.Monic) :
    q * p /ₘ q = p := by
  nontriviality R
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q✝ p q : R[X]
hmo : Monic q
✝ : Nontrivial R
⊢ q * p /ₘ q = p

Next tactic:
refine' (div_modByMonic_unique _ 0 hmo ⟨by rw [zero_add], _⟩).1
theorem mul_div_mod_by_monic_cancel_left (p : R[X]) {q : R[X]} (hmo : q.Monic) :
    q * p /ₘ q = p := by
  nontriviality R
  refine' (div_modByMonic_unique _ 0 hmo ⟨by 

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q✝ p q : R[X]
hmo : Monic q
✝ : Nontrivial R
⊢ 0 + q * p = q * p

Next tactic:
rw [zero_add]
theorem mul_div_mod_by_monic_cancel_left (p : R[X]) {q : R[X]} (hmo : q.Monic) :
    q * p /ₘ q = p := by
  nontriviality R
  refine' (div_modByMonic_unique _ 0 hmo ⟨by rw [zero_add], _⟩).1
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q✝ p q : R[X]
hmo : Monic q
✝ : Nontrivial R
⊢ degree 0 < degree q

Next tactic:
rw [degree_zero]
theorem mul_div_mod_by_monic_cancel_left (p : R[X]) {q : R[X]} (hmo : q.Monic) :
    q * p /ₘ q = p := by
  nontriviality R
  refine' (div_modByMonic_unique _ 0 hmo ⟨by rw [zero_add], _⟩).1
  rw [degree_zero]
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a b : R
n : ℕ
inst✝ : Ring R
p✝ q✝ p q : R[X]
hmo : Monic q
✝ : Nontrivial R
⊢ ⊥ < degree q

Next tactic:
exact Ne.bot_lt fun h => hmo.ne_zero (degree_eq_bot.1 h)
lemma coeff_divByMonic_X_sub_C_rec (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = coeff p (n + 1) + a * (p /ₘ (X - C a)).coeff (n + 1) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n : ℕ
⊢ coeff (p /ₘ (X - C a)) n = coeff p (n + 1) + a * coeff (p /ₘ (X - C a)) (n + 1)

Next tactic:
nontriviality R
lemma coeff_divByMonic_X_sub_C_rec (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = coeff p (n + 1) + a * (p /ₘ (X - C a)).coeff (n + 1) := by
  nontriviality R
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n : ℕ
✝ : Nontrivial R
⊢ coeff (p /ₘ (X - C a)) n = coeff p (n + 1) + a * coeff (p /ₘ (X - C a)) (n + 1)

Next tactic:
have := monic_X_sub_C a
lemma coeff_divByMonic_X_sub_C_rec (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = coeff p (n + 1) + a * (p /ₘ (X - C a)).coeff (n + 1) := by
  nontriviality R
  have := monic_X_sub_C a
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n : ℕ
✝ : Nontrivial R
this : Monic (X - C a)
⊢ coeff (p /ₘ (X - C a)) n = coeff p (n + 1) + a * coeff (p /ₘ (X - C a)) (n + 1)

Next tactic:
set q := p /ₘ (X - C a)
lemma coeff_divByMonic_X_sub_C_rec (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = coeff p (n + 1) + a * (p /ₘ (X - C a)).coeff (n + 1) := by
  nontriviality R
  have := monic_X_sub_C a
  set q := p /ₘ (X - C a)
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝ : ℕ
inst✝ : Ring R
p✝ q✝ p : R[X]
a : R
n : ℕ
✝ : Nontrivial R
this : Monic (X - C a)
q : R[X] := p /ₘ (X - C a)
⊢ coeff q n = coeff p (n + 1) + a * coeff q (n + 1)

Next tactic:
rw [← p.modByMonic_add_div this]
lemma coeff_divByMonic_X_sub_C_rec (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = coeff p (n + 1) + a * (p /ₘ (X - C a)).coeff (n + 1) := by
  nontriviality R
  have := monic_X_sub_C a
  set q := p /ₘ (X - C a)
  rw [← p.modByMonic_add_div this]
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝ : ℕ
inst✝ : Ring R
p✝ q✝ p : R[X]
a : R
n : ℕ
✝ : Nontrivial R
this : Monic (X - C a)
q : R[X] := p /ₘ (X - C a)
⊢ coeff q n = coeff (p %ₘ (X - C a) + (X - C a) * (p /ₘ (X - C a))) (n + 1) + a * coeff q (n + 1)

Next tactic:
have : degree (p %ₘ (X - C a)) < ↑(n + 1) := degree_X_sub_C a ▸ p.degree_modByMonic_lt this
    |>.trans_le <| WithBot.coe_le_coe.mpr le_add_self
lemma coeff_divByMonic_X_sub_C_rec (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = coeff p (n + 1) + a * (p /ₘ (X - C a)).coeff (n + 1) := by
  nontriviality R
  have := monic_X_sub_C a
  set q := p /ₘ (X - C a)
  rw [← p.modByMonic_add_div this]
  have : degree (p %ₘ (X - C a)) < ↑(n + 1) := degree_X_sub_C a ▸ p.degree_modByMonic_lt this
    |>.trans_le <| WithBot.coe_le_coe.mpr le_add_self
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝ : ℕ
inst✝ : Ring R
p✝ q✝ p : R[X]
a : R
n : ℕ
✝ : Nontrivial R
this✝ : Monic (X - C a)
q : R[X] := p /ₘ (X - C a)
this : degree (p %ₘ (X - C a)) < ↑(n + 1)
⊢ coeff q n = coeff (p %ₘ (X - C a) + (X - C a) * (p /ₘ (X - C a))) (n + 1) + a * coeff q (n + 1)

Next tactic:
simp [sub_mul, add_sub, coeff_eq_zero_of_degree_lt this]
theorem coeff_divByMonic_X_sub_C (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = ∑ i in Icc (n + 1) p.natDegree, a ^ (i - (n + 1)) * p.coeff i := by
  

Proof state:
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n : ℕ
⊢ coeff (p /ₘ (X - C a)) n = ∑ i in Icc (n + 1) (natDegree p), a ^ (i - (n + 1)) * coeff p i

Next tactic:
wlog h : p.natDegree ≤ n generalizing n
theorem coeff_divByMonic_X_sub_C (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = ∑ i in Icc (n + 1) p.natDegree, a ^ (i - (n + 1)) * p.coeff i := by
  wlog h : p.natDegree ≤ n generalizing n
  · 

Proof state:
case inr
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n : ℕ
this :
  ∀ (n : ℕ),
    natDegree p ≤ n → coeff (p /ₘ (X - C a)) n = ∑ i in Icc (n + 1) (natDegree p), a ^ (i - (n + 1)) * coeff p i
h : ¬natDegree p ≤ n
⊢ coeff (p /ₘ (X - C a)) n = ∑ i in Icc (n + 1) (natDegree p), a ^ (i - (n + 1)) * coeff p i

Next tactic:
refine Nat.decreasingInduction' (fun n hn _ ih ↦ ?_) (le_of_not_le h) ?_
theorem coeff_divByMonic_X_sub_C (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = ∑ i in Icc (n + 1) p.natDegree, a ^ (i - (n + 1)) * p.coeff i := by
  wlog h : p.natDegree ≤ n generalizing n
  · refine Nat.decreasingInduction' (fun n hn _ ih ↦ ?_) (le_of_not_le h) ?_
    · 

Proof state:
case inr.refine_1
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝¹ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n✝ : ℕ
this :
  ∀ (n : ℕ),
    natDegree p ≤ n → coeff (p /ₘ (X - C a)) n = ∑ i in Icc (n + 1) (natDegree p), a ^ (i - (n + 1)) * coeff p i
h : ¬natDegree p ≤ n✝
n : ℕ
hn : n < natDegree p
x✝ : n✝ ≤ n
ih : coeff (p /ₘ (X - C a)) (n + 1) = ∑ i in Icc (n + 1 + 1) (natDegree p), a ^ (i - (n + 1 + 1)) * coeff p i
⊢ coeff (p /ₘ (X - C a)) n = ∑ i in Icc (n + 1) (natDegree p), a ^ (i - (n + 1)) * coeff p i

Next tactic:
rw [coeff_divByMonic_X_sub_C_rec, ih, eq_comm, Icc_eq_cons_Ioc (Nat.succ_le.mpr hn),
          sum_cons, Nat.sub_self, pow_zero, one_mul, mul_sum]
theorem coeff_divByMonic_X_sub_C (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = ∑ i in Icc (n + 1) p.natDegree, a ^ (i - (n + 1)) * p.coeff i := by
  wlog h : p.natDegree ≤ n generalizing n
  · refine Nat.decreasingInduction' (fun n hn _ ih ↦ ?_) (le_of_not_le h) ?_
    · rw [coeff_divByMonic_X_sub_C_rec, ih, eq_comm, Icc_eq_cons_Ioc (Nat.succ_le.mpr hn),
          sum_cons, Nat.sub_self, pow_zero, one_mul, mul_sum]
      

Proof state:
case inr.refine_1
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝¹ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n✝ : ℕ
this :
  ∀ (n : ℕ),
    natDegree p ≤ n → coeff (p /ₘ (X - C a)) n = ∑ i in Icc (n + 1) (natDegree p), a ^ (i - (n + 1)) * coeff p i
h : ¬natDegree p ≤ n✝
n : ℕ
hn : n < natDegree p
x✝ : n✝ ≤ n
ih : coeff (p /ₘ (X - C a)) (n + 1) = ∑ i in Icc (n + 1 + 1) (natDegree p), a ^ (i - (n + 1 + 1)) * coeff p i
⊢ coeff p (Nat.succ n) + ∑ x in Ioc (Nat.succ n) (natDegree p), a ^ (x - (n + 1)) * coeff p x =
    coeff p (n + 1) + ∑ x in Icc (n + 1 + 1) (natDegree p), a * (a ^ (x - (n + 1 + 1)) * coeff p x)

Next tactic:
congr 1
theorem coeff_divByMonic_X_sub_C (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = ∑ i in Icc (n + 1) p.natDegree, a ^ (i - (n + 1)) * p.coeff i := by
  wlog h : p.natDegree ≤ n generalizing n
  · refine Nat.decreasingInduction' (fun n hn _ ih ↦ ?_) (le_of_not_le h) ?_
    · rw [coeff_divByMonic_X_sub_C_rec, ih, eq_comm, Icc_eq_cons_Ioc (Nat.succ_le.mpr hn),
          sum_cons, Nat.sub_self, pow_zero, one_mul, mul_sum]
      congr 1; 

Proof state:
case inr.refine_1.e_a
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝¹ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n✝ : ℕ
this :
  ∀ (n : ℕ),
    natDegree p ≤ n → coeff (p /ₘ (X - C a)) n = ∑ i in Icc (n + 1) (natDegree p), a ^ (i - (n + 1)) * coeff p i
h : ¬natDegree p ≤ n✝
n : ℕ
hn : n < natDegree p
x✝ : n✝ ≤ n
ih : coeff (p /ₘ (X - C a)) (n + 1) = ∑ i in Icc (n + 1 + 1) (natDegree p), a ^ (i - (n + 1 + 1)) * coeff p i
⊢ ∑ x in Ioc (Nat.succ n) (natDegree p), a ^ (x - (n + 1)) * coeff p x =
    ∑ x in Icc (n + 1 + 1) (natDegree p), a * (a ^ (x - (n + 1 + 1)) * coeff p x)

Next tactic:
refine sum_congr ?_ fun i hi ↦ ?_
theorem coeff_divByMonic_X_sub_C (p : R[X]) (a : R) (n : ℕ) :
    (p /ₘ (X - C a)).coeff n = ∑ i in Icc (n + 1) p.natDegree, a ^ (i - (n + 1)) * p.coeff i := by
  wlog h : p.natDegree ≤ n generalizing n
  · refine Nat.decreasingInduction' (fun n hn _ ih ↦ ?_) (le_of_not_le h) ?_
    · rw [coeff_divByMonic_X_sub_C_rec, ih, eq_comm, Icc_eq_cons_Ioc (Nat.succ_le.mpr hn),
          sum_cons, Nat.sub_self, pow_zero, one_mul, mul_sum]
      congr 1; refine sum_congr ?_ fun i hi ↦ ?_
      · 

Proof state:
case inr.refine_1.e_a.refine_1
R : Type u
S : Type v
T : Type w
A : Type z
a✝ b : R
n✝¹ : ℕ
inst✝ : Ring R
p✝ q p : R[X]
a : R
n✝ : ℕ
this :
  ∀ (n : ℕ),
    natDegree p ≤ n → coeff (p /ₘ (X - C a)) n = ∑ i in Icc (n + 1) (natDegree p), a ^ (i - (n + 1)) * coeff p i
h : ¬natDegree p ≤ n✝
n : ℕ
hn : n < natDegree p
x✝ : n✝ ≤ n
ih : coeff (p /ₘ (X - C a)) (n + 1) = ∑ i in Icc (n + 1 + 1) (natDegree p), a ^ (i - (n + 1 + 1)) * coeff p i
⊢ Ioc (Nat.succ n) (natDegree p) = Icc (n + 1 + 1) (natDegree p)

Next tactic:
ext