l3lab/ntp-mathlib huggingface dataset:
theorem natDegree_sum_eq_of_disjoint (f : S → R[X]) (s : Finset S)
    (h : Set.Pairwise { i | i ∈ s ∧ f i ≠ 0 } (Ne on natDegree ∘ f)) :
    natDegree (s.sum f) = s.sup fun i => natDegree (f i) := by
  by_cases H : ∃ x ∈ s, f x ≠ 0
  · obtain ⟨x, hx, hx'⟩ := H
    have hs : s.Nonempty := ⟨x, hx⟩
    refine' natDegree_eq_of_degree_eq_some _
    rw [degree_sum_eq_of_disjoint]
    · rw [← Finset.sup'_eq_sup hs, ← Finset.sup'_eq_sup hs,
        Nat.cast_withBot, Finset.coe_sup' hs, ←
        Finset.sup'_eq_sup hs]
      refine' le_antisymm _ _
      · rw [Finset.sup'_le_iff]
        intro b hb
        by_cases hb' : f b = 0
        · simpa [hb'] using hs
        rw [degree_eq_natDegree hb', Nat.cast_withBot]
        exact Finset.le_sup' (fun i : S => (natDegree (f i) : WithBot ℕ)) hb
      · rw [Finset.sup'_le_iff]
        intro b hb
        simp only [Finset.le_sup'_iff, exists_prop, Function.comp_apply]
        by_cases hb' : f b = 0
        · refine' ⟨x, hx, _⟩
          contrapose! hx'
          simpa [← Nat.cast_withBot, hb', degree_eq_bot] using hx'
        exact ⟨b, hb, (degree_eq_natDegree hb').ge⟩
    · exact h.imp fun x y hxy hxy' => hxy (natDegree_eq_of_degree_eq hxy')
  · push_neg at H
    rw [Finset.sum_eq_zero H, natDegree_zero, eq_comm, show 0 = ⊥ from rfl, Finset.sup_eq_bot_iff]
    intro x hx
    

Proof state:
case neg
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝ : Semiring R
p q r : R[X]
f : S → R[X]
s : Finset S
h : Set.Pairwise {i | i ∈ s ∧ f i ≠ 0} (Ne on natDegree ∘ f)
H : ∀ x ∈ s, f x = 0
x : S
hx : x ∈ s
⊢ natDegree (f x) = ⊥

Next tactic:
simp [H x hx]
set_option linter.deprecated false in
theorem natDegree_bit1 (a : R[X]) : (bit1 a).natDegree ≤ a.natDegree :=
  (natDegree_add_le _ _).trans (by 

Proof state:
R : Type u
S : Type v
ι : Type w
a✝ b : R
m n : ℕ
inst✝ : Semiring R
p q r a : R[X]
⊢ max (natDegree (bit0 a)) (natDegree 1) ≤ natDegree a

Next tactic:
simp [natDegree_bit0]
theorem natDegree_pos_of_eval₂_root {p : R[X]} (hp : p ≠ 0) (f : R →+* S) {z : S}
    (hz : eval₂ f z p = 0) (inj : ∀ x : R, f x = 0 → x = 0) : 0 < natDegree p :=
  lt_of_not_ge fun hlt => by
    

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
p : R[X]
hp : p ≠ 0
f : R →+* S
z : S
hz : eval₂ f z p = 0
inj : ∀ (x : R), f x = 0 → x = 0
hlt : 0 ≥ natDegree p
⊢ False

Next tactic:
have A : p = C (p.coeff 0) := eq_C_of_natDegree_le_zero hlt
theorem natDegree_pos_of_eval₂_root {p : R[X]} (hp : p ≠ 0) (f : R →+* S) {z : S}
    (hz : eval₂ f z p = 0) (inj : ∀ x : R, f x = 0 → x = 0) : 0 < natDegree p :=
  lt_of_not_ge fun hlt => by
    have A : p = C (p.coeff 0) := eq_C_of_natDegree_le_zero hlt
    

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
p : R[X]
hp : p ≠ 0
f : R →+* S
z : S
hz : eval₂ f z p = 0
inj : ∀ (x : R), f x = 0 → x = 0
hlt : 0 ≥ natDegree p
A : p = C (coeff p 0)
⊢ False

Next tactic:
rw [A, eval₂_C] at hz
theorem natDegree_pos_of_eval₂_root {p : R[X]} (hp : p ≠ 0) (f : R →+* S) {z : S}
    (hz : eval₂ f z p = 0) (inj : ∀ x : R, f x = 0 → x = 0) : 0 < natDegree p :=
  lt_of_not_ge fun hlt => by
    have A : p = C (p.coeff 0) := eq_C_of_natDegree_le_zero hlt
    rw [A, eval₂_C] at hz
    

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
p : R[X]
hp : p ≠ 0
f : R →+* S
z : S
hz : f (coeff p 0) = 0
inj : ∀ (x : R), f x = 0 → x = 0
hlt : 0 ≥ natDegree p
A : p = C (coeff p 0)
⊢ False

Next tactic:
simp only [inj (p.coeff 0) hz, RingHom.map_zero] at A
theorem natDegree_pos_of_eval₂_root {p : R[X]} (hp : p ≠ 0) (f : R →+* S) {z : S}
    (hz : eval₂ f z p = 0) (inj : ∀ x : R, f x = 0 → x = 0) : 0 < natDegree p :=
  lt_of_not_ge fun hlt => by
    have A : p = C (p.coeff 0) := eq_C_of_natDegree_le_zero hlt
    rw [A, eval₂_C] at hz
    simp only [inj (p.coeff 0) hz, RingHom.map_zero] at A
    

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
p : R[X]
hp : p ≠ 0
f : R →+* S
z : S
hz : f (coeff p 0) = 0
inj : ∀ (x : R), f x = 0 → x = 0
hlt : 0 ≥ natDegree p
A : p = 0
⊢ False

Next tactic:
exact hp A
@[simp]
theorem coe_lt_degree {p : R[X]} {n : ℕ} : (n : WithBot ℕ) < degree p ↔ n < natDegree p := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
p : R[X]
n : ℕ
⊢ ↑n < degree p ↔ n < natDegree p

Next tactic:
by_cases h : p = 0
@[simp]
theorem coe_lt_degree {p : R[X]} {n : ℕ} : (n : WithBot ℕ) < degree p ↔ n < natDegree p := by
  by_cases h : p = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
ι : Type w
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
p : R[X]
n : ℕ
h : p = 0
⊢ ↑n < degree p ↔ n < natDegree p

Next tactic:
simp [h]
@[simp]
theorem coe_lt_degree {p : R[X]} {n : ℕ} : (n : WithBot ℕ) < degree p ↔ n < natDegree p := by
  by_cases h : p = 0
  · simp [h]
  

Proof state:
case neg
R : Type u
S : Type v
ι : Type w
a b : R
m n✝ : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
p : R[X]
n : ℕ
h : ¬p = 0
⊢ ↑n < degree p ↔ n < natDegree p

Next tactic:
simp [degree_eq_natDegree h, Nat.cast_lt]
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
⊢ degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0

Next tactic:
rcases eq_or_ne p 0 with h|h
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  rcases eq_or_ne p 0 with h|h
  · 

Proof state:
case inl
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : p = 0
⊢ degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0

Next tactic:
simp [h]
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  rcases eq_or_ne p 0 with h|h
  · simp [h]
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : p ≠ 0
⊢ degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0

Next tactic:
simp only [h, or_false]
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  rcases eq_or_ne p 0 with h|h
  · simp [h]
  simp only [h, or_false]
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : p ≠ 0
⊢ degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0

Next tactic:
refine ⟨fun h2 ↦ ?_, degree_map_eq_of_leadingCoeff_ne_zero f⟩
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  rcases eq_or_ne p 0 with h|h
  · simp [h]
  simp only [h, or_false]
  refine ⟨fun h2 ↦ ?_, degree_map_eq_of_leadingCoeff_ne_zero f⟩
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : p ≠ 0
h2 : degree (map f p) = degree p
⊢ f (leadingCoeff p) ≠ 0

Next tactic:
have h3 : natDegree (map f p) = natDegree p
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  rcases eq_or_ne p 0 with h|h
  · simp [h]
  simp only [h, or_false]
  refine ⟨fun h2 ↦ ?_, degree_map_eq_of_leadingCoeff_ne_zero f⟩
  have h3 : natDegree (map f p) = natDegree p
  · 

Proof state:
case h3
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : p ≠ 0
h2 : degree (map f p) = degree p
⊢ natDegree (map f p) = natDegree p

Next tactic:
simp_rw [natDegree, h2]
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  rcases eq_or_ne p 0 with h|h
  · simp [h]
  simp only [h, or_false]
  refine ⟨fun h2 ↦ ?_, degree_map_eq_of_leadingCoeff_ne_zero f⟩
  have h3 : natDegree (map f p) = natDegree p
  · simp_rw [natDegree, h2]
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : p ≠ 0
h2 : degree (map f p) = degree p
h3 : natDegree (map f p) = natDegree p
⊢ f (leadingCoeff p) ≠ 0

Next tactic:
have h4 : map f p ≠ 0
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  rcases eq_or_ne p 0 with h|h
  · simp [h]
  simp only [h, or_false]
  refine ⟨fun h2 ↦ ?_, degree_map_eq_of_leadingCoeff_ne_zero f⟩
  have h3 : natDegree (map f p) = natDegree p
  · simp_rw [natDegree, h2]
  have h4 : map f p ≠ 0
  · 

Proof state:
case h4
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : p ≠ 0
h2 : degree (map f p) = degree p
h3 : natDegree (map f p) = natDegree p
⊢ map f p ≠ 0

Next tactic:
rwa [ne_eq, ← degree_eq_bot, h2, degree_eq_bot]
@[simp]
theorem degree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    degree (map f p) = degree p ↔ f (leadingCoeff p) ≠ 0 ∨ p = 0 := by
  rcases eq_or_ne p 0 with h|h
  · simp [h]
  simp only [h, or_false]
  refine ⟨fun h2 ↦ ?_, degree_map_eq_of_leadingCoeff_ne_zero f⟩
  have h3 : natDegree (map f p) = natDegree p
  · simp_rw [natDegree, h2]
  have h4 : map f p ≠ 0
  · rwa [ne_eq, ← degree_eq_bot, h2, degree_eq_bot]
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : p ≠ 0
h2 : degree (map f p) = degree p
h3 : natDegree (map f p) = natDegree p
h4 : map f p ≠ 0
⊢ f (leadingCoeff p) ≠ 0

Next tactic:
rwa [← coeff_natDegree, ← coeff_map, ← h3, coeff_natDegree, ne_eq, leadingCoeff_eq_zero]
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
⊢ natDegree (map f p) = natDegree p ↔ f (leadingCoeff p) ≠ 0 ∨ natDegree p = 0

Next tactic:
rcases eq_or_ne (natDegree p) 0 with h|h
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  rcases eq_or_ne (natDegree p) 0 with h|h
  · 

Proof state:
case inl
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : natDegree p = 0
⊢ natDegree (map f p) = natDegree p ↔ f (leadingCoeff p) ≠ 0 ∨ natDegree p = 0

Next tactic:
simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le f p]
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  rcases eq_or_ne (natDegree p) 0 with h|h
  · simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le f p]
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : natDegree p ≠ 0
⊢ natDegree (map f p) = natDegree p ↔ f (leadingCoeff p) ≠ 0 ∨ natDegree p = 0

Next tactic:
have h2 : p ≠ 0 := by rintro rfl; simp at h
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  rcases eq_or_ne (natDegree p) 0 with h|h
  · simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le f p]
  have h2 : p ≠ 0 := by 

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : natDegree p ≠ 0
⊢ p ≠ 0

Next tactic:
rintro rfl
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  rcases eq_or_ne (natDegree p) 0 with h|h
  · simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le f p]
  have h2 : p ≠ 0 := by rintro rfl; 

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p q r : R[X]
inst✝ : Semiring S
f : R →+* S
h : natDegree 0 ≠ 0
⊢ False

Next tactic:
simp at h
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  rcases eq_or_ne (natDegree p) 0 with h|h
  · simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le f p]
  have h2 : p ≠ 0 := by rintro rfl; simp at h
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : natDegree p ≠ 0
h2 : p ≠ 0
⊢ natDegree (map f p) = natDegree p ↔ f (leadingCoeff p) ≠ 0 ∨ natDegree p = 0

Next tactic:
have h3 : degree p ≠ (0 : ℕ)  := degree_ne_of_natDegree_ne h
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  rcases eq_or_ne (natDegree p) 0 with h|h
  · simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le f p]
  have h2 : p ≠ 0 := by rintro rfl; simp at h
  have h3 : degree p ≠ (0 : ℕ)  := degree_ne_of_natDegree_ne h
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : natDegree p ≠ 0
h2 : p ≠ 0
h3 : degree p ≠ ↑0
⊢ natDegree (map f p) = natDegree p ↔ f (leadingCoeff p) ≠ 0 ∨ natDegree p = 0

Next tactic:
simp_rw [h, or_false, natDegree, WithBot.unbot'_eq_unbot'_iff, degree_map_eq_iff]
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  rcases eq_or_ne (natDegree p) 0 with h|h
  · simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le f p]
  have h2 : p ≠ 0 := by rintro rfl; simp at h
  have h3 : degree p ≠ (0 : ℕ)  := degree_ne_of_natDegree_ne h
  simp_rw [h, or_false, natDegree, WithBot.unbot'_eq_unbot'_iff, degree_map_eq_iff]
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : natDegree p ≠ 0
h2 : p ≠ 0
h3 : degree p ≠ ↑0
⊢ (f (leadingCoeff p) ≠ 0 ∨ p = 0) ∨ degree (map f p) = ↑0 ∧ degree p = ⊥ ∨ degree (map f p) = ⊥ ∧ degree p = ↑0 ↔
    f (leadingCoeff p) ≠ 0

Next tactic:
simp [h, h2, h3]
@[simp]
theorem natDegree_map_eq_iff {f : R →+* S} {p : Polynomial R} :
    natDegree (map f p) = natDegree p ↔ f (p.leadingCoeff) ≠ 0 ∨ natDegree p = 0 := by
  rcases eq_or_ne (natDegree p) 0 with h|h
  · simp_rw [h, ne_eq, or_true, iff_true, ← Nat.le_zero, ← h, natDegree_map_le f p]
  have h2 : p ≠ 0 := by rintro rfl; simp at h
  have h3 : degree p ≠ (0 : ℕ)  := degree_ne_of_natDegree_ne h
  simp_rw [h, or_false, natDegree, WithBot.unbot'_eq_unbot'_iff, degree_map_eq_iff]
  simp [h, h2, h3] -- simp doesn't rewrite in the hypothesis for some reason
  

Proof state:
case inr
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
p✝ q r : R[X]
inst✝ : Semiring S
f : R →+* S
p : R[X]
h : natDegree p ≠ 0
h2 : p ≠ 0
h3 : degree p ≠ ↑0
⊢ map f p = 0 → degree p = ↑0 → ¬f (leadingCoeff p) = 0

Next tactic:
tauto
theorem natDegree_sub : (p - q).natDegree = (q - p).natDegree := by 

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

Next tactic:
rw [← natDegree_neg, neg_sub]
theorem natDegree_sub_le_iff_left (qn : q.natDegree ≤ n) :
    (p - q).natDegree ≤ n ↔ p.natDegree ≤ n := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝ : Ring R
p q : R[X]
qn : natDegree q ≤ n
⊢ natDegree (p - q) ≤ n ↔ natDegree p ≤ n

Next tactic:
rw [← natDegree_neg] at qn
theorem natDegree_sub_le_iff_left (qn : q.natDegree ≤ n) :
    (p - q).natDegree ≤ n ↔ p.natDegree ≤ n := by
  rw [← natDegree_neg] at qn
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝ : Ring R
p q : R[X]
qn : natDegree (-q) ≤ n
⊢ natDegree (p - q) ≤ n ↔ natDegree p ≤ n

Next tactic:
rw [sub_eq_add_neg, natDegree_add_le_iff_left _ _ qn]
theorem natDegree_sub_le_iff_right (pn : p.natDegree ≤ n) :
    (p - q).natDegree ≤ n ↔ q.natDegree ≤ n := by 

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝ : Ring R
p q : R[X]
pn : natDegree p ≤ n
⊢ natDegree (p - q) ≤ n ↔ natDegree q ≤ n

Next tactic:
rwa [natDegree_sub, natDegree_sub_le_iff_left]
theorem coeff_sub_eq_left_of_lt (dg : q.natDegree < n) : (p - q).coeff n = p.coeff n := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝ : Ring R
p q : R[X]
dg : natDegree q < n
⊢ coeff (p - q) n = coeff p n

Next tactic:
rw [← natDegree_neg] at dg
theorem coeff_sub_eq_left_of_lt (dg : q.natDegree < n) : (p - q).coeff n = p.coeff n := by
  rw [← natDegree_neg] at dg
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝ : Ring R
p q : R[X]
dg : natDegree (-q) < n
⊢ coeff (p - q) n = coeff p n

Next tactic:
rw [sub_eq_add_neg, coeff_add_eq_left_of_lt dg]
theorem coeff_sub_eq_neg_right_of_lt (df : p.natDegree < n) : (p - q).coeff n = -q.coeff n := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝ : Ring R
p q : R[X]
df : natDegree p < n
⊢ coeff (p - q) n = -coeff q n

Next tactic:
rwa [sub_eq_add_neg, coeff_add_eq_right_of_lt, coeff_neg]
theorem degree_mul_C (a0 : a ≠ 0) : (p * C a).degree = p.degree := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
a0 : a ≠ 0
⊢ degree (p * C a) = degree p

Next tactic:
rw [degree_mul, degree_C a0, add_zero]
theorem degree_C_mul (a0 : a ≠ 0) : (C a * p).degree = p.degree := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
a0 : a ≠ 0
⊢ degree (C a * p) = degree p

Next tactic:
rw [degree_mul, degree_C a0, zero_add]
theorem natDegree_mul_C (a0 : a ≠ 0) : (p * C a).natDegree = p.natDegree := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
a0 : a ≠ 0
⊢ natDegree (p * C a) = natDegree p

Next tactic:
simp only [natDegree, degree_mul_C a0]
theorem natDegree_C_mul (a0 : a ≠ 0) : (C a * p).natDegree = p.natDegree := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
a0 : a ≠ 0
⊢ natDegree (C a * p) = natDegree p

Next tactic:
simp only [natDegree, degree_C_mul a0]
theorem natDegree_comp : natDegree (p.comp q) = natDegree p * natDegree q := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
⊢ natDegree (comp p q) = natDegree p * natDegree q

Next tactic:
by_cases q0 : q.natDegree = 0
theorem natDegree_comp : natDegree (p.comp q) = natDegree p * natDegree q := by
  by_cases q0 : q.natDegree = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
q0 : natDegree q = 0
⊢ natDegree (comp p q) = natDegree p * natDegree q

Next tactic:
rw [degree_le_zero_iff.mp (natDegree_eq_zero_iff_degree_le_zero.mp q0), comp_C, natDegree_C,
      natDegree_C, mul_zero]
theorem natDegree_comp : natDegree (p.comp q) = natDegree p * natDegree q := by
  by_cases q0 : q.natDegree = 0
  · rw [degree_le_zero_iff.mp (natDegree_eq_zero_iff_degree_le_zero.mp q0), comp_C, natDegree_C,
      natDegree_C, mul_zero]
  · 

Proof state:
case neg
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
q0 : ¬natDegree q = 0
⊢ natDegree (comp p q) = natDegree p * natDegree q

Next tactic:
by_cases p0 : p = 0
theorem natDegree_comp : natDegree (p.comp q) = natDegree p * natDegree q := by
  by_cases q0 : q.natDegree = 0
  · rw [degree_le_zero_iff.mp (natDegree_eq_zero_iff_degree_le_zero.mp q0), comp_C, natDegree_C,
      natDegree_C, mul_zero]
  · by_cases p0 : p = 0
    · 

Proof state:
case pos
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
q0 : ¬natDegree q = 0
p0 : p = 0
⊢ natDegree (comp p q) = natDegree p * natDegree q

Next tactic:
simp only [p0, zero_comp, natDegree_zero, zero_mul]
theorem natDegree_comp : natDegree (p.comp q) = natDegree p * natDegree q := by
  by_cases q0 : q.natDegree = 0
  · rw [degree_le_zero_iff.mp (natDegree_eq_zero_iff_degree_le_zero.mp q0), comp_C, natDegree_C,
      natDegree_C, mul_zero]
  · by_cases p0 : p = 0
    · simp only [p0, zero_comp, natDegree_zero, zero_mul]
    

Proof state:
case neg
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
q0 : ¬natDegree q = 0
p0 : ¬p = 0
⊢ natDegree (comp p q) = natDegree p * natDegree q

Next tactic:
refine' le_antisymm natDegree_comp_le (le_natDegree_of_ne_zero _)
theorem natDegree_comp : natDegree (p.comp q) = natDegree p * natDegree q := by
  by_cases q0 : q.natDegree = 0
  · rw [degree_le_zero_iff.mp (natDegree_eq_zero_iff_degree_le_zero.mp q0), comp_C, natDegree_C,
      natDegree_C, mul_zero]
  · by_cases p0 : p = 0
    · simp only [p0, zero_comp, natDegree_zero, zero_mul]
    refine' le_antisymm natDegree_comp_le (le_natDegree_of_ne_zero _)
    

Proof state:
case neg
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
q0 : ¬natDegree q = 0
p0 : ¬p = 0
⊢ coeff (comp p q) (natDegree p * natDegree q) ≠ 0

Next tactic:
simp only [coeff_comp_degree_mul_degree q0, p0, mul_eq_zero, leadingCoeff_eq_zero, or_self_iff,
      ne_zero_of_natDegree_gt (Nat.pos_of_ne_zero q0), pow_ne_zero, Ne.def, not_false_iff]
@[simp]
theorem natDegree_iterate_comp (k : ℕ) :
    (p.comp^[k] q).natDegree = p.natDegree ^ k * q.natDegree := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
k : ℕ
⊢ natDegree ((comp p)^[k] q) = natDegree p ^ k * natDegree q

Next tactic:
induction' k with k IH
@[simp]
theorem natDegree_iterate_comp (k : ℕ) :
    (p.comp^[k] q).natDegree = p.natDegree ^ k * q.natDegree := by
  induction' k with k IH
  · 

Proof state:
case zero
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
⊢ natDegree ((comp p)^[Nat.zero] q) = natDegree p ^ Nat.zero * natDegree q

Next tactic:
simp
@[simp]
theorem natDegree_iterate_comp (k : ℕ) :
    (p.comp^[k] q).natDegree = p.natDegree ^ k * q.natDegree := by
  induction' k with k IH
  · simp
  · 

Proof state:
case succ
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
k : ℕ
IH : natDegree ((comp p)^[k] q) = natDegree p ^ k * natDegree q
⊢ natDegree ((comp p)^[Nat.succ k] q) = natDegree p ^ Nat.succ k * natDegree q

Next tactic:
rw [Function.iterate_succ_apply', natDegree_comp, IH, pow_succ, mul_assoc]
theorem leadingCoeff_comp (hq : natDegree q ≠ 0) :
    leadingCoeff (p.comp q) = leadingCoeff p * leadingCoeff q ^ natDegree p := by
  

Proof state:
R : Type u
S : Type v
ι : Type w
a b : R
m n : ℕ
inst✝¹ : Semiring R
inst✝ : NoZeroDivisors R
p q : R[X]
hq : natDegree q ≠ 0
⊢ leadingCoeff (comp p q) = leadingCoeff p * leadingCoeff q ^ natDegree p

Next tactic:
rw [← coeff_comp_degree_mul_degree hq, ← natDegree_comp, coeff_natDegree]