l3lab/ntp-mathlib huggingface dataset:
theorem natTrailingDegree_le_natTrailingDegree {hq : q ≠ 0}
    (hpq : p.trailingDegree ≤ q.trailingDegree) : p.natTrailingDegree ≤ q.natTrailingDegree := by
  by_cases hp : p = 0;
  · 

Proof state:
case pos
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
hq : q ≠ 0
hpq : trailingDegree p ≤ trailingDegree q
hp : p = 0
⊢ natTrailingDegree p ≤ natTrailingDegree q

Next tactic:
rw [hp, natTrailingDegree_zero]
theorem natTrailingDegree_le_natTrailingDegree {hq : q ≠ 0}
    (hpq : p.trailingDegree ≤ q.trailingDegree) : p.natTrailingDegree ≤ q.natTrailingDegree := by
  by_cases hp : p = 0;
  · rw [hp, natTrailingDegree_zero]
    

Proof state:
case pos
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
hq : q ≠ 0
hpq : trailingDegree p ≤ trailingDegree q
hp : p = 0
⊢ 0 ≤ natTrailingDegree q

Next tactic:
exact zero_le _
theorem natTrailingDegree_le_natTrailingDegree {hq : q ≠ 0}
    (hpq : p.trailingDegree ≤ q.trailingDegree) : p.natTrailingDegree ≤ q.natTrailingDegree := by
  by_cases hp : p = 0;
  · rw [hp, natTrailingDegree_zero]
    exact zero_le _
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
hq : q ≠ 0
hpq : trailingDegree p ≤ trailingDegree q
hp : ¬p = 0
⊢ natTrailingDegree p ≤ natTrailingDegree q

Next tactic:
rw [trailingDegree_eq_natTrailingDegree hp, trailingDegree_eq_natTrailingDegree hq] at hpq
theorem natTrailingDegree_le_natTrailingDegree {hq : q ≠ 0}
    (hpq : p.trailingDegree ≤ q.trailingDegree) : p.natTrailingDegree ≤ q.natTrailingDegree := by
  by_cases hp : p = 0;
  · rw [hp, natTrailingDegree_zero]
    exact zero_le _
  rw [trailingDegree_eq_natTrailingDegree hp, trailingDegree_eq_natTrailingDegree hq] at hpq
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
hq : q ≠ 0
hpq : ↑(natTrailingDegree p) ≤ ↑(natTrailingDegree q)
hp : ¬p = 0
⊢ natTrailingDegree p ≤ natTrailingDegree q

Next tactic:
exact WithTop.coe_le_coe.1 hpq
@[simp]
theorem trailingDegree_monomial (ha : a ≠ 0) : trailingDegree (monomial n a) = n := by
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
ha : a ≠ 0
⊢ trailingDegree ((monomial n) a) = ↑n

Next tactic:
rw [trailingDegree, support_monomial n ha, min_singleton]
@[simp]
theorem trailingDegree_monomial (ha : a ≠ 0) : trailingDegree (monomial n a) = n := by
  rw [trailingDegree, support_monomial n ha, min_singleton]
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
ha : a ≠ 0
⊢ ↑n = ↑n

Next tactic:
rfl
theorem natTrailingDegree_monomial (ha : a ≠ 0) : natTrailingDegree (monomial n a) = n := by
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
ha : a ≠ 0
⊢ natTrailingDegree ((monomial n) a) = n

Next tactic:
rw [natTrailingDegree, trailingDegree_monomial ha]
theorem natTrailingDegree_monomial (ha : a ≠ 0) : natTrailingDegree (monomial n a) = n := by
  rw [natTrailingDegree, trailingDegree_monomial ha]
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
ha : a ≠ 0
⊢ Option.getD (↑n) 0 = n

Next tactic:
rfl
theorem natTrailingDegree_monomial_le : natTrailingDegree (monomial n a) ≤ n :=
  letI := Classical.decEq R
  if ha : a = 0 then by 

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
this : DecidableEq R := Classical.decEq R
ha : a = 0
⊢ natTrailingDegree ((monomial n) a) ≤ n

Next tactic:
simp [ha]
theorem le_trailingDegree_monomial : ↑n ≤ trailingDegree (monomial n a) :=
  letI := Classical.decEq R
  if ha : a = 0 then by 

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
this : DecidableEq R := Classical.decEq R
ha : a = 0
⊢ ↑n ≤ trailingDegree ((monomial n) a)

Next tactic:
simp [ha]
theorem trailingDegree_one_le : (0 : ℕ∞) ≤ trailingDegree (1 : R[X]) := by
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ 0 ≤ trailingDegree 1

Next tactic:
rw [← C_1]
theorem trailingDegree_one_le : (0 : ℕ∞) ≤ trailingDegree (1 : R[X]) := by
  rw [← C_1]
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ 0 ≤ trailingDegree (C 1)

Next tactic:
exact le_trailingDegree_C
@[simp]
theorem natTrailingDegree_nat_cast (n : ℕ) : natTrailingDegree (n : R[X]) = 0 := by
  

Proof state:
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
⊢ natTrailingDegree ↑n = 0

Next tactic:
simp only [← C_eq_nat_cast, natTrailingDegree_C]
@[simp]
theorem trailingDegree_C_mul_X_pow (n : ℕ) (ha : a ≠ 0) : trailingDegree (C a * X ^ n) = n := by
  

Proof state:
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
ha : a ≠ 0
⊢ trailingDegree (C a * X ^ n) = ↑n

Next tactic:
rw [C_mul_X_pow_eq_monomial, trailingDegree_monomial ha]
theorem le_trailingDegree_C_mul_X_pow (n : ℕ) (a : R) :
    (n : ℕ∞) ≤ trailingDegree (C a * X ^ n) := by
  

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

Next tactic:
rw [C_mul_X_pow_eq_monomial]
theorem le_trailingDegree_C_mul_X_pow (n : ℕ) (a : R) :
    (n : ℕ∞) ≤ trailingDegree (C a * X ^ n) := by
  rw [C_mul_X_pow_eq_monomial]
  

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

Next tactic:
exact le_trailingDegree_monomial
theorem coeff_eq_zero_of_lt_natTrailingDegree {p : R[X]} {n : ℕ} (h : n < p.natTrailingDegree) :
    p.coeff n = 0 := by
  

Proof state:
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
n : ℕ
h : n < natTrailingDegree p
⊢ coeff p n = 0

Next tactic:
apply coeff_eq_zero_of_trailingDegree_lt
theorem coeff_eq_zero_of_lt_natTrailingDegree {p : R[X]} {n : ℕ} (h : n < p.natTrailingDegree) :
    p.coeff n = 0 := by
  apply coeff_eq_zero_of_trailingDegree_lt
  

Proof state:
case h
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
n : ℕ
h : n < natTrailingDegree p
⊢ ↑n < trailingDegree p

Next tactic:
by_cases hp : p = 0
theorem coeff_eq_zero_of_lt_natTrailingDegree {p : R[X]} {n : ℕ} (h : n < p.natTrailingDegree) :
    p.coeff n = 0 := by
  apply coeff_eq_zero_of_trailingDegree_lt
  by_cases hp : p = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
n : ℕ
h : n < natTrailingDegree p
hp : p = 0
⊢ ↑n < trailingDegree p

Next tactic:
rw [hp, trailingDegree_zero]
theorem coeff_eq_zero_of_lt_natTrailingDegree {p : R[X]} {n : ℕ} (h : n < p.natTrailingDegree) :
    p.coeff n = 0 := by
  apply coeff_eq_zero_of_trailingDegree_lt
  by_cases hp : p = 0
  · rw [hp, trailingDegree_zero]
    

Proof state:
case pos
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
n : ℕ
h : n < natTrailingDegree p
hp : p = 0
⊢ ↑n < ⊤

Next tactic:
exact WithTop.coe_lt_top n
theorem coeff_eq_zero_of_lt_natTrailingDegree {p : R[X]} {n : ℕ} (h : n < p.natTrailingDegree) :
    p.coeff n = 0 := by
  apply coeff_eq_zero_of_trailingDegree_lt
  by_cases hp : p = 0
  · rw [hp, trailingDegree_zero]
    exact WithTop.coe_lt_top n
  · 

Proof state:
case neg
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
n : ℕ
h : n < natTrailingDegree p
hp : ¬p = 0
⊢ ↑n < trailingDegree p

Next tactic:
rw [trailingDegree_eq_natTrailingDegree hp]
theorem coeff_eq_zero_of_lt_natTrailingDegree {p : R[X]} {n : ℕ} (h : n < p.natTrailingDegree) :
    p.coeff n = 0 := by
  apply coeff_eq_zero_of_trailingDegree_lt
  by_cases hp : p = 0
  · rw [hp, trailingDegree_zero]
    exact WithTop.coe_lt_top n
  · rw [trailingDegree_eq_natTrailingDegree hp]
    

Proof state:
case neg
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
n : ℕ
h : n < natTrailingDegree p
hp : ¬p = 0
⊢ ↑n < ↑(natTrailingDegree p)

Next tactic:
exact WithTop.coe_lt_coe.2 h
theorem le_trailingDegree_X_pow (n : ℕ) : (n : ℕ∞) ≤ trailingDegree (X ^ n : R[X]) := by
  

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

Next tactic:
simpa only [C_1, one_mul] using le_trailingDegree_C_mul_X_pow n (1 : R)
theorem natTrailingDegree_eq_support_min' (h : p ≠ 0) :
    natTrailingDegree p = p.support.min' (nonempty_support_iff.mpr h) := by
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p ≠ 0
⊢ natTrailingDegree p = min' (support p) (_ : Finset.Nonempty (support p))

Next tactic:
apply le_antisymm
theorem natTrailingDegree_eq_support_min' (h : p ≠ 0) :
    natTrailingDegree p = p.support.min' (nonempty_support_iff.mpr h) := by
  apply le_antisymm
  · 

Proof state:
case a
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p ≠ 0
⊢ natTrailingDegree p ≤ min' (support p) (_ : Finset.Nonempty (support p))

Next tactic:
apply le_min'
theorem natTrailingDegree_eq_support_min' (h : p ≠ 0) :
    natTrailingDegree p = p.support.min' (nonempty_support_iff.mpr h) := by
  apply le_antisymm
  · apply le_min'
    

Proof state:
case a.H2
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p ≠ 0
⊢ ∀ y ∈ support p, natTrailingDegree p ≤ y

Next tactic:
intro y hy
theorem natTrailingDegree_eq_support_min' (h : p ≠ 0) :
    natTrailingDegree p = p.support.min' (nonempty_support_iff.mpr h) := by
  apply le_antisymm
  · apply le_min'
    intro y hy
    

Proof state:
case a.H2
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p ≠ 0
y : ℕ
hy : y ∈ support p
⊢ natTrailingDegree p ≤ y

Next tactic:
exact natTrailingDegree_le_of_mem_supp y hy
theorem natTrailingDegree_eq_support_min' (h : p ≠ 0) :
    natTrailingDegree p = p.support.min' (nonempty_support_iff.mpr h) := by
  apply le_antisymm
  · apply le_min'
    intro y hy
    exact natTrailingDegree_le_of_mem_supp y hy
  · 

Proof state:
case a
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p ≠ 0
⊢ min' (support p) (_ : Finset.Nonempty (support p)) ≤ natTrailingDegree p

Next tactic:
apply Finset.min'_le
theorem natTrailingDegree_eq_support_min' (h : p ≠ 0) :
    natTrailingDegree p = p.support.min' (nonempty_support_iff.mpr h) := by
  apply le_antisymm
  · apply le_min'
    intro y hy
    exact natTrailingDegree_le_of_mem_supp y hy
  · apply Finset.min'_le
    

Proof state:
case a.H2
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p ≠ 0
⊢ natTrailingDegree p ∈ support p

Next tactic:
exact mem_support_iff.mpr (trailingCoeff_nonzero_iff_nonzero.mpr h)
theorem le_natTrailingDegree (hp : p ≠ 0) (hn : ∀ m < n, p.coeff m = 0) :
    n ≤ p.natTrailingDegree := by
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
hp : p ≠ 0
hn : ∀ m < n, coeff p m = 0
⊢ n ≤ natTrailingDegree p

Next tactic:
rw [natTrailingDegree_eq_support_min' hp]
theorem le_natTrailingDegree (hp : p ≠ 0) (hn : ∀ m < n, p.coeff m = 0) :
    n ≤ p.natTrailingDegree := by
  rw [natTrailingDegree_eq_support_min' hp]
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
hp : p ≠ 0
hn : ∀ m < n, coeff p m = 0
⊢ n ≤ min' (support p) (_ : Finset.Nonempty (support p))

Next tactic:
exact Finset.le_min' _ _ _ fun m hm => not_lt.1 fun hmn => mem_support_iff.1 hm <| hn _ hmn
theorem natTrailingDegree_le_natDegree (p : R[X]) : p.natTrailingDegree ≤ p.natDegree := by
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
⊢ natTrailingDegree p ≤ natDegree p

Next tactic:
by_cases hp : p = 0
theorem natTrailingDegree_le_natDegree (p : R[X]) : p.natTrailingDegree ≤ p.natDegree := by
  by_cases hp : p = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p = 0
⊢ natTrailingDegree p ≤ natDegree p

Next tactic:
rw [hp, natDegree_zero, natTrailingDegree_zero]
theorem natTrailingDegree_le_natDegree (p : R[X]) : p.natTrailingDegree ≤ p.natDegree := by
  by_cases hp : p = 0
  · rw [hp, natDegree_zero, natTrailingDegree_zero]
  · 

Proof state:
case neg
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : ¬p = 0
⊢ natTrailingDegree p ≤ natDegree p

Next tactic:
exact le_natDegree_of_ne_zero (mt trailingCoeff_eq_zero.mp hp)
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  

Proof state:
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n : ℕ
⊢ natTrailingDegree (p * X ^ n) = natTrailingDegree p + n

Next tactic:
apply le_antisymm
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · 

Proof state:
case a
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n : ℕ
⊢ natTrailingDegree (p * X ^ n) ≤ natTrailingDegree p + n

Next tactic:
refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
    

Proof state:
case a
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n : ℕ
h : coeff (p * X ^ n) (natTrailingDegree p + n) = 0
⊢ trailingCoeff p = 0

Next tactic:
rwa [trailingCoeff, ← coeff_mul_X_pow]
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
    rwa [trailingCoeff, ← coeff_mul_X_pow]
  · 

Proof state:
case a
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n : ℕ
⊢ natTrailingDegree p + n ≤ natTrailingDegree (p * X ^ n)

Next tactic:
rw [natTrailingDegree_eq_support_min' fun h => hp (mul_X_pow_eq_zero h), Finset.le_min'_iff]
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
    rwa [trailingCoeff, ← coeff_mul_X_pow]
  · rw [natTrailingDegree_eq_support_min' fun h => hp (mul_X_pow_eq_zero h), Finset.le_min'_iff]
    

Proof state:
case a
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n : ℕ
⊢ ∀ y ∈ support (p * X ^ n), natTrailingDegree p + n ≤ y

Next tactic:
intro y hy
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
    rwa [trailingCoeff, ← coeff_mul_X_pow]
  · rw [natTrailingDegree_eq_support_min' fun h => hp (mul_X_pow_eq_zero h), Finset.le_min'_iff]
    intro y hy
    

Proof state:
case a
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n y : ℕ
hy : y ∈ support (p * X ^ n)
⊢ natTrailingDegree p + n ≤ y

Next tactic:
have key : n ≤ y := by
      rw [mem_support_iff, coeff_mul_X_pow'] at hy
      exact by_contra fun h => hy (if_neg h)
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
    rwa [trailingCoeff, ← coeff_mul_X_pow]
  · rw [natTrailingDegree_eq_support_min' fun h => hp (mul_X_pow_eq_zero h), Finset.le_min'_iff]
    intro y hy
    have key : n ≤ y := by
      

Proof state:
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n y : ℕ
hy : y ∈ support (p * X ^ n)
⊢ n ≤ y

Next tactic:
rw [mem_support_iff, coeff_mul_X_pow'] at hy
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
    rwa [trailingCoeff, ← coeff_mul_X_pow]
  · rw [natTrailingDegree_eq_support_min' fun h => hp (mul_X_pow_eq_zero h), Finset.le_min'_iff]
    intro y hy
    have key : n ≤ y := by
      rw [mem_support_iff, coeff_mul_X_pow'] at hy
      

Proof state:
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n y : ℕ
hy : (if n ≤ y then coeff p (y - n) else 0) ≠ 0
⊢ n ≤ y

Next tactic:
exact by_contra fun h => hy (if_neg h)
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
    rwa [trailingCoeff, ← coeff_mul_X_pow]
  · rw [natTrailingDegree_eq_support_min' fun h => hp (mul_X_pow_eq_zero h), Finset.le_min'_iff]
    intro y hy
    have key : n ≤ y := by
      rw [mem_support_iff, coeff_mul_X_pow'] at hy
      exact by_contra fun h => hy (if_neg h)
    

Proof state:
case a
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n y : ℕ
hy : y ∈ support (p * X ^ n)
key : n ≤ y
⊢ natTrailingDegree p + n ≤ y

Next tactic:
rw [mem_support_iff, coeff_mul_X_pow', if_pos key] at hy
theorem natTrailingDegree_mul_X_pow {p : R[X]} (hp : p ≠ 0) (n : ℕ) :
    (p * X ^ n).natTrailingDegree = p.natTrailingDegree + n := by
  apply le_antisymm
  · refine' natTrailingDegree_le_of_ne_zero fun h => mt trailingCoeff_eq_zero.mp hp _
    rwa [trailingCoeff, ← coeff_mul_X_pow]
  · rw [natTrailingDegree_eq_support_min' fun h => hp (mul_X_pow_eq_zero h), Finset.le_min'_iff]
    intro y hy
    have key : n ≤ y := by
      rw [mem_support_iff, coeff_mul_X_pow'] at hy
      exact by_contra fun h => hy (if_neg h)
    rw [mem_support_iff, coeff_mul_X_pow', if_pos key] at hy
    

Proof state:
case a
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q r p : R[X]
hp : p ≠ 0
n y : ℕ
hy : coeff p (y - n) ≠ 0
key : n ≤ y
⊢ natTrailingDegree p + n ≤ y

Next tactic:
exact (le_tsub_iff_right key).mp (natTrailingDegree_le_of_ne_zero hy)
theorem le_trailingDegree_mul : p.trailingDegree + q.trailingDegree ≤ (p * q).trailingDegree := by
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
⊢ trailingDegree p + trailingDegree q ≤ trailingDegree (p * q)

Next tactic:
refine' Finset.le_min fun n hn => _
theorem le_trailingDegree_mul : p.trailingDegree + q.trailingDegree ≤ (p * q).trailingDegree := by
  refine' Finset.le_min fun n hn => _
  

Proof state:
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
hn : n ∈ support (p * q)
⊢ trailingDegree p + trailingDegree q ≤ ↑n

Next tactic:
rw [mem_support_iff, coeff_mul] at hn
theorem le_trailingDegree_mul : p.trailingDegree + q.trailingDegree ≤ (p * q).trailingDegree := by
  refine' Finset.le_min fun n hn => _
  rw [mem_support_iff, coeff_mul] at hn
  

Proof state:
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
hn : ∑ x in antidiagonal n, coeff p x.1 * coeff q x.2 ≠ 0
⊢ trailingDegree p + trailingDegree q ≤ ↑n

Next tactic:
obtain ⟨⟨i, j⟩, hij, hpq⟩ := exists_ne_zero_of_sum_ne_zero hn
theorem le_trailingDegree_mul : p.trailingDegree + q.trailingDegree ≤ (p * q).trailingDegree := by
  refine' Finset.le_min fun n hn => _
  rw [mem_support_iff, coeff_mul] at hn
  obtain ⟨⟨i, j⟩, hij, hpq⟩ := exists_ne_zero_of_sum_ne_zero hn
  

Proof state:
case intro.mk.intro
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
hn : ∑ x in antidiagonal n, coeff p x.1 * coeff q x.2 ≠ 0
i j : ℕ
hij : (i, j) ∈ antidiagonal n
hpq : coeff p (i, j).1 * coeff q (i, j).2 ≠ 0
⊢ trailingDegree p + trailingDegree q ≤ ↑n

Next tactic:
refine'
    (add_le_add (min_le (mem_support_iff.mpr (left_ne_zero_of_mul hpq)))
          (min_le (mem_support_iff.mpr (right_ne_zero_of_mul hpq)))).trans
      (le_of_eq _)
theorem le_trailingDegree_mul : p.trailingDegree + q.trailingDegree ≤ (p * q).trailingDegree := by
  refine' Finset.le_min fun n hn => _
  rw [mem_support_iff, coeff_mul] at hn
  obtain ⟨⟨i, j⟩, hij, hpq⟩ := exists_ne_zero_of_sum_ne_zero hn
  refine'
    (add_le_add (min_le (mem_support_iff.mpr (left_ne_zero_of_mul hpq)))
          (min_le (mem_support_iff.mpr (right_ne_zero_of_mul hpq)))).trans
      (le_of_eq _)
  

Proof state:
case intro.mk.intro
R : Type u
S : Type v
a b : R
n✝ m : ℕ
inst✝ : Semiring R
p q r : R[X]
n : ℕ
hn : ∑ x in antidiagonal n, coeff p x.1 * coeff q x.2 ≠ 0
i j : ℕ
hij : (i, j) ∈ antidiagonal n
hpq : coeff p (i, j).1 * coeff q (i, j).2 ≠ 0
⊢ ↑(i, j).1 + ↑(i, j).2 = ↑n

Next tactic:
rwa [← WithTop.coe_add, WithTop.coe_eq_coe, ← mem_antidiagonal]
theorem le_natTrailingDegree_mul (h : p * q ≠ 0) :
    p.natTrailingDegree + q.natTrailingDegree ≤ (p * q).natTrailingDegree := by
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p * q ≠ 0
⊢ natTrailingDegree p + natTrailingDegree q ≤ natTrailingDegree (p * q)

Next tactic:
have hp : p ≠ 0 := fun hp => h (by rw [hp, zero_mul])
theorem le_natTrailingDegree_mul (h : p * q ≠ 0) :
    p.natTrailingDegree + q.natTrailingDegree ≤ (p * q).natTrailingDegree := by
  have hp : p ≠ 0 := fun hp => h (by 

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p * q ≠ 0
hp : p = 0
⊢ p * q = 0

Next tactic:
rw [hp, zero_mul]
theorem le_natTrailingDegree_mul (h : p * q ≠ 0) :
    p.natTrailingDegree + q.natTrailingDegree ≤ (p * q).natTrailingDegree := by
  have hp : p ≠ 0 := fun hp => h (by rw [hp, zero_mul])
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p * q ≠ 0
hp : p ≠ 0
⊢ natTrailingDegree p + natTrailingDegree q ≤ natTrailingDegree (p * q)

Next tactic:
have hq : q ≠ 0 := fun hq => h (by rw [hq, mul_zero])
theorem le_natTrailingDegree_mul (h : p * q ≠ 0) :
    p.natTrailingDegree + q.natTrailingDegree ≤ (p * q).natTrailingDegree := by
  have hp : p ≠ 0 := fun hp => h (by rw [hp, zero_mul])
  have hq : q ≠ 0 := fun hq => h (by 

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p * q ≠ 0
hp : p ≠ 0
hq : q = 0
⊢ p * q = 0

Next tactic:
rw [hq, mul_zero]
theorem le_natTrailingDegree_mul (h : p * q ≠ 0) :
    p.natTrailingDegree + q.natTrailingDegree ≤ (p * q).natTrailingDegree := by
  have hp : p ≠ 0 := fun hp => h (by rw [hp, zero_mul])
  have hq : q ≠ 0 := fun hq => h (by rw [hq, mul_zero])
  -- Porting note: Needed to account for different coercion behaviour & add the lemma below
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p * q ≠ 0
hp : p ≠ 0
hq : q ≠ 0
⊢ natTrailingDegree p + natTrailingDegree q ≤ natTrailingDegree (p * q)

Next tactic:
have : ∀ (p : R[X]), WithTop.some (natTrailingDegree p) = Nat.cast (natTrailingDegree p) :=
    fun p ↦ rfl
theorem le_natTrailingDegree_mul (h : p * q ≠ 0) :
    p.natTrailingDegree + q.natTrailingDegree ≤ (p * q).natTrailingDegree := by
  have hp : p ≠ 0 := fun hp => h (by rw [hp, zero_mul])
  have hq : q ≠ 0 := fun hq => h (by rw [hq, mul_zero])
  -- Porting note: Needed to account for different coercion behaviour & add the lemma below
  have : ∀ (p : R[X]), WithTop.some (natTrailingDegree p) = Nat.cast (natTrailingDegree p) :=
    fun p ↦ rfl
  

Proof state:
R : Type u
S : Type v
a b : R
n m : ℕ
inst✝ : Semiring R
p q r : R[X]
h : p * q ≠ 0
hp : p ≠ 0
hq : q ≠ 0
this : ∀ (p : R[X]), ↑(natTrailingDegree p) = ↑(natTrailingDegree p)
⊢ natTrailingDegree p + natTrailingDegree q ≤ natTrailingDegree (p * q)

Next tactic:
rw [← WithTop.coe_le_coe, WithTop.coe_add, this p, this q, this (p * q),
    ← trailingDegree_eq_natTrailingDegree hp, ← trailingDegree_eq_natTrailingDegree hq,
    ← trailingDegree_eq_natTrailingDegree h]