l3lab/ntp-mathlib huggingface dataset:
theorem degree_mul_le (p q : R[X]) : degree (p * 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
p q : R[X]
⊢ degree (p * q) ≤ degree p + degree q

Next tactic:
simpa only [degree, ← support_toFinsupp, toFinsupp_mul]
    using AddMonoidAlgebra.sup_support_mul_le (WithBot.coe_add _ _).le _ _
theorem degree_pow_le (p : R[X]) : ∀ n : ℕ, degree (p ^ n) ≤ n • degree 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
p : R[X]
⊢ degree (p ^ 0) ≤ 0 • degree p

Next tactic:
rw [pow_zero, zero_nsmul]
theorem degree_pow_le (p : R[X]) : ∀ n : ℕ, degree (p ^ n) ≤ n • degree p
  | 0 => by rw [pow_zero, zero_nsmul]; 

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 : R[X]
⊢ degree 1 ≤ 0

Next tactic:
exact degree_one_le
theorem degree_pow_le (p : R[X]) : ∀ n : ℕ, degree (p ^ n) ≤ n • degree p
  | 0 => by rw [pow_zero, zero_nsmul]; exact degree_one_le
  | n + 1 =>
    calc
      degree (p ^ (n + 1)) ≤ degree p + degree (p ^ n) := 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 : R[X]
n : ℕ
⊢ degree (p ^ (n + 1)) ≤ degree p + degree (p ^ n)

Next tactic:
rw [pow_succ]
theorem degree_pow_le (p : R[X]) : ∀ n : ℕ, degree (p ^ n) ≤ n • degree p
  | 0 => by rw [pow_zero, zero_nsmul]; exact degree_one_le
  | n + 1 =>
    calc
      degree (p ^ (n + 1)) ≤ degree p + degree (p ^ n) := by
        rw [pow_succ]; 

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 : R[X]
n : ℕ
⊢ degree (p * p ^ n) ≤ degree p + degree (p ^ n)

Next tactic:
exact degree_mul_le _ _
theorem degree_pow_le (p : R[X]) : ∀ n : ℕ, degree (p ^ n) ≤ n • degree p
  | 0 => by rw [pow_zero, zero_nsmul]; exact degree_one_le
  | n + 1 =>
    calc
      degree (p ^ (n + 1)) ≤ degree p + degree (p ^ n) := by
        rw [pow_succ]; exact degree_mul_le _ _
      _ ≤ _ := 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 : R[X]
n : ℕ
⊢ degree p + degree (p ^ n) ≤ (n + 1) • degree p

Next tactic:
rw [succ_nsmul]
theorem degree_pow_le (p : R[X]) : ∀ n : ℕ, degree (p ^ n) ≤ n • degree p
  | 0 => by rw [pow_zero, zero_nsmul]; exact degree_one_le
  | n + 1 =>
    calc
      degree (p ^ (n + 1)) ≤ degree p + degree (p ^ n) := by
        rw [pow_succ]; exact degree_mul_le _ _
      _ ≤ _ := by rw [succ_nsmul]; 

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 : R[X]
n : ℕ
⊢ degree p + degree (p ^ n) ≤ degree p + n • degree p

Next tactic:
exact add_le_add le_rfl (degree_pow_le _ _)
theorem degree_pow_le_of_le {a : WithBot ℕ} (b : ℕ) (hp : degree p ≤ a) :
    degree (p ^ b) ≤ b * a := 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
a : WithBot ℕ
b : ℕ
hp : degree p ≤ a
⊢ degree (p ^ b) ≤ ↑b * a

Next tactic:
induction b with
  | zero => simp [degree_one_le]
  | succ n hn =>
      rw [Nat.cast_succ, add_mul, one_mul, pow_succ']
      exact degree_mul_le_of_le hn hp
theorem degree_pow_le_of_le {a : WithBot ℕ} (b : ℕ) (hp : degree p ≤ a) :
    degree (p ^ b) ≤ b * a := by
  induction b with
  

Proof state:
case zero
R : Type u
S : Type v
a✝ b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
a : WithBot ℕ
hp : degree p ≤ a
⊢ degree (p ^ Nat.zero) ≤ ↑Nat.zero * a

Next tactic:
| zero => simp [degree_one_le]
theorem degree_pow_le_of_le {a : WithBot ℕ} (b : ℕ) (hp : degree p ≤ a) :
    degree (p ^ b) ≤ b * a := by
  induction b with
  | zero => 

Proof state:
case zero
R : Type u
S : Type v
a✝ b c d : R
n m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
a : WithBot ℕ
hp : degree p ≤ a
⊢ degree (p ^ Nat.zero) ≤ ↑Nat.zero * a

Next tactic:
simp [degree_one_le]
theorem degree_pow_le_of_le {a : WithBot ℕ} (b : ℕ) (hp : degree p ≤ a) :
    degree (p ^ b) ≤ b * a := by
  induction b with
  | zero => simp [degree_one_le]
  

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

Next tactic:
| succ n hn =>
      rw [Nat.cast_succ, add_mul, one_mul, pow_succ']
      exact degree_mul_le_of_le hn hp
theorem degree_pow_le_of_le {a : WithBot ℕ} (b : ℕ) (hp : degree p ≤ a) :
    degree (p ^ b) ≤ b * a := by
  induction b with
  | zero => simp [degree_one_le]
  | succ n hn =>
      

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

Next tactic:
rw [Nat.cast_succ, add_mul, one_mul, pow_succ']
theorem degree_pow_le_of_le {a : WithBot ℕ} (b : ℕ) (hp : degree p ≤ a) :
    degree (p ^ b) ≤ b * a := by
  induction b with
  | zero => simp [degree_one_le]
  | succ n hn =>
      rw [Nat.cast_succ, add_mul, one_mul, pow_succ']
      

Proof state:
case succ
R : Type u
S : Type v
a✝ b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p q : R[X]
ι : Type u_1
a : WithBot ℕ
hp : degree p ≤ a
n : ℕ
hn : degree (p ^ n) ≤ ↑n * a
⊢ degree (p ^ n * p) ≤ ↑n * a + a

Next tactic:
exact degree_mul_le_of_le hn hp
@[simp]
theorem leadingCoeff_monomial (a : R) (n : ℕ) : leadingCoeff (monomial n a) = a := 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
a : R
n : ℕ
⊢ leadingCoeff ((monomial n) a) = a

Next tactic:
classical
  by_cases ha : a = 0
  · simp only [ha, (monomial n).map_zero, leadingCoeff_zero]
  · rw [leadingCoeff, natDegree_monomial, if_neg ha, coeff_monomial]
    simp
@[simp]
theorem leadingCoeff_monomial (a : R) (n : ℕ) : leadingCoeff (monomial n a) = a := by
  classical
  

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
a : R
n : ℕ
⊢ leadingCoeff ((monomial n) a) = a

Next tactic:
by_cases ha : a = 0
@[simp]
theorem leadingCoeff_monomial (a : R) (n : ℕ) : leadingCoeff (monomial n a) = a := by
  classical
  by_cases ha : a = 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
a : R
n : ℕ
ha : a = 0
⊢ leadingCoeff ((monomial n) a) = a

Next tactic:
simp only [ha, (monomial n).map_zero, leadingCoeff_zero]
@[simp]
theorem leadingCoeff_monomial (a : R) (n : ℕ) : leadingCoeff (monomial n a) = a := by
  classical
  by_cases ha : a = 0
  · simp only [ha, (monomial n).map_zero, leadingCoeff_zero]
  · 

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
a : R
n : ℕ
ha : ¬a = 0
⊢ leadingCoeff ((monomial n) a) = a

Next tactic:
rw [leadingCoeff, natDegree_monomial, if_neg ha, coeff_monomial]
@[simp]
theorem leadingCoeff_monomial (a : R) (n : ℕ) : leadingCoeff (monomial n a) = a := by
  classical
  by_cases ha : a = 0
  · simp only [ha, (monomial n).map_zero, leadingCoeff_zero]
  · rw [leadingCoeff, natDegree_monomial, if_neg ha, coeff_monomial]
    

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
a : R
n : ℕ
ha : ¬a = 0
⊢ (if n = n then a else 0) = a

Next tactic:
simp
theorem leadingCoeff_C_mul_X_pow (a : R) (n : ℕ) : leadingCoeff (C a * X ^ n) = a := 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
a : R
n : ℕ
⊢ leadingCoeff (C a * X ^ n) = a

Next tactic:
rw [C_mul_X_pow_eq_monomial, leadingCoeff_monomial]
theorem leadingCoeff_C_mul_X (a : R) : leadingCoeff (C a * X) = a := 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
a : R
⊢ leadingCoeff (C a * X) = a

Next tactic:
simpa only [pow_one] using leadingCoeff_C_mul_X_pow a 1
theorem leadingCoeff_X_pow (n : ℕ) : leadingCoeff ((X : R[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[X]
ι : Type u_1
n : ℕ
⊢ leadingCoeff (X ^ n) = 1

Next tactic:
simpa only [C_1, one_mul] using leadingCoeff_C_mul_X_pow (1 : R) n
theorem leadingCoeff_X : leadingCoeff (X : R[X]) = 1 := 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 X = 1

Next tactic:
simpa only [pow_one] using @leadingCoeff_X_pow R _ 1
theorem Monic.ne_zero {R : Type*} [Semiring R] [Nontrivial R] {p : R[X]} (hp : p.Monic) :
    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
R : Type u_2
inst✝¹ : Semiring R
inst✝ : Nontrivial R
p : R[X]
hp : Monic p
⊢ p ≠ 0

Next tactic:
rintro rfl
theorem Monic.ne_zero {R : Type*} [Semiring R] [Nontrivial R] {p : R[X]} (hp : p.Monic) :
    p ≠ 0 := by
  rintro rfl
  

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
R : Type u_2
inst✝¹ : Semiring R
inst✝ : Nontrivial R
hp : Monic 0
⊢ False

Next tactic:
simp [Monic] at hp
theorem Monic.ne_zero_of_ne (h : (0 : R) ≠ 1) {p : R[X]} (hp : p.Monic) : 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 : 0 ≠ 1
p : R[X]
hp : Monic p
⊢ p ≠ 0

Next tactic:
nontriviality R
theorem Monic.ne_zero_of_ne (h : (0 : R) ≠ 1) {p : R[X]} (hp : p.Monic) : p ≠ 0 := by
  nontriviality R
  

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 : 0 ≠ 1
p : R[X]
hp : Monic p
inst✝ : Nontrivial R
⊢ p ≠ 0

Next tactic:
exact hp.ne_zero
theorem monic_of_natDegree_le_of_coeff_eq_one (n : ℕ) (pn : p.natDegree ≤ n) (p1 : p.coeff n = 1) :
    Monic 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
n : ℕ
pn : natDegree p ≤ n
p1 : coeff p n = 1
⊢ Monic p

Next tactic:
unfold Monic
theorem monic_of_natDegree_le_of_coeff_eq_one (n : ℕ) (pn : p.natDegree ≤ n) (p1 : p.coeff n = 1) :
    Monic p := by
  unfold Monic
  

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 : ℕ
pn : natDegree p ≤ n
p1 : coeff p n = 1
⊢ leadingCoeff p = 1

Next tactic:
nontriviality
theorem monic_of_natDegree_le_of_coeff_eq_one (n : ℕ) (pn : p.natDegree ≤ n) (p1 : p.coeff n = 1) :
    Monic p := by
  unfold Monic
  nontriviality
  

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 : ℕ
pn : natDegree p ≤ n
p1 : coeff p n = 1
✝ : Nontrivial R
⊢ leadingCoeff p = 1

Next tactic:
refine' (congr_arg _ <| natDegree_eq_of_le_of_coeff_ne_zero pn _).trans p1
theorem monic_of_natDegree_le_of_coeff_eq_one (n : ℕ) (pn : p.natDegree ≤ n) (p1 : p.coeff n = 1) :
    Monic p := by
  unfold Monic
  nontriviality
  refine' (congr_arg _ <| natDegree_eq_of_le_of_coeff_ne_zero pn _).trans p1
  

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 : ℕ
pn : natDegree p ≤ n
p1 : coeff p n = 1
✝ : Nontrivial R
⊢ coeff p n ≠ 0

Next tactic:
exact ne_of_eq_of_ne p1 one_ne_zero
theorem leadingCoeff_add_of_degree_lt (h : degree p < degree q) :
    leadingCoeff (p + q) = leadingCoeff 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
⊢ leadingCoeff (p + q) = leadingCoeff q

Next tactic:
have : coeff p (natDegree q) = 0 := coeff_natDegree_eq_zero_of_degree_lt h
theorem leadingCoeff_add_of_degree_lt (h : degree p < degree q) :
    leadingCoeff (p + q) = leadingCoeff q := by
  have : coeff p (natDegree q) = 0 := coeff_natDegree_eq_zero_of_degree_lt 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
h : degree p < degree q
this : coeff p (natDegree q) = 0
⊢ leadingCoeff (p + q) = leadingCoeff q

Next tactic:
simp only [leadingCoeff, natDegree_eq_of_degree_eq (degree_add_eq_right_of_degree_lt h), this,
    coeff_add, zero_add]
theorem leadingCoeff_add_of_degree_lt' (h : degree q < degree p) :
    leadingCoeff (p + q) = leadingCoeff 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
h : degree q < degree p
⊢ leadingCoeff (p + q) = leadingCoeff p

Next tactic:
rw [add_comm]
theorem leadingCoeff_add_of_degree_lt' (h : degree q < degree p) :
    leadingCoeff (p + q) = leadingCoeff p := by
  rw [add_comm]
  

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
⊢ leadingCoeff (q + p) = leadingCoeff p

Next tactic:
exact leadingCoeff_add_of_degree_lt h
theorem leadingCoeff_add_of_degree_eq (h : degree p = degree q)
    (hlc : leadingCoeff p + leadingCoeff q ≠ 0) :
    leadingCoeff (p + q) = leadingCoeff p + leadingCoeff 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
hlc : leadingCoeff p + leadingCoeff q ≠ 0
⊢ leadingCoeff (p + q) = leadingCoeff p + leadingCoeff q

Next tactic:
have : natDegree (p + q) = natDegree p := by
    apply natDegree_eq_of_degree_eq
    rw [degree_add_eq_of_leadingCoeff_add_ne_zero hlc, h, max_self]
theorem leadingCoeff_add_of_degree_eq (h : degree p = degree q)
    (hlc : leadingCoeff p + leadingCoeff q ≠ 0) :
    leadingCoeff (p + q) = leadingCoeff p + leadingCoeff q := by
  have : natDegree (p + q) = natDegree 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
h : degree p = degree q
hlc : leadingCoeff p + leadingCoeff q ≠ 0
⊢ natDegree (p + q) = natDegree p

Next tactic:
apply natDegree_eq_of_degree_eq
theorem leadingCoeff_add_of_degree_eq (h : degree p = degree q)
    (hlc : leadingCoeff p + leadingCoeff q ≠ 0) :
    leadingCoeff (p + q) = leadingCoeff p + leadingCoeff q := by
  have : natDegree (p + q) = natDegree p := by
    apply natDegree_eq_of_degree_eq
    

Proof state:
case h
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
hlc : leadingCoeff p + leadingCoeff q ≠ 0
⊢ degree (p + q) = degree p

Next tactic:
rw [degree_add_eq_of_leadingCoeff_add_ne_zero hlc, h, max_self]
theorem leadingCoeff_add_of_degree_eq (h : degree p = degree q)
    (hlc : leadingCoeff p + leadingCoeff q ≠ 0) :
    leadingCoeff (p + q) = leadingCoeff p + leadingCoeff q := by
  have : natDegree (p + q) = natDegree p := by
    apply natDegree_eq_of_degree_eq
    rw [degree_add_eq_of_leadingCoeff_add_ne_zero hlc, h, max_self]
  

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
hlc : leadingCoeff p + leadingCoeff q ≠ 0
this : natDegree (p + q) = natDegree p
⊢ leadingCoeff (p + q) = leadingCoeff p + leadingCoeff q

Next tactic:
simp only [leadingCoeff, this, natDegree_eq_of_degree_eq h, coeff_add]
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (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]
⊢ ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 =
    coeff p (natDegree p) * coeff q (natDegree q)

Next tactic:
refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · 

Proof state:
case refine'_1
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]
⊢ ∀ b ∈ antidiagonal (natDegree p + natDegree q), b ≠ (natDegree p, natDegree q) → coeff p b.1 * coeff q b.2 = 0

Next tactic:
rintro ⟨i, j⟩ h₁ h₂
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · rintro ⟨i, j⟩ h₁ h₂
        

Proof state:
case refine'_1.mk
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]
i j : ℕ
h₁ : (i, j) ∈ antidiagonal (natDegree p + natDegree q)
h₂ : (i, j) ≠ (natDegree p, natDegree q)
⊢ coeff p (i, j).1 * coeff q (i, j).2 = 0

Next tactic:
rw [mem_antidiagonal] at h₁
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · rintro ⟨i, j⟩ h₁ h₂
        rw [mem_antidiagonal] at h₁
        

Proof state:
case refine'_1.mk
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]
i j : ℕ
h₁ : (i, j).1 + (i, j).2 = natDegree p + natDegree q
h₂ : (i, j) ≠ (natDegree p, natDegree q)
⊢ coeff p (i, j).1 * coeff q (i, j).2 = 0

Next tactic:
by_cases H : natDegree p < i
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · rintro ⟨i, j⟩ h₁ h₂
        rw [mem_antidiagonal] at h₁
        by_cases H : natDegree p < i
        · 

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
p q : R[X]
i j : ℕ
h₁ : (i, j).1 + (i, j).2 = natDegree p + natDegree q
h₂ : (i, j) ≠ (natDegree p, natDegree q)
H : natDegree p < i
⊢ coeff p (i, j).1 * coeff q (i, j).2 = 0

Next tactic:
rw [coeff_eq_zero_of_degree_lt
              (lt_of_le_of_lt degree_le_natDegree (WithBot.coe_lt_coe.2 H)),
            zero_mul]
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · rintro ⟨i, j⟩ h₁ h₂
        rw [mem_antidiagonal] at h₁
        by_cases H : natDegree p < i
        · rw [coeff_eq_zero_of_degree_lt
              (lt_of_le_of_lt degree_le_natDegree (WithBot.coe_lt_coe.2 H)),
            zero_mul]
        · 

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
p q : R[X]
i j : ℕ
h₁ : (i, j).1 + (i, j).2 = natDegree p + natDegree q
h₂ : (i, j) ≠ (natDegree p, natDegree q)
H : ¬natDegree p < i
⊢ coeff p (i, j).1 * coeff q (i, j).2 = 0

Next tactic:
rw [not_lt_iff_eq_or_lt] at H
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · rintro ⟨i, j⟩ h₁ h₂
        rw [mem_antidiagonal] at h₁
        by_cases H : natDegree p < i
        · rw [coeff_eq_zero_of_degree_lt
              (lt_of_le_of_lt degree_le_natDegree (WithBot.coe_lt_coe.2 H)),
            zero_mul]
        · rw [not_lt_iff_eq_or_lt] 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
p q : R[X]
i j : ℕ
h₁ : (i, j).1 + (i, j).2 = natDegree p + natDegree q
h₂ : (i, j) ≠ (natDegree p, natDegree q)
H : natDegree p = i ∨ i < natDegree p
⊢ coeff p (i, j).1 * coeff q (i, j).2 = 0

Next tactic:
cases' H with H H
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · rintro ⟨i, j⟩ h₁ h₂
        rw [mem_antidiagonal] at h₁
        by_cases H : natDegree p < i
        · rw [coeff_eq_zero_of_degree_lt
              (lt_of_le_of_lt degree_le_natDegree (WithBot.coe_lt_coe.2 H)),
            zero_mul]
        · rw [not_lt_iff_eq_or_lt] at H
          cases' H with H H
          · 

Proof state:
case neg.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]
i j : ℕ
h₁ : (i, j).1 + (i, j).2 = natDegree p + natDegree q
h₂ : (i, j) ≠ (natDegree p, natDegree q)
H : natDegree p = i
⊢ coeff p (i, j).1 * coeff q (i, j).2 = 0

Next tactic:
subst H
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · rintro ⟨i, j⟩ h₁ h₂
        rw [mem_antidiagonal] at h₁
        by_cases H : natDegree p < i
        · rw [coeff_eq_zero_of_degree_lt
              (lt_of_le_of_lt degree_le_natDegree (WithBot.coe_lt_coe.2 H)),
            zero_mul]
        · rw [not_lt_iff_eq_or_lt] at H
          cases' H with H H
          · subst H
            

Proof state:
case neg.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]
j : ℕ
h₁ : (natDegree p, j).1 + (natDegree p, j).2 = natDegree p + natDegree q
h₂ : (natDegree p, j) ≠ (natDegree p, natDegree q)
⊢ coeff p (natDegree p, j).1 * coeff q (natDegree p, j).2 = 0

Next tactic:
rw [add_left_cancel_iff] at h₁
@[simp]
theorem coeff_mul_degree_add_degree (p q : R[X]) :
    coeff (p * q) (natDegree p + natDegree q) = leadingCoeff p * leadingCoeff q :=
  calc
    coeff (p * q) (natDegree p + natDegree q) =
        ∑ x in antidiagonal (natDegree p + natDegree q), coeff p x.1 * coeff q x.2 :=
      coeff_mul _ _ _
    _ = coeff p (natDegree p) * coeff q (natDegree q) := by
      refine' Finset.sum_eq_single (natDegree p, natDegree q) _ _
      · rintro ⟨i, j⟩ h₁ h₂
        rw [mem_antidiagonal] at h₁
        by_cases H : natDegree p < i
        · rw [coeff_eq_zero_of_degree_lt
              (lt_of_le_of_lt degree_le_natDegree (WithBot.coe_lt_coe.2 H)),
            zero_mul]
        · rw [not_lt_iff_eq_or_lt] at H
          cases' H with H H
          · subst H
            rw [add_left_cancel_iff] at h₁
            

Proof state:
case neg.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]
j : ℕ
h₁ : (natDegree p, j).2 = natDegree q
h₂ : (natDegree p, j) ≠ (natDegree p, natDegree q)
⊢ coeff p (natDegree p, j).1 * coeff q (natDegree p, j).2 = 0

Next tactic:
dsimp at h₁