l3lab/ntp-mathlib huggingface dataset:
@[simp] theorem natDegree_add_C {a : R} : (p + C a).natDegree = p.natDegree := 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
⊢ natDegree (p + C a) = natDegree p

Next tactic:
rcases eq_or_ne p 0 with rfl | hp
@[simp] theorem natDegree_add_C {a : R} : (p + C a).natDegree = p.natDegree := by
  rcases eq_or_ne p 0 with rfl | hp
  · 

Proof state:
case inl
R : Type u
S : Type v
a✝ b c d : R
n m : ℕ
inst✝ : Semiring R
q : R[X]
ι : Type u_1
a : R
⊢ natDegree (0 + C a) = natDegree 0

Next tactic:
simp
@[simp] theorem natDegree_add_C {a : R} : (p + C a).natDegree = p.natDegree := by
  rcases eq_or_ne p 0 with rfl | hp
  · simp
  

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
a : R
hp : p ≠ 0
⊢ natDegree (p + C a) = natDegree p

Next tactic:
by_cases hpd : p.degree ≤ 0
@[simp] theorem natDegree_add_C {a : R} : (p + C a).natDegree = p.natDegree := by
  rcases eq_or_ne p 0 with rfl | hp
  · simp
  by_cases hpd : p.degree ≤ 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
hp : p ≠ 0
hpd : degree p ≤ 0
⊢ natDegree (p + C a) = natDegree p

Next tactic:
rw [eq_C_of_degree_le_zero hpd, ← C_add, natDegree_C, natDegree_C]
@[simp] theorem natDegree_add_C {a : R} : (p + C a).natDegree = p.natDegree := by
  rcases eq_or_ne p 0 with rfl | hp
  · simp
  by_cases hpd : p.degree ≤ 0
  · rw [eq_C_of_degree_le_zero hpd, ← C_add, natDegree_C, natDegree_C]
  · 

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
hp : p ≠ 0
hpd : ¬degree p ≤ 0
⊢ natDegree (p + C a) = natDegree p

Next tactic:
rw [not_le, degree_eq_natDegree hp, Nat.cast_pos, ← natDegree_C a] at hpd
@[simp] theorem natDegree_add_C {a : R} : (p + C a).natDegree = p.natDegree := by
  rcases eq_or_ne p 0 with rfl | hp
  · simp
  by_cases hpd : p.degree ≤ 0
  · rw [eq_C_of_degree_le_zero hpd, ← C_add, natDegree_C, natDegree_C]
  · rw [not_le, degree_eq_natDegree hp, Nat.cast_pos, ← natDegree_C a] at hpd
    

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
hp : p ≠ 0
hpd : natDegree (C a) < natDegree p
⊢ natDegree (p + C a) = natDegree p

Next tactic:
exact natDegree_add_eq_left_of_natDegree_lt hpd
@[simp] theorem natDegree_C_add {a : R} : (C a + p).natDegree = p.natDegree := 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
⊢ natDegree (C a + p) = natDegree p

Next tactic:
simp [add_comm _ p]
theorem degree_add_eq_of_leadingCoeff_add_ne_zero (h : leadingCoeff p + leadingCoeff q ≠ 0) :
    degree (p + q) = max p.degree q.degree :=
  le_antisymm (degree_add_le _ _) <|
    match lt_trichotomy (degree p) (degree q) with
    | Or.inl hlt => 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 : leadingCoeff p + leadingCoeff q ≠ 0
hlt : degree p < degree q
⊢ max (degree p) (degree q) ≤ degree (p + q)

Next tactic:
rw [degree_add_eq_right_of_degree_lt hlt, max_eq_right_of_lt hlt]
theorem degree_add_eq_of_leadingCoeff_add_ne_zero (h : leadingCoeff p + leadingCoeff q ≠ 0) :
    degree (p + q) = max p.degree q.degree :=
  le_antisymm (degree_add_le _ _) <|
    match lt_trichotomy (degree p) (degree q) with
    | Or.inl hlt => by
      rw [degree_add_eq_right_of_degree_lt hlt, max_eq_right_of_lt hlt]
    | Or.inr (Or.inl HEq) =>
      le_of_not_gt fun hlt : max (degree p) (degree q) > degree (p + q) =>
        h <|
          show leadingCoeff p + leadingCoeff q = 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 : leadingCoeff p + leadingCoeff q ≠ 0
HEq : degree p = degree q
hlt : max (degree p) (degree q) > degree (p + q)
⊢ leadingCoeff p + leadingCoeff q = 0

Next tactic:
rw [HEq, max_self] at hlt
theorem degree_add_eq_of_leadingCoeff_add_ne_zero (h : leadingCoeff p + leadingCoeff q ≠ 0) :
    degree (p + q) = max p.degree q.degree :=
  le_antisymm (degree_add_le _ _) <|
    match lt_trichotomy (degree p) (degree q) with
    | Or.inl hlt => by
      rw [degree_add_eq_right_of_degree_lt hlt, max_eq_right_of_lt hlt]
    | Or.inr (Or.inl HEq) =>
      le_of_not_gt fun hlt : max (degree p) (degree q) > degree (p + q) =>
        h <|
          show leadingCoeff p + leadingCoeff q = 0 by
            rw [HEq, max_self] at hlt
            

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 : leadingCoeff p + leadingCoeff q ≠ 0
HEq : degree p = degree q
hlt : degree q > degree (p + q)
⊢ leadingCoeff p + leadingCoeff q = 0

Next tactic:
rw [leadingCoeff, leadingCoeff, natDegree_eq_of_degree_eq HEq, ← coeff_add]
theorem degree_add_eq_of_leadingCoeff_add_ne_zero (h : leadingCoeff p + leadingCoeff q ≠ 0) :
    degree (p + q) = max p.degree q.degree :=
  le_antisymm (degree_add_le _ _) <|
    match lt_trichotomy (degree p) (degree q) with
    | Or.inl hlt => by
      rw [degree_add_eq_right_of_degree_lt hlt, max_eq_right_of_lt hlt]
    | Or.inr (Or.inl HEq) =>
      le_of_not_gt fun hlt : max (degree p) (degree q) > degree (p + q) =>
        h <|
          show leadingCoeff p + leadingCoeff q = 0 by
            rw [HEq, max_self] at hlt
            rw [leadingCoeff, leadingCoeff, natDegree_eq_of_degree_eq HEq, ← coeff_add]
            

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 : leadingCoeff p + leadingCoeff q ≠ 0
HEq : degree p = degree q
hlt : degree q > degree (p + q)
⊢ coeff (p + q) (natDegree q) = 0

Next tactic:
exact coeff_natDegree_eq_zero_of_degree_lt hlt
theorem degree_add_eq_of_leadingCoeff_add_ne_zero (h : leadingCoeff p + leadingCoeff q ≠ 0) :
    degree (p + q) = max p.degree q.degree :=
  le_antisymm (degree_add_le _ _) <|
    match lt_trichotomy (degree p) (degree q) with
    | Or.inl hlt => by
      rw [degree_add_eq_right_of_degree_lt hlt, max_eq_right_of_lt hlt]
    | Or.inr (Or.inl HEq) =>
      le_of_not_gt fun hlt : max (degree p) (degree q) > degree (p + q) =>
        h <|
          show leadingCoeff p + leadingCoeff q = 0 by
            rw [HEq, max_self] at hlt
            rw [leadingCoeff, leadingCoeff, natDegree_eq_of_degree_eq HEq, ← coeff_add]
            exact coeff_natDegree_eq_zero_of_degree_lt hlt
    | Or.inr (Or.inr hlt) => 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 : leadingCoeff p + leadingCoeff q ≠ 0
hlt : degree q < degree p
⊢ max (degree p) (degree q) ≤ degree (p + q)

Next tactic:
rw [degree_add_eq_left_of_degree_lt hlt, max_eq_left_of_lt hlt]
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : 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]
H : natDegree (p + q) < natDegree p
⊢ natDegree p = natDegree q

Next tactic:
by_contra h
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : natDegree p = natDegree q := by
  by_contra 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
p q : R[X]
H : natDegree (p + q) < natDegree p
h : ¬natDegree p = natDegree q
⊢ False

Next tactic:
cases Nat.lt_or_lt_of_ne h with
  | inl h => exact lt_asymm h (by rwa [natDegree_add_eq_right_of_natDegree_lt h] at H)
  | inr h =>
    rw [natDegree_add_eq_left_of_natDegree_lt h] at H
    exact LT.lt.false H
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : natDegree p = natDegree q := by
  by_contra 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
p q : R[X]
H : natDegree (p + q) < natDegree p
h : ¬natDegree p = natDegree q
x✝ : natDegree p < natDegree q ∨ natDegree q < natDegree p
⊢ False

Next tactic:
cases Nat.lt_or_lt_of_ne h with
  | inl h => exact lt_asymm h (by rwa [natDegree_add_eq_right_of_natDegree_lt h] at H)
  | inr h =>
    rw [natDegree_add_eq_left_of_natDegree_lt h] at H
    exact LT.lt.false H
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : natDegree p = natDegree q := by
  by_contra h
  cases Nat.lt_or_lt_of_ne h with
  

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 : natDegree (p + q) < natDegree p
h✝ : ¬natDegree p = natDegree q
h : natDegree p < natDegree q
⊢ False

Next tactic:
| inl h => exact lt_asymm h (by rwa [natDegree_add_eq_right_of_natDegree_lt h] at H)
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : natDegree p = natDegree q := by
  by_contra h
  cases Nat.lt_or_lt_of_ne h with
  | inl 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 : natDegree (p + q) < natDegree p
h✝ : ¬natDegree p = natDegree q
h : natDegree p < natDegree q
⊢ False

Next tactic:
exact lt_asymm h (by rwa [natDegree_add_eq_right_of_natDegree_lt h] at H)
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : natDegree p = natDegree q := by
  by_contra h
  cases Nat.lt_or_lt_of_ne h with
  | inl h => exact lt_asymm 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
p q : R[X]
H : natDegree (p + q) < natDegree p
h✝ : ¬natDegree p = natDegree q
h : natDegree p < natDegree q
⊢ natDegree q < natDegree p

Next tactic:
rwa [natDegree_add_eq_right_of_natDegree_lt h] at H
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : natDegree p = natDegree q := by
  by_contra h
  cases Nat.lt_or_lt_of_ne h with
  | inl h => exact lt_asymm h (by rwa [natDegree_add_eq_right_of_natDegree_lt h] at 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 : natDegree (p + q) < natDegree p
h✝ : ¬natDegree p = natDegree q
h : natDegree q < natDegree p
⊢ False

Next tactic:
| inr h =>
    rw [natDegree_add_eq_left_of_natDegree_lt h] at H
    exact LT.lt.false H
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : natDegree p = natDegree q := by
  by_contra h
  cases Nat.lt_or_lt_of_ne h with
  | inl h => exact lt_asymm h (by rwa [natDegree_add_eq_right_of_natDegree_lt h] at H)
  | inr 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 : natDegree (p + q) < natDegree p
h✝ : ¬natDegree p = natDegree q
h : natDegree q < natDegree p
⊢ False

Next tactic:
rw [natDegree_add_eq_left_of_natDegree_lt h] at H
lemma natDegree_eq_of_natDegree_add_lt_left (p q : R[X])
    (H : natDegree (p + q) < natDegree p) : natDegree p = natDegree q := by
  by_contra h
  cases Nat.lt_or_lt_of_ne h with
  | inl h => exact lt_asymm h (by rwa [natDegree_add_eq_right_of_natDegree_lt h] at H)
  | inr h =>
    rw [natDegree_add_eq_left_of_natDegree_lt h] at 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 : natDegree p < natDegree p
h✝ : ¬natDegree p = natDegree q
h : natDegree q < natDegree p
⊢ False

Next tactic:
exact LT.lt.false H
lemma natDegree_eq_of_natDegree_add_eq_zero (p q : R[X])
    (H : natDegree (p + q) = 0) : 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]
H : natDegree (p + q) = 0
⊢ natDegree p = natDegree q

Next tactic:
by_cases h₁ : natDegree p = 0
lemma natDegree_eq_of_natDegree_add_eq_zero (p q : R[X])
    (H : natDegree (p + q) = 0) : natDegree p = natDegree q := by
  by_cases h₁ : natDegree 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
p q : R[X]
H : natDegree (p + q) = 0
h₁ : natDegree p = 0
⊢ natDegree p = natDegree q
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]
H : natDegree (p + q) = 0
h₁ : ¬natDegree p = 0
⊢ natDegree p = natDegree q

Next tactic:
by_cases h₂ : natDegree q = 0
lemma natDegree_eq_of_natDegree_add_eq_zero (p q : R[X])
    (H : natDegree (p + q) = 0) : natDegree p = natDegree q := by
  by_cases h₁ : natDegree p = 0; by_cases h₂ : natDegree q = 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
p q : R[X]
H : natDegree (p + q) = 0
h₁ : natDegree p = 0
h₂ : natDegree q = 0
⊢ natDegree p = natDegree q

Next tactic:
exact h₁.trans h₂.symm
lemma natDegree_eq_of_natDegree_add_eq_zero (p q : R[X])
    (H : natDegree (p + q) = 0) : natDegree p = natDegree q := by
  by_cases h₁ : natDegree p = 0; by_cases h₂ : natDegree q = 0
  · exact h₁.trans h₂.symm
  · 

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]
H : natDegree (p + q) = 0
h₁ : natDegree p = 0
h₂ : ¬natDegree q = 0
⊢ natDegree p = natDegree q

Next tactic:
apply natDegree_eq_of_natDegree_add_lt_right
lemma natDegree_eq_of_natDegree_add_eq_zero (p q : R[X])
    (H : natDegree (p + q) = 0) : natDegree p = natDegree q := by
  by_cases h₁ : natDegree p = 0; by_cases h₂ : natDegree q = 0
  · exact h₁.trans h₂.symm
  · apply natDegree_eq_of_natDegree_add_lt_right; 

Proof state:
case neg.H
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 : natDegree (p + q) = 0
h₁ : natDegree p = 0
h₂ : ¬natDegree q = 0
⊢ natDegree (p + q) < natDegree q

Next tactic:
rwa [H, Nat.pos_iff_ne_zero]
lemma natDegree_eq_of_natDegree_add_eq_zero (p q : R[X])
    (H : natDegree (p + q) = 0) : natDegree p = natDegree q := by
  by_cases h₁ : natDegree p = 0; by_cases h₂ : natDegree q = 0
  · exact h₁.trans h₂.symm
  · apply natDegree_eq_of_natDegree_add_lt_right; rwa [H, Nat.pos_iff_ne_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
p q : R[X]
H : natDegree (p + q) = 0
h₁ : ¬natDegree p = 0
⊢ natDegree p = natDegree q

Next tactic:
apply natDegree_eq_of_natDegree_add_lt_left
lemma natDegree_eq_of_natDegree_add_eq_zero (p q : R[X])
    (H : natDegree (p + q) = 0) : natDegree p = natDegree q := by
  by_cases h₁ : natDegree p = 0; by_cases h₂ : natDegree q = 0
  · exact h₁.trans h₂.symm
  · apply natDegree_eq_of_natDegree_add_lt_right; rwa [H, Nat.pos_iff_ne_zero]
  · apply natDegree_eq_of_natDegree_add_lt_left; 

Proof state:
case neg.H
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 : natDegree (p + q) = 0
h₁ : ¬natDegree p = 0
⊢ natDegree (p + q) < natDegree p

Next tactic:
rwa [H, Nat.pos_iff_ne_zero]
theorem degree_erase_le (p : R[X]) (n : ℕ) : degree (p.erase n) ≤ 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
p : R[X]
n : ℕ
⊢ degree (erase n p) ≤ degree p

Next tactic:
rcases p with ⟨p⟩
theorem degree_erase_le (p : R[X]) (n : ℕ) : degree (p.erase n) ≤ degree p := by
  rcases p with ⟨p⟩
  

Proof state:
case ofFinsupp
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
n : ℕ
p : AddMonoidAlgebra R ℕ
⊢ degree (erase n { toFinsupp := p }) ≤ degree { toFinsupp := p }

Next tactic:
simp only [erase_def, degree, coeff, support]
theorem degree_erase_le (p : R[X]) (n : ℕ) : degree (p.erase n) ≤ degree p := by
  rcases p with ⟨p⟩
  simp only [erase_def, degree, coeff, support]
  -- Porting note: simpler convert-free proof to be explicit about definition unfolding
  

Proof state:
case ofFinsupp
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
n : ℕ
p : AddMonoidAlgebra R ℕ
⊢ Finset.max (Finsupp.erase n p).support ≤ Finset.max p.support

Next tactic:
apply sup_mono
theorem degree_erase_le (p : R[X]) (n : ℕ) : degree (p.erase n) ≤ degree p := by
  rcases p with ⟨p⟩
  simp only [erase_def, degree, coeff, support]
  -- Porting note: simpler convert-free proof to be explicit about definition unfolding
  apply sup_mono
  

Proof state:
case ofFinsupp.h
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
n : ℕ
p : AddMonoidAlgebra R ℕ
⊢ (Finsupp.erase n p).support ⊆ p.support

Next tactic:
rw [Finsupp.support_erase]
theorem degree_erase_le (p : R[X]) (n : ℕ) : degree (p.erase n) ≤ degree p := by
  rcases p with ⟨p⟩
  simp only [erase_def, degree, coeff, support]
  -- Porting note: simpler convert-free proof to be explicit about definition unfolding
  apply sup_mono
  rw [Finsupp.support_erase]
  

Proof state:
case ofFinsupp.h
R : Type u
S : Type v
a b c d : R
n✝ m : ℕ
inst✝ : Semiring R
p✝ q : R[X]
ι : Type u_1
n : ℕ
p : AddMonoidAlgebra R ℕ
⊢ Finset.erase p.support n ⊆ p.support

Next tactic:
apply Finset.erase_subset
theorem degree_erase_lt (hp : p ≠ 0) : degree (p.erase (natDegree p)) < 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
hp : p ≠ 0
⊢ degree (erase (natDegree p) p) < degree p

Next tactic:
apply lt_of_le_of_ne (degree_erase_le _ _)
theorem degree_erase_lt (hp : p ≠ 0) : degree (p.erase (natDegree p)) < degree p := by
  apply lt_of_le_of_ne (degree_erase_le _ _)
  

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
⊢ degree (erase (natDegree p) p) ≠ degree p

Next tactic:
rw [degree_eq_natDegree hp, degree, support_erase]
theorem degree_erase_lt (hp : p ≠ 0) : degree (p.erase (natDegree p)) < degree p := by
  apply lt_of_le_of_ne (degree_erase_le _ _)
  rw [degree_eq_natDegree hp, degree, support_erase]
  

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
⊢ Finset.max (Finset.erase (support p) (natDegree p)) ≠ ↑(natDegree p)

Next tactic:
exact fun h => not_mem_erase _ _ (mem_of_max h)
theorem degree_update_le (p : R[X]) (n : ℕ) (a : R) : degree (p.update n a) ≤ max (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 : ℕ
a : R
⊢ degree (update p n a) ≤ max (degree p) ↑n

Next tactic:
classical
  rw [degree, support_update]
  split_ifs
  · exact (Finset.max_mono (erase_subset _ _)).trans (le_max_left _ _)
  · rw [max_insert, max_comm]
    exact le_rfl
theorem degree_update_le (p : R[X]) (n : ℕ) (a : R) : degree (p.update n a) ≤ max (degree p) n := 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
p : R[X]
n : ℕ
a : R
⊢ degree (update p n a) ≤ max (degree p) ↑n

Next tactic:
rw [degree, support_update]
theorem degree_update_le (p : R[X]) (n : ℕ) (a : R) : degree (p.update n a) ≤ max (degree p) n := by
  classical
  rw [degree, support_update]
  

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 : ℕ
a : R
⊢ Finset.max (if a = 0 then Finset.erase (support p) n else insert n (support p)) ≤ max (degree p) ↑n

Next tactic:
split_ifs
theorem degree_update_le (p : R[X]) (n : ℕ) (a : R) : degree (p.update n a) ≤ max (degree p) n := by
  classical
  rw [degree, support_update]
  split_ifs
  · 

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 : R[X]
n : ℕ
a : R
h✝ : a = 0
⊢ Finset.max (Finset.erase (support p) n) ≤ max (degree p) ↑n

Next tactic:
exact (Finset.max_mono (erase_subset _ _)).trans (le_max_left _ _)
theorem degree_update_le (p : R[X]) (n : ℕ) (a : R) : degree (p.update n a) ≤ max (degree p) n := by
  classical
  rw [degree, support_update]
  split_ifs
  · exact (Finset.max_mono (erase_subset _ _)).trans (le_max_left _ _)
  · 

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 : R[X]
n : ℕ
a : R
h✝ : ¬a = 0
⊢ Finset.max (insert n (support p)) ≤ max (degree p) ↑n

Next tactic:
rw [max_insert, max_comm]
theorem degree_update_le (p : R[X]) (n : ℕ) (a : R) : degree (p.update n a) ≤ max (degree p) n := by
  classical
  rw [degree, support_update]
  split_ifs
  · exact (Finset.max_mono (erase_subset _ _)).trans (le_max_left _ _)
  · rw [max_insert, max_comm]
    

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 : R[X]
n : ℕ
a : R
h✝ : ¬a = 0
⊢ max (Finset.max (support p)) ↑n ≤ max (degree p) ↑n

Next tactic:
exact le_rfl
theorem degree_sum_le (s : Finset ι) (f : ι → R[X]) :
    degree (∑ i in s, f i) ≤ s.sup fun b => degree (f b) :=
  Finset.cons_induction_on s (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
s : Finset ι
f : ι → R[X]
⊢ degree (∑ i in ∅, f i) ≤ sup ∅ fun b => degree (f b)

Next tactic:
simp only [sum_empty, sup_empty, degree_zero, le_refl]
theorem degree_sum_le (s : Finset ι) (f : ι → R[X]) :
    degree (∑ i in s, f i) ≤ s.sup fun b => degree (f b) :=
  Finset.cons_induction_on s (by simp only [sum_empty, sup_empty, degree_zero, le_refl])
    fun a s has ih =>
    calc
      degree (∑ i in cons a s has, f i) ≤ max (degree (f a)) (degree (∑ i in s, f i)) := 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
s✝ : Finset ι
f : ι → R[X]
a : ι
s : Finset ι
has : a ∉ s
ih : degree (∑ i in s, f i) ≤ sup s fun b => degree (f b)
⊢ degree (∑ i in Finset.cons a s has, f i) ≤ max (degree (f a)) (degree (∑ i in s, f i))

Next tactic:
rw [Finset.sum_cons]
theorem degree_sum_le (s : Finset ι) (f : ι → R[X]) :
    degree (∑ i in s, f i) ≤ s.sup fun b => degree (f b) :=
  Finset.cons_induction_on s (by simp only [sum_empty, sup_empty, degree_zero, le_refl])
    fun a s has ih =>
    calc
      degree (∑ i in cons a s has, f i) ≤ max (degree (f a)) (degree (∑ i in s, f i)) := by
        rw [Finset.sum_cons]; 

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
s✝ : Finset ι
f : ι → R[X]
a : ι
s : Finset ι
has : a ∉ s
ih : degree (∑ i in s, f i) ≤ sup s fun b => degree (f b)
⊢ degree (f a + ∑ x in s, f x) ≤ max (degree (f a)) (degree (∑ i in s, f i))

Next tactic:
exact degree_add_le _ _
theorem degree_sum_le (s : Finset ι) (f : ι → R[X]) :
    degree (∑ i in s, f i) ≤ s.sup fun b => degree (f b) :=
  Finset.cons_induction_on s (by simp only [sum_empty, sup_empty, degree_zero, le_refl])
    fun a s has ih =>
    calc
      degree (∑ i in cons a s has, f i) ≤ max (degree (f a)) (degree (∑ i in s, f i)) := by
        rw [Finset.sum_cons]; exact degree_add_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
s✝ : Finset ι
f : ι → R[X]
a : ι
s : Finset ι
has : a ∉ s
ih : degree (∑ i in s, f i) ≤ sup s fun b => degree (f b)
⊢ max (degree (f a)) (degree (∑ i in s, f i)) ≤ sup (Finset.cons a s has) fun b => degree (f b)

Next tactic:
rw [sup_cons, sup_eq_max]
theorem degree_sum_le (s : Finset ι) (f : ι → R[X]) :
    degree (∑ i in s, f i) ≤ s.sup fun b => degree (f b) :=
  Finset.cons_induction_on s (by simp only [sum_empty, sup_empty, degree_zero, le_refl])
    fun a s has ih =>
    calc
      degree (∑ i in cons a s has, f i) ≤ max (degree (f a)) (degree (∑ i in s, f i)) := by
        rw [Finset.sum_cons]; exact degree_add_le _ _
      _ ≤ _ := by rw [sup_cons, sup_eq_max]; 

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
s✝ : Finset ι
f : ι → R[X]
a : ι
s : Finset ι
has : a ∉ s
ih : degree (∑ i in s, f i) ≤ sup s fun b => degree (f b)
⊢ max (degree (f a)) (degree (∑ i in s, f i)) ≤ max (degree (f a)) (sup s fun b => degree (f b))

Next tactic:
exact max_le_max le_rfl ih