l3lab/ntp-mathlib huggingface dataset:
theorem ite_le_natDegree_coeff (p : R[X]) (n : ℕ) (I : Decidable (n < 1 + natDegree p)) :
    @ite _ (n < 1 + natDegree p) I (coeff p n) 0 = coeff p n := by
  split_ifs with h
  · 

Proof state:
case pos
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
n : ℕ
I : Decidable (n < 1 + natDegree p)
h : n < 1 + natDegree p
⊢ coeff p n = coeff p n

Next tactic:
rfl
theorem ite_le_natDegree_coeff (p : R[X]) (n : ℕ) (I : Decidable (n < 1 + natDegree p)) :
    @ite _ (n < 1 + natDegree p) I (coeff p n) 0 = coeff p n := by
  split_ifs with h
  · rfl
  · 

Proof state:
case neg
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
n : ℕ
I : Decidable (n < 1 + natDegree p)
h : ¬n < 1 + natDegree p
⊢ 0 = coeff p n

Next tactic:
exact (coeff_eq_zero_of_natDegree_lt (not_le.1 fun w => h (Nat.lt_one_add_iff.2 w))).symm
theorem as_sum_support_C_mul_X_pow (p : R[X]) : p = ∑ i in p.support, C (p.coeff i) * X ^ i :=
  _root_.trans p.as_sum_support <| by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
⊢ ∑ i in support p, (monomial i) (coeff p i) = ∑ i in support p, C (coeff p i) * X ^ i

Next tactic:
simp only [C_mul_X_pow_eq_monomial]
/-- We can reexpress a sum over `p.support` as a sum over `range n`,
for any `n` satisfying `p.natDegree < n`.
-/
theorem sum_over_range' [AddCommMonoid S] (p : R[X]) {f : ℕ → R → S} (h : ∀ n, f n 0 = 0) (n : ℕ)
    (w : p.natDegree < n) : p.sum f = ∑ a : ℕ in range n, f a (coeff p a) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : AddCommMonoid S
p : R[X]
f : ℕ → R → S
h : ∀ (n : ℕ), f n 0 = 0
n : ℕ
w : natDegree p < n
⊢ sum p f = ∑ a in range n, f a (coeff p a)

Next tactic:
rcases p with ⟨⟩
/-- We can reexpress a sum over `p.support` as a sum over `range n`,
for any `n` satisfying `p.natDegree < n`.
-/
theorem sum_over_range' [AddCommMonoid S] (p : R[X]) {f : ℕ → R → S} (h : ∀ n, f n 0 = 0) (n : ℕ)
    (w : p.natDegree < n) : p.sum f = ∑ a : ℕ in range n, f a (coeff p a) := by
  rcases p with ⟨⟩
  

Proof state:
case ofFinsupp
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : AddCommMonoid S
f : ℕ → R → S
h : ∀ (n : ℕ), f n 0 = 0
n : ℕ
toFinsupp✝ : AddMonoidAlgebra R ℕ
w : natDegree { toFinsupp := toFinsupp✝ } < n
⊢ sum { toFinsupp := toFinsupp✝ } f = ∑ a in range n, f a (coeff { toFinsupp := toFinsupp✝ } a)

Next tactic:
have := supp_subset_range w
/-- We can reexpress a sum over `p.support` as a sum over `range n`,
for any `n` satisfying `p.natDegree < n`.
-/
theorem sum_over_range' [AddCommMonoid S] (p : R[X]) {f : ℕ → R → S} (h : ∀ n, f n 0 = 0) (n : ℕ)
    (w : p.natDegree < n) : p.sum f = ∑ a : ℕ in range n, f a (coeff p a) := by
  rcases p with ⟨⟩
  have := supp_subset_range w
  

Proof state:
case ofFinsupp
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : AddCommMonoid S
f : ℕ → R → S
h : ∀ (n : ℕ), f n 0 = 0
n : ℕ
toFinsupp✝ : AddMonoidAlgebra R ℕ
w : natDegree { toFinsupp := toFinsupp✝ } < n
this : support { toFinsupp := toFinsupp✝ } ⊆ range n
⊢ sum { toFinsupp := toFinsupp✝ } f = ∑ a in range n, f a (coeff { toFinsupp := toFinsupp✝ } a)

Next tactic:
simp only [Polynomial.sum, support, coeff, natDegree, degree] at this ⊢
/-- We can reexpress a sum over `p.support` as a sum over `range n`,
for any `n` satisfying `p.natDegree < n`.
-/
theorem sum_over_range' [AddCommMonoid S] (p : R[X]) {f : ℕ → R → S} (h : ∀ n, f n 0 = 0) (n : ℕ)
    (w : p.natDegree < n) : p.sum f = ∑ a : ℕ in range n, f a (coeff p a) := by
  rcases p with ⟨⟩
  have := supp_subset_range w
  simp only [Polynomial.sum, support, coeff, natDegree, degree] at this ⊢
  

Proof state:
case ofFinsupp
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : AddCommMonoid S
f : ℕ → R → S
h : ∀ (n : ℕ), f n 0 = 0
n : ℕ
toFinsupp✝ : AddMonoidAlgebra R ℕ
w : natDegree { toFinsupp := toFinsupp✝ } < n
this : toFinsupp✝.support ⊆ range n
⊢ ∑ x in toFinsupp✝.support, f x (toFinsupp✝ x) = ∑ x in range n, f x (toFinsupp✝ x)

Next tactic:
exact Finsupp.sum_of_support_subset _ this _ fun n _hn => h n
theorem sum_fin [AddCommMonoid S] (f : ℕ → R → S) (hf : ∀ i, f i 0 = 0) {n : ℕ} {p : R[X]}
    (hn : p.degree < n) : (∑ i : Fin n, f i (p.coeff i)) = p.sum f := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : AddCommMonoid S
f : ℕ → R → S
hf : ∀ (i : ℕ), f i 0 = 0
n : ℕ
p : R[X]
hn : degree p < ↑n
⊢ ∑ i : Fin n, f (↑i) (coeff p ↑i) = sum p f

Next tactic:
by_cases hp : p = 0
theorem sum_fin [AddCommMonoid S] (f : ℕ → R → S) (hf : ∀ i, f i 0 = 0) {n : ℕ} {p : R[X]}
    (hn : p.degree < n) : (∑ i : Fin n, f i (p.coeff i)) = p.sum f := by
  by_cases hp : p = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : AddCommMonoid S
f : ℕ → R → S
hf : ∀ (i : ℕ), f i 0 = 0
n : ℕ
p : R[X]
hn : degree p < ↑n
hp : p = 0
⊢ ∑ i : Fin n, f (↑i) (coeff p ↑i) = sum p f

Next tactic:
rw [hp, sum_zero_index, Finset.sum_eq_zero]
theorem sum_fin [AddCommMonoid S] (f : ℕ → R → S) (hf : ∀ i, f i 0 = 0) {n : ℕ} {p : R[X]}
    (hn : p.degree < n) : (∑ i : Fin n, f i (p.coeff i)) = p.sum f := by
  by_cases hp : p = 0
  · rw [hp, sum_zero_index, Finset.sum_eq_zero]
    

Proof state:
case pos
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : AddCommMonoid S
f : ℕ → R → S
hf : ∀ (i : ℕ), f i 0 = 0
n : ℕ
p : R[X]
hn : degree p < ↑n
hp : p = 0
⊢ ∀ x ∈ univ, f (↑x) (coeff 0 ↑x) = 0

Next tactic:
intro i _
theorem sum_fin [AddCommMonoid S] (f : ℕ → R → S) (hf : ∀ i, f i 0 = 0) {n : ℕ} {p : R[X]}
    (hn : p.degree < n) : (∑ i : Fin n, f i (p.coeff i)) = p.sum f := by
  by_cases hp : p = 0
  · rw [hp, sum_zero_index, Finset.sum_eq_zero]
    intro i _
    

Proof state:
case pos
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : AddCommMonoid S
f : ℕ → R → S
hf : ∀ (i : ℕ), f i 0 = 0
n : ℕ
p : R[X]
hn : degree p < ↑n
hp : p = 0
i : Fin n
a✝ : i ∈ univ
⊢ f (↑i) (coeff 0 ↑i) = 0

Next tactic:
exact hf i
theorem sum_fin [AddCommMonoid S] (f : ℕ → R → S) (hf : ∀ i, f i 0 = 0) {n : ℕ} {p : R[X]}
    (hn : p.degree < n) : (∑ i : Fin n, f i (p.coeff i)) = p.sum f := by
  by_cases hp : p = 0
  · rw [hp, sum_zero_index, Finset.sum_eq_zero]
    intro i _
    exact hf i
  

Proof state:
case neg
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : AddCommMonoid S
f : ℕ → R → S
hf : ∀ (i : ℕ), f i 0 = 0
n : ℕ
p : R[X]
hn : degree p < ↑n
hp : ¬p = 0
⊢ ∑ i : Fin n, f (↑i) (coeff p ↑i) = sum p f

Next tactic:
rw [sum_over_range' _ hf n ((natDegree_lt_iff_degree_lt hp).mpr hn),
    Fin.sum_univ_eq_sum_range fun i => f i (p.coeff i)]
theorem as_sum_range_C_mul_X_pow (p : R[X]) :
    p = ∑ i in range (p.natDegree + 1), C (coeff p i) * X ^ i :=
  p.as_sum_range.trans <| by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
⊢ ∑ i in range (natDegree p + 1), (monomial i) (coeff p i) = ∑ i in range (natDegree p + 1), C (coeff p i) * X ^ i

Next tactic:
simp only [C_mul_X_pow_eq_monomial]
theorem eq_X_add_C_of_degree_le_one (h : degree p ≤ 1) : p = C (p.coeff 1) * X + C (p.coeff 0) :=
  ext fun n =>
    Nat.casesOn n (by 

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : degree p ≤ 1
n : ℕ
⊢ coeff p Nat.zero = coeff (C (coeff p 1) * X + C (coeff p 0)) Nat.zero

Next tactic:
simp
theorem eq_X_add_C_of_degree_le_one (h : degree p ≤ 1) : p = C (p.coeff 1) * X + C (p.coeff 0) :=
  ext fun n =>
    Nat.casesOn n (by simp) fun n =>
      Nat.casesOn n (by 

Proof state:
R : Type u
S : Type v
a b c d : R
n✝¹ m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : degree p ≤ 1
n✝ n : ℕ
⊢ coeff p (Nat.succ Nat.zero) = coeff (C (coeff p 1) * X + C (coeff p 0)) (Nat.succ Nat.zero)

Next tactic:
simp [coeff_C]
theorem eq_X_add_C_of_degree_le_one (h : degree p ≤ 1) : p = C (p.coeff 1) * X + C (p.coeff 0) :=
  ext fun n =>
    Nat.casesOn n (by simp) fun n =>
      Nat.casesOn n (by simp [coeff_C]) fun m => by
        -- Porting note: `by decide` → `Iff.mpr ..`
        

Proof state:
R : Type u
S : Type v
a b c d : R
n✝¹ m✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
h : degree p ≤ 1
n✝ n m : ℕ
⊢ coeff p (Nat.succ (Nat.succ m)) = coeff (C (coeff p 1) * X + C (coeff p 0)) (Nat.succ (Nat.succ m))

Next tactic:
have : degree p < m.succ.succ := lt_of_le_of_lt h
          (Iff.mpr WithBot.coe_lt_coe <| Nat.succ_lt_succ <| Nat.zero_lt_succ m)
theorem eq_X_add_C_of_degree_le_one (h : degree p ≤ 1) : p = C (p.coeff 1) * X + C (p.coeff 0) :=
  ext fun n =>
    Nat.casesOn n (by simp) fun n =>
      Nat.casesOn n (by simp [coeff_C]) fun m => by
        -- Porting note: `by decide` → `Iff.mpr ..`
        have : degree p < m.succ.succ := lt_of_le_of_lt h
          (Iff.mpr WithBot.coe_lt_coe <| Nat.succ_lt_succ <| Nat.zero_lt_succ m)
        

Proof state:
R : Type u
S : Type v
a b c d : R
n✝¹ m✝ : ℕ
inst✝ : Semiring R
p q r : R[X]
h : degree p ≤ 1
n✝ n m : ℕ
this : degree p < ↑(Nat.succ (Nat.succ m))
⊢ coeff p (Nat.succ (Nat.succ m)) = coeff (C (coeff p 1) * X + C (coeff p 0)) (Nat.succ (Nat.succ m))

Next tactic:
simp [coeff_eq_zero_of_degree_lt this, coeff_C, Nat.succ_ne_zero, coeff_X, Nat.succ_inj',
          @eq_comm ℕ 0]
theorem eq_X_add_C_of_degree_eq_one (h : degree p = 1) :
    p = C p.leadingCoeff * X + C (p.coeff 0) :=
  (eq_X_add_C_of_degree_le_one (show degree p ≤ 1 from h ▸ le_rfl)).trans
    (by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : degree p = 1
⊢ C (coeff p 1) * X + C (coeff p 0) = C (leadingCoeff p) * X + C (coeff p 0)

Next tactic:
simp only [leadingCoeff, natDegree_eq_of_degree_eq_some h]
theorem eq_X_add_C_of_degree_eq_one (h : degree p = 1) :
    p = C p.leadingCoeff * X + C (p.coeff 0) :=
  (eq_X_add_C_of_degree_le_one (show degree p ≤ 1 from h ▸ le_rfl)).trans
    (by simp only [leadingCoeff, natDegree_eq_of_degree_eq_some h]; 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : degree p = 1
⊢ C (coeff p 1) * X + C (coeff p 0) = C (coeff p One.one) * X + C (coeff p 0)

Next tactic:
rfl
theorem Monic.eq_X_add_C (hm : p.Monic) (hnd : p.natDegree = 1) : p = X + C (p.coeff 0) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
hm : Monic p
hnd : natDegree p = 1
⊢ p = X + C (coeff p 0)

Next tactic:
rw [← one_mul X, ← C_1, ← hm.coeff_natDegree, hnd, ← eq_X_add_C_of_natDegree_le_one hnd.le]
theorem degree_X_pow_le (n : ℕ) : degree (X ^ n : R[X]) ≤ n := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
⊢ degree (X ^ n) ≤ ↑n

Next tactic:
simpa only [C_1, one_mul] using degree_C_mul_X_pow_le n (1 : R)
theorem card_support_C_mul_X_pow_le_one {c : R} {n : ℕ} : card (support (C c * X ^ n)) ≤ 1 := by
  

Proof state:
R : Type u
S : Type v
a b c✝ d : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
c : R
n : ℕ
⊢ card (support (C c * X ^ n)) ≤ 1

Next tactic:
rw [← card_singleton n]
theorem card_support_C_mul_X_pow_le_one {c : R} {n : ℕ} : card (support (C c * X ^ n)) ≤ 1 := by
  rw [← card_singleton n]
  

Proof state:
R : Type u
S : Type v
a b c✝ d : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
c : R
n : ℕ
⊢ card (support (C c * X ^ n)) ≤ card {n}

Next tactic:
apply card_le_of_subset (support_C_mul_X_pow' n c)
theorem card_supp_le_succ_natDegree (p : R[X]) : p.support.card ≤ p.natDegree + 1 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
⊢ card (support p) ≤ natDegree p + 1

Next tactic:
rw [← Finset.card_range (p.natDegree + 1)]
theorem card_supp_le_succ_natDegree (p : R[X]) : p.support.card ≤ p.natDegree + 1 := by
  rw [← Finset.card_range (p.natDegree + 1)]
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
⊢ card (support p) ≤ card (range (natDegree p + 1))

Next tactic:
exact Finset.card_le_of_subset supp_subset_range_natDegree_succ
theorem nonempty_support_iff : p.support.Nonempty ↔ p ≠ 0 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ Finset.Nonempty (support p) ↔ p ≠ 0

Next tactic:
rw [Ne.def, nonempty_iff_ne_empty, Ne.def, ← support_eq_empty]
theorem coeff_mul_X_sub_C {p : R[X]} {r : R} {a : ℕ} :
    coeff (p * (X - C r)) (a + 1) = coeff p a - coeff p (a + 1) * r := by 

Proof state:
R : Type u
S : Type v
a✝ b c d : R
n m : ℕ
inst✝ : Ring R
p : R[X]
r : R
a : ℕ
⊢ coeff (p * (X - C r)) (a + 1) = coeff p a - coeff p (a + 1) * r

Next tactic:
simp [mul_sub]
@[simp]
theorem degree_neg (p : R[X]) : degree (-p) = degree p := by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Ring R
p : R[X]
⊢ degree (-p) = degree p

Next tactic:
unfold degree
@[simp]
theorem degree_neg (p : R[X]) : degree (-p) = degree p := by unfold degree; 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Ring R
p : R[X]
⊢ Finset.max (support (-p)) = Finset.max (support p)

Next tactic:
rw [support_neg]
@[simp]
theorem natDegree_neg (p : R[X]) : natDegree (-p) = natDegree p := by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Ring R
p : R[X]
⊢ natDegree (-p) = natDegree p

Next tactic:
simp [natDegree]
@[simp]
theorem natDegree_int_cast (n : ℤ) : natDegree (n : R[X]) = 0 := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Ring R
n : ℤ
⊢ natDegree ↑n = 0

Next tactic:
rw [← C_eq_int_cast, natDegree_C]
theorem degree_int_cast_le (n : ℤ) : degree (n : R[X]) ≤ 0 := degree_le_of_natDegree_le (by 

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Ring R
n : ℤ
⊢ natDegree ↑n ≤ Zero.zero

Next tactic:
simp
@[simp]
theorem leadingCoeff_neg (p : R[X]) : (-p).leadingCoeff = -p.leadingCoeff := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Ring R
p : R[X]
⊢ leadingCoeff (-p) = -leadingCoeff p

Next tactic:
rw [leadingCoeff, leadingCoeff, natDegree_neg, coeff_neg]
@[simp]
theorem nextCoeff_C_eq_zero (c : R) : nextCoeff (C c) = 0 := by
  

Proof state:
R : Type u
S : Type v
a b c✝ d : R
n m : ℕ
inst✝ : Semiring R
c : R
⊢ nextCoeff (C c) = 0

Next tactic:
rw [nextCoeff]
@[simp]
theorem nextCoeff_C_eq_zero (c : R) : nextCoeff (C c) = 0 := by
  rw [nextCoeff]
  

Proof state:
R : Type u
S : Type v
a b c✝ d : R
n m : ℕ
inst✝ : Semiring R
c : R
⊢ (if natDegree (C c) = 0 then 0 else coeff (C c) (natDegree (C c) - 1)) = 0

Next tactic:
simp
theorem nextCoeff_of_pos_natDegree (p : R[X]) (hp : 0 < p.natDegree) :
    nextCoeff p = p.coeff (p.natDegree - 1) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p : R[X]
hp : 0 < natDegree p
⊢ nextCoeff p = coeff p (natDegree p - 1)

Next tactic:
rw [nextCoeff, if_neg]
theorem nextCoeff_of_pos_natDegree (p : R[X]) (hp : 0 < p.natDegree) :
    nextCoeff p = p.coeff (p.natDegree - 1) := by
  rw [nextCoeff, if_neg]
  

Proof state:
case hnc
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p : R[X]
hp : 0 < natDegree p
⊢ ¬natDegree p = 0

Next tactic:
contrapose! hp
theorem nextCoeff_of_pos_natDegree (p : R[X]) (hp : 0 < p.natDegree) :
    nextCoeff p = p.coeff (p.natDegree - 1) := by
  rw [nextCoeff, if_neg]
  contrapose! hp
  

Proof state:
case hnc
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p : R[X]
hp : natDegree p = 0
⊢ natDegree p ≤ 0

Next tactic:
simpa
theorem ne_zero_of_degree_ge_degree (hpq : p.degree ≤ q.degree) (hp : p ≠ 0) : q ≠ 0 :=
  Polynomial.ne_zero_of_degree_gt
    (lt_of_lt_of_le (bot_lt_iff_ne_bot.mpr (by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hpq : degree p ≤ degree q
hp : p ≠ 0
⊢ degree p ≠ ⊥

Next tactic:
rwa [Ne.def, Polynomial.degree_eq_bot]
theorem ne_zero_of_natDegree_gt {n : ℕ} (h : n < natDegree p) : p ≠ 0 := fun H => by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
n : ℕ
h : n < natDegree p
H : p = 0
⊢ False

Next tactic:
simp [H, Nat.not_lt_zero] at h
theorem degree_lt_degree (h : natDegree p < natDegree q) : degree p < degree q := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : natDegree p < natDegree q
⊢ degree p < degree q

Next tactic:
by_cases hp : p = 0
theorem degree_lt_degree (h : natDegree p < natDegree q) : degree p < degree q := by
  by_cases hp : p = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : natDegree p < natDegree q
hp : p = 0
⊢ degree p < degree q

Next tactic:
simp [hp]
theorem degree_lt_degree (h : natDegree p < natDegree q) : degree p < degree q := by
  by_cases hp : p = 0
  · simp [hp]
    

Proof state:
case pos
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : natDegree p < natDegree q
hp : p = 0
⊢ ⊥ < degree q

Next tactic:
rw [bot_lt_iff_ne_bot]
theorem degree_lt_degree (h : natDegree p < natDegree q) : degree p < degree q := by
  by_cases hp : p = 0
  · simp [hp]
    rw [bot_lt_iff_ne_bot]
    

Proof state:
case pos
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : natDegree p < natDegree q
hp : p = 0
⊢ degree q ≠ ⊥

Next tactic:
intro hq
theorem degree_lt_degree (h : natDegree p < natDegree q) : degree p < degree q := by
  by_cases hp : p = 0
  · simp [hp]
    rw [bot_lt_iff_ne_bot]
    intro hq
    

Proof state:
case pos
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : natDegree p < natDegree q
hp : p = 0
hq : degree q = ⊥
⊢ False

Next tactic:
simp [hp, degree_eq_bot.mp hq, lt_irrefl] at h
theorem degree_lt_degree (h : natDegree p < natDegree q) : degree p < degree q := by
  by_cases hp : p = 0
  · simp [hp]
    rw [bot_lt_iff_ne_bot]
    intro hq
    simp [hp, degree_eq_bot.mp hq, lt_irrefl] at h
  · 

Proof state:
case neg
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : natDegree p < natDegree q
hp : ¬p = 0
⊢ degree p < degree q

Next tactic:
rwa [degree_eq_natDegree hp, degree_eq_natDegree <| ne_zero_of_natDegree_gt h, Nat.cast_lt]
theorem natDegree_lt_natDegree_iff (hp : p ≠ 0) : natDegree p < natDegree q ↔ degree p < degree q :=
  ⟨degree_lt_degree, fun h ↦ by
    

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hp : p ≠ 0
h : degree p < degree q
⊢ natDegree p < natDegree q

Next tactic:
have hq : q ≠ 0 := ne_zero_of_degree_gt h
theorem natDegree_lt_natDegree_iff (hp : p ≠ 0) : natDegree p < natDegree q ↔ degree p < degree q :=
  ⟨degree_lt_degree, fun h ↦ by
    have hq : q ≠ 0 := ne_zero_of_degree_gt h
    

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
hp : p ≠ 0
h : degree p < degree q
hq : q ≠ 0
⊢ natDegree p < natDegree q

Next tactic:
rwa [degree_eq_natDegree hp, degree_eq_natDegree hq, Nat.cast_lt] at h
theorem eq_C_of_degree_le_zero (h : degree p ≤ 0) : p = C (coeff p 0) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : degree p ≤ 0
⊢ p = C (coeff p 0)

Next tactic:
ext (_ | n)
theorem eq_C_of_degree_le_zero (h : degree p ≤ 0) : p = C (coeff p 0) := by
  ext (_ | n)
  · 

Proof state:
case a.zero
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : degree p ≤ 0
⊢ coeff p Nat.zero = coeff (C (coeff p 0)) Nat.zero

Next tactic:
simp
theorem eq_C_of_degree_le_zero (h : degree p ≤ 0) : p = C (coeff p 0) := by
  ext (_ | n)
  · simp
  

Proof state:
case a.succ
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : degree p ≤ 0
n : ℕ
⊢ coeff p (Nat.succ n) = coeff (C (coeff p 0)) (Nat.succ n)

Next tactic:
rw [coeff_C, if_neg (Nat.succ_ne_zero _), coeff_eq_zero_of_degree_lt]
theorem eq_C_of_degree_le_zero (h : degree p ≤ 0) : p = C (coeff p 0) := by
  ext (_ | n)
  · simp
  rw [coeff_C, if_neg (Nat.succ_ne_zero _), coeff_eq_zero_of_degree_lt]
  

Proof state:
case a.succ
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : degree p ≤ 0
n : ℕ
⊢ degree p < ↑(Nat.succ n)

Next tactic:
exact h.trans_lt (WithBot.some_lt_some.2 n.succ_pos)
theorem degree_add_le (p q : R[X]) : degree (p + q) ≤ max (degree p) (degree q) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q✝ : R[X]
ι : Type u_1
p q : R[X]
⊢ degree (p + q) ≤ max (degree p) (degree q)

Next tactic:
simpa only [degree, ← support_toFinsupp, toFinsupp_add]
    using AddMonoidAlgebra.sup_support_add_le _ _ _
theorem natDegree_add_le (p q : R[X]) : natDegree (p + q) ≤ max (natDegree p) (natDegree q) := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q✝ : R[X]
ι : Type u_1
p q : R[X]
⊢ natDegree (p + q) ≤ max (natDegree p) (natDegree q)

Next tactic:
cases' le_max_iff.1 (degree_add_le p q) with h h
theorem natDegree_add_le (p q : R[X]) : natDegree (p + q) ≤ max (natDegree p) (natDegree q) := by
  cases' le_max_iff.1 (degree_add_le p q) with h h <;> 

Proof state:
case inl
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q✝ : R[X]
ι : Type u_1
p q : R[X]
h : degree (p + q) ≤ degree p
⊢ natDegree (p + q) ≤ max (natDegree p) (natDegree q)

Next tactic:
simp [natDegree_le_natDegree h]
theorem natDegree_add_le (p q : R[X]) : natDegree (p + q) ≤ max (natDegree p) (natDegree q) := by
  cases' le_max_iff.1 (degree_add_le p q) with h h <;> 

Proof state:
case inr
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p✝ q✝ : R[X]
ι : Type u_1
p q : R[X]
h : degree (p + q) ≤ degree q
⊢ natDegree (p + q) ≤ max (natDegree p) (natDegree q)

Next tactic:
simp [natDegree_le_natDegree h]
theorem leadingCoeff_ne_zero : leadingCoeff p ≠ 0 ↔ p ≠ 0 := by 

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
⊢ leadingCoeff p ≠ 0 ↔ p ≠ 0

Next tactic:
rw [Ne.def, leadingCoeff_eq_zero]
theorem leadingCoeff_eq_zero_iff_deg_eq_bot : leadingCoeff p = 0 ↔ degree p = ⊥ := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
⊢ leadingCoeff p = 0 ↔ degree p = ⊥

Next tactic:
rw [leadingCoeff_eq_zero, degree_eq_bot]
theorem natDegree_mem_support_of_nonzero (H : p ≠ 0) : p.natDegree ∈ p.support := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
H : p ≠ 0
⊢ natDegree p ∈ support p

Next tactic:
rw [mem_support_iff]
theorem natDegree_mem_support_of_nonzero (H : p ≠ 0) : p.natDegree ∈ p.support := by
  rw [mem_support_iff]
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
H : p ≠ 0
⊢ coeff p (natDegree p) ≠ 0

Next tactic:
exact (not_congr leadingCoeff_eq_zero).mpr H
theorem degree_add_eq_left_of_degree_lt (h : degree q < degree p) : degree (p + q) = degree p :=
  le_antisymm (max_eq_left_of_lt h ▸ degree_add_le _ _) <|
    degree_le_degree <| by
      

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : degree q < degree p
⊢ coeff (p + q) (natDegree p) ≠ 0

Next tactic:
rw [coeff_add, coeff_natDegree_eq_zero_of_degree_lt h, add_zero]
theorem degree_add_eq_left_of_degree_lt (h : degree q < degree p) : degree (p + q) = degree p :=
  le_antisymm (max_eq_left_of_lt h ▸ degree_add_le _ _) <|
    degree_le_degree <| by
      rw [coeff_add, coeff_natDegree_eq_zero_of_degree_lt h, add_zero]
      

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : degree q < degree p
⊢ coeff p (natDegree p) ≠ 0

Next tactic:
exact mt leadingCoeff_eq_zero.1 (ne_zero_of_degree_gt h)
theorem degree_add_eq_right_of_degree_lt (h : degree p < degree q) : degree (p + q) = degree q := by
  

Proof state:
R : Type u
S : Type v
a b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
h : degree p < degree q
⊢ degree (p + q) = degree q

Next tactic:
rw [add_comm, degree_add_eq_left_of_degree_lt h]