l3lab/ntp-mathlib huggingface dataset:
theorem monic_of_injective {p : R[X]} (hp : (p.map f).Monic) : p.Monic := by
  apply hf
  

Proof state:
case a
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝¹ : Semiring R
inst✝ : Semiring S
f : R →+* S
hf : Injective ⇑f
p : R[X]
hp : Monic (map f p)
⊢ f (leadingCoeff p) = f 1

Next tactic:
rw [← leadingCoeff_of_injective hf, hp.leadingCoeff, f.map_one]
theorem monic_X_sub_C (x : R) : Monic (X - C x) := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p : R[X]
x : R
⊢ Monic (X - C x)

Next tactic:
simpa only [sub_eq_add_neg, C_neg] using monic_X_add_C (-x)
theorem monic_X_pow_sub {n : ℕ} (H : degree p ≤ n) : Monic (X ^ (n + 1) - p) := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n✝ : ℕ
ι : Type y
inst✝ : Ring R
p : R[X]
n : ℕ
H : degree p ≤ ↑n
⊢ Monic (X ^ (n + 1) - p)

Next tactic:
simpa [sub_eq_add_neg] using monic_X_pow_add (show degree (-p) ≤ n by rwa [← degree_neg p] at H)
theorem monic_X_pow_sub {n : ℕ} (H : degree p ≤ n) : Monic (X ^ (n + 1) - p) := by
  simpa [sub_eq_add_neg] using monic_X_pow_add (show degree (-p) ≤ n by 

Proof state:
R : Type u
S : Type v
a b : R
m n✝ : ℕ
ι : Type y
inst✝ : Ring R
p : R[X]
n : ℕ
H : degree p ≤ ↑n
⊢ degree (-p) ≤ ↑n

Next tactic:
rwa [← degree_neg p] at H
/-- `X ^ n - a` is monic. -/
theorem monic_X_pow_sub_C {R : Type u} [Ring R] (a : R) {n : ℕ} (h : n ≠ 0) :
    (X ^ n - C a).Monic := by
  

Proof state:
R✝ : Type u
S : Type v
a✝ b : R✝
m n✝ : ℕ
ι : Type y
inst✝¹ : Ring R✝
p : R✝[X]
R : Type u
inst✝ : Ring R
a : R
n : ℕ
h : n ≠ 0
⊢ Monic (X ^ n - C a)

Next tactic:
obtain ⟨k, rfl⟩ := Nat.exists_eq_succ_of_ne_zero h
/-- `X ^ n - a` is monic. -/
theorem monic_X_pow_sub_C {R : Type u} [Ring R] (a : R) {n : ℕ} (h : n ≠ 0) :
    (X ^ n - C a).Monic := by
  obtain ⟨k, rfl⟩ := Nat.exists_eq_succ_of_ne_zero h
  

Proof state:
case intro
R✝ : Type u
S : Type v
a✝ b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Ring R✝
p : R✝[X]
R : Type u
inst✝ : Ring R
a : R
k : ℕ
h : Nat.succ k ≠ 0
⊢ Monic (X ^ Nat.succ k - C a)

Next tactic:
apply monic_X_pow_sub _
/-- `X ^ n - a` is monic. -/
theorem monic_X_pow_sub_C {R : Type u} [Ring R] (a : R) {n : ℕ} (h : n ≠ 0) :
    (X ^ n - C a).Monic := by
  obtain ⟨k, rfl⟩ := Nat.exists_eq_succ_of_ne_zero h
  apply monic_X_pow_sub _
  

Proof state:
R✝ : Type u
S : Type v
a✝ b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Ring R✝
p : R✝[X]
R : Type u
inst✝ : Ring R
a : R
k : ℕ
h : Nat.succ k ≠ 0
⊢ degree (C a) ≤ ↑k

Next tactic:
exact le_trans degree_C_le Nat.WithBot.coe_nonneg
theorem not_isUnit_X_pow_sub_one (R : Type*) [CommRing R] [Nontrivial R] (n : ℕ) :
    ¬IsUnit (X ^ n - 1 : R[X]) := by
  

Proof state:
R✝ : Type u
S : Type v
a b : R✝
m n✝ : ℕ
ι : Type y
inst✝² : Ring R✝
p : R✝[X]
R : Type u_1
inst✝¹ : CommRing R
inst✝ : Nontrivial R
n : ℕ
⊢ ¬IsUnit (X ^ n - 1)

Next tactic:
intro h
theorem not_isUnit_X_pow_sub_one (R : Type*) [CommRing R] [Nontrivial R] (n : ℕ) :
    ¬IsUnit (X ^ n - 1 : R[X]) := by
  intro h
  

Proof state:
R✝ : Type u
S : Type v
a b : R✝
m n✝ : ℕ
ι : Type y
inst✝² : Ring R✝
p : R✝[X]
R : Type u_1
inst✝¹ : CommRing R
inst✝ : Nontrivial R
n : ℕ
h : IsUnit (X ^ n - 1)
⊢ False

Next tactic:
rcases eq_or_ne n 0 with (rfl | hn)
theorem not_isUnit_X_pow_sub_one (R : Type*) [CommRing R] [Nontrivial R] (n : ℕ) :
    ¬IsUnit (X ^ n - 1 : R[X]) := by
  intro h
  rcases eq_or_ne n 0 with (rfl | hn)
  · 

Proof state:
case inl
R✝ : Type u
S : Type v
a b : R✝
m n : ℕ
ι : Type y
inst✝² : Ring R✝
p : R✝[X]
R : Type u_1
inst✝¹ : CommRing R
inst✝ : Nontrivial R
h : IsUnit (X ^ 0 - 1)
⊢ False

Next tactic:
simp at h
theorem not_isUnit_X_pow_sub_one (R : Type*) [CommRing R] [Nontrivial R] (n : ℕ) :
    ¬IsUnit (X ^ n - 1 : R[X]) := by
  intro h
  rcases eq_or_ne n 0 with (rfl | hn)
  · simp at h
  

Proof state:
case inr
R✝ : Type u
S : Type v
a b : R✝
m n✝ : ℕ
ι : Type y
inst✝² : Ring R✝
p : R✝[X]
R : Type u_1
inst✝¹ : CommRing R
inst✝ : Nontrivial R
n : ℕ
h : IsUnit (X ^ n - 1)
hn : n ≠ 0
⊢ False

Next tactic:
apply hn
theorem not_isUnit_X_pow_sub_one (R : Type*) [CommRing R] [Nontrivial R] (n : ℕ) :
    ¬IsUnit (X ^ n - 1 : R[X]) := by
  intro h
  rcases eq_or_ne n 0 with (rfl | hn)
  · simp at h
  apply hn
  

Proof state:
case inr
R✝ : Type u
S : Type v
a b : R✝
m n✝ : ℕ
ι : Type y
inst✝² : Ring R✝
p : R✝[X]
R : Type u_1
inst✝¹ : CommRing R
inst✝ : Nontrivial R
n : ℕ
h : IsUnit (X ^ n - 1)
hn : n ≠ 0
⊢ n = 0

Next tactic:
rw [← @natDegree_one R, ← (monic_X_pow_sub_C _ hn).eq_one_of_isUnit h, natDegree_X_pow_sub_C]
theorem Monic.sub_of_left {p q : R[X]} (hp : Monic p) (hpq : degree q < degree p) :
    Monic (p - q) := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p✝ p q : R[X]
hp : Monic p
hpq : degree q < degree p
⊢ Monic (p - q)

Next tactic:
rw [sub_eq_add_neg]
theorem Monic.sub_of_left {p q : R[X]} (hp : Monic p) (hpq : degree q < degree p) :
    Monic (p - q) := by
  rw [sub_eq_add_neg]
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p✝ p q : R[X]
hp : Monic p
hpq : degree q < degree p
⊢ Monic (p + -q)

Next tactic:
apply hp.add_of_left
theorem Monic.sub_of_left {p q : R[X]} (hp : Monic p) (hpq : degree q < degree p) :
    Monic (p - q) := by
  rw [sub_eq_add_neg]
  apply hp.add_of_left
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p✝ p q : R[X]
hp : Monic p
hpq : degree q < degree p
⊢ degree (-q) < degree p

Next tactic:
rwa [degree_neg]
theorem Monic.sub_of_right {p q : R[X]} (hq : q.leadingCoeff = -1) (hpq : degree p < degree q) :
    Monic (p - q) := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p✝ p q : R[X]
hq : Polynomial.leadingCoeff q = -1
hpq : degree p < degree q
⊢ Monic (p - q)

Next tactic:
have : (-q).coeff (-q).natDegree = 1 := by
    rw [natDegree_neg, coeff_neg, show q.coeff q.natDegree = -1 from hq, neg_neg]
theorem Monic.sub_of_right {p q : R[X]} (hq : q.leadingCoeff = -1) (hpq : degree p < degree q) :
    Monic (p - q) := by
  have : (-q).coeff (-q).natDegree = 1 := by
    

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p✝ p q : R[X]
hq : Polynomial.leadingCoeff q = -1
hpq : degree p < degree q
⊢ coeff (-q) (natDegree (-q)) = 1

Next tactic:
rw [natDegree_neg, coeff_neg, show q.coeff q.natDegree = -1 from hq, neg_neg]
theorem Monic.sub_of_right {p q : R[X]} (hq : q.leadingCoeff = -1) (hpq : degree p < degree q) :
    Monic (p - q) := by
  have : (-q).coeff (-q).natDegree = 1 := by
    rw [natDegree_neg, coeff_neg, show q.coeff q.natDegree = -1 from hq, neg_neg]
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p✝ p q : R[X]
hq : Polynomial.leadingCoeff q = -1
hpq : degree p < degree q
this : coeff (-q) (natDegree (-q)) = 1
⊢ Monic (p - q)

Next tactic:
rw [sub_eq_add_neg]
theorem Monic.sub_of_right {p q : R[X]} (hq : q.leadingCoeff = -1) (hpq : degree p < degree q) :
    Monic (p - q) := by
  have : (-q).coeff (-q).natDegree = 1 := by
    rw [natDegree_neg, coeff_neg, show q.coeff q.natDegree = -1 from hq, neg_neg]
  rw [sub_eq_add_neg]
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p✝ p q : R[X]
hq : Polynomial.leadingCoeff q = -1
hpq : degree p < degree q
this : coeff (-q) (natDegree (-q)) = 1
⊢ Monic (p + -q)

Next tactic:
apply Monic.add_of_right this
theorem Monic.sub_of_right {p q : R[X]} (hq : q.leadingCoeff = -1) (hpq : degree p < degree q) :
    Monic (p - q) := by
  have : (-q).coeff (-q).natDegree = 1 := by
    rw [natDegree_neg, coeff_neg, show q.coeff q.natDegree = -1 from hq, neg_neg]
  rw [sub_eq_add_neg]
  apply Monic.add_of_right this
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Ring R
p✝ p q : R[X]
hq : Polynomial.leadingCoeff q = -1
hpq : degree p < degree q
this : coeff (-q) (natDegree (-q)) = 1
⊢ degree p < degree (-q)

Next tactic:
rwa [degree_neg]
theorem Monic.mul_left_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : q * p ≠ 0 := by
  

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

Next tactic:
by_cases h : p = 1
theorem Monic.mul_left_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : q * p ≠ 0 := by
  by_cases h : p = 1
  · 

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

Next tactic:
simpa [h]
theorem Monic.mul_left_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : q * p ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : ¬p = 1
⊢ q * p ≠ 0

Next tactic:
rw [Ne.def, ← degree_eq_bot, hp.degree_mul, WithBot.add_eq_bot, not_or, degree_eq_bot]
theorem Monic.mul_left_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : q * p ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  rw [Ne.def, ← degree_eq_bot, hp.degree_mul, WithBot.add_eq_bot, not_or, degree_eq_bot]
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : ¬p = 1
⊢ ¬q = 0 ∧ ¬degree p = ⊥

Next tactic:
refine' ⟨hq, _⟩
theorem Monic.mul_left_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : q * p ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  rw [Ne.def, ← degree_eq_bot, hp.degree_mul, WithBot.add_eq_bot, not_or, degree_eq_bot]
  refine' ⟨hq, _⟩
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : ¬p = 1
⊢ ¬degree p = ⊥

Next tactic:
rw [← hp.degree_le_zero_iff_eq_one, not_le] at h
theorem Monic.mul_left_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : q * p ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  rw [Ne.def, ← degree_eq_bot, hp.degree_mul, WithBot.add_eq_bot, not_or, degree_eq_bot]
  refine' ⟨hq, _⟩
  rw [← hp.degree_le_zero_iff_eq_one, not_le] at h
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : 0 < degree p
⊢ ¬degree p = ⊥

Next tactic:
refine' (lt_trans _ h).ne'
theorem Monic.mul_left_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : q * p ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  rw [Ne.def, ← degree_eq_bot, hp.degree_mul, WithBot.add_eq_bot, not_or, degree_eq_bot]
  refine' ⟨hq, _⟩
  rw [← hp.degree_le_zero_iff_eq_one, not_le] at h
  refine' (lt_trans _ h).ne'
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : 0 < degree p
⊢ ⊥ < 0

Next tactic:
simp
theorem Monic.mul_right_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : p * q ≠ 0 := by
  

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

Next tactic:
by_cases h : p = 1
theorem Monic.mul_right_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : p * q ≠ 0 := by
  by_cases h : p = 1
  · 

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

Next tactic:
simpa [h]
theorem Monic.mul_right_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : p * q ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : ¬p = 1
⊢ p * q ≠ 0

Next tactic:
rw [Ne.def, ← degree_eq_bot, hp.degree_mul_comm, hp.degree_mul, WithBot.add_eq_bot, not_or,
    degree_eq_bot]
theorem Monic.mul_right_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : p * q ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  rw [Ne.def, ← degree_eq_bot, hp.degree_mul_comm, hp.degree_mul, WithBot.add_eq_bot, not_or,
    degree_eq_bot]
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : ¬p = 1
⊢ ¬q = 0 ∧ ¬degree p = ⊥

Next tactic:
refine' ⟨hq, _⟩
theorem Monic.mul_right_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : p * q ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  rw [Ne.def, ← degree_eq_bot, hp.degree_mul_comm, hp.degree_mul, WithBot.add_eq_bot, not_or,
    degree_eq_bot]
  refine' ⟨hq, _⟩
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : ¬p = 1
⊢ ¬degree p = ⊥

Next tactic:
rw [← hp.degree_le_zero_iff_eq_one, not_le] at h
theorem Monic.mul_right_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : p * q ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  rw [Ne.def, ← degree_eq_bot, hp.degree_mul_comm, hp.degree_mul, WithBot.add_eq_bot, not_or,
    degree_eq_bot]
  refine' ⟨hq, _⟩
  rw [← hp.degree_le_zero_iff_eq_one, not_le] at h
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : 0 < degree p
⊢ ¬degree p = ⊥

Next tactic:
refine' (lt_trans _ h).ne'
theorem Monic.mul_right_ne_zero (hp : Monic p) {q : R[X]} (hq : q ≠ 0) : p * q ≠ 0 := by
  by_cases h : p = 1
  · simpa [h]
  rw [Ne.def, ← degree_eq_bot, hp.degree_mul_comm, hp.degree_mul, WithBot.add_eq_bot, not_or,
    degree_eq_bot]
  refine' ⟨hq, _⟩
  rw [← hp.degree_le_zero_iff_eq_one, not_le] at h
  refine' (lt_trans _ h).ne'
  

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
hp : Monic p
q : R[X]
hq : q ≠ 0
h : 0 < degree p
⊢ ⊥ < 0

Next tactic:
simp
theorem Monic.mul_natDegree_lt_iff (h : Monic p) {q : R[X]} :
    (p * q).natDegree < p.natDegree ↔ p ≠ 1 ∧ q = 0 := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
⊢ natDegree (p * q) < natDegree p ↔ p ≠ 1 ∧ q = 0

Next tactic:
by_cases hq : q = 0
theorem Monic.mul_natDegree_lt_iff (h : Monic p) {q : R[X]} :
    (p * q).natDegree < p.natDegree ↔ p ≠ 1 ∧ q = 0 := by
  by_cases hq : q = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
hq : q = 0
⊢ natDegree (p * q) < natDegree p ↔ p ≠ 1 ∧ q = 0

Next tactic:
suffices 0 < p.natDegree ↔ p.natDegree ≠ 0 by simpa [hq, ← h.natDegree_eq_zero_iff_eq_one]
theorem Monic.mul_natDegree_lt_iff (h : Monic p) {q : R[X]} :
    (p * q).natDegree < p.natDegree ↔ p ≠ 1 ∧ q = 0 := by
  by_cases hq : q = 0
  · suffices 0 < p.natDegree ↔ p.natDegree ≠ 0 by 

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
hq : q = 0
this : 0 < natDegree p ↔ natDegree p ≠ 0
⊢ natDegree (p * q) < natDegree p ↔ p ≠ 1 ∧ q = 0

Next tactic:
simpa [hq, ← h.natDegree_eq_zero_iff_eq_one]
theorem Monic.mul_natDegree_lt_iff (h : Monic p) {q : R[X]} :
    (p * q).natDegree < p.natDegree ↔ p ≠ 1 ∧ q = 0 := by
  by_cases hq : q = 0
  · suffices 0 < p.natDegree ↔ p.natDegree ≠ 0 by simpa [hq, ← h.natDegree_eq_zero_iff_eq_one]
    

Proof state:
case pos
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
hq : q = 0
⊢ 0 < natDegree p ↔ natDegree p ≠ 0

Next tactic:
exact ⟨fun h => h.ne', fun h => lt_of_le_of_ne (Nat.zero_le _) h.symm⟩
theorem Monic.mul_natDegree_lt_iff (h : Monic p) {q : R[X]} :
    (p * q).natDegree < p.natDegree ↔ p ≠ 1 ∧ q = 0 := by
  by_cases hq : q = 0
  · suffices 0 < p.natDegree ↔ p.natDegree ≠ 0 by simpa [hq, ← h.natDegree_eq_zero_iff_eq_one]
    exact ⟨fun h => h.ne', fun h => lt_of_le_of_ne (Nat.zero_le _) h.symm⟩
  · 

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
hq : ¬q = 0
⊢ natDegree (p * q) < natDegree p ↔ p ≠ 1 ∧ q = 0

Next tactic:
simp [h.natDegree_mul', hq]
theorem Monic.mul_right_eq_zero_iff (h : Monic p) {q : R[X]} : p * q = 0 ↔ q = 0 := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
⊢ p * q = 0 ↔ q = 0

Next tactic:
by_cases hq : q = 0
theorem Monic.mul_right_eq_zero_iff (h : Monic p) {q : R[X]} : p * q = 0 ↔ q = 0 := by
  by_cases hq : q = 0 <;> 

Proof state:
case pos
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
hq : q = 0
⊢ p * q = 0 ↔ q = 0

Next tactic:
simp [h.mul_right_ne_zero, hq]
theorem Monic.mul_right_eq_zero_iff (h : Monic p) {q : R[X]} : p * q = 0 ↔ q = 0 := by
  by_cases hq : q = 0 <;> 

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
hq : ¬q = 0
⊢ p * q = 0 ↔ q = 0

Next tactic:
simp [h.mul_right_ne_zero, hq]
theorem Monic.mul_left_eq_zero_iff (h : Monic p) {q : R[X]} : q * p = 0 ↔ q = 0 := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
⊢ q * p = 0 ↔ q = 0

Next tactic:
by_cases hq : q = 0
theorem Monic.mul_left_eq_zero_iff (h : Monic p) {q : R[X]} : q * p = 0 ↔ q = 0 := by
  by_cases hq : q = 0 <;> 

Proof state:
case pos
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
hq : q = 0
⊢ q * p = 0 ↔ q = 0

Next tactic:
simp [h.mul_left_ne_zero, hq]
theorem Monic.mul_left_eq_zero_iff (h : Monic p) {q : R[X]} : q * p = 0 ↔ q = 0 := by
  by_cases hq : q = 0 <;> 

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p : R[X]
h : Monic p
q : R[X]
hq : ¬q = 0
⊢ q * p = 0 ↔ q = 0

Next tactic:
simp [h.mul_left_ne_zero, hq]
theorem Monic.isRegular {R : Type*} [Ring R] {p : R[X]} (hp : Monic p) : IsRegular p := by
  

Proof state:
R✝ : Type u
S : Type v
a b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Semiring R✝
p✝ : R✝[X]
R : Type u_1
inst✝ : Ring R
p : R[X]
hp : Monic p
⊢ IsRegular p

Next tactic:
constructor
theorem Monic.isRegular {R : Type*} [Ring R] {p : R[X]} (hp : Monic p) : IsRegular p := by
  constructor
  · 

Proof state:
case left
R✝ : Type u
S : Type v
a b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Semiring R✝
p✝ : R✝[X]
R : Type u_1
inst✝ : Ring R
p : R[X]
hp : Monic p
⊢ IsLeftRegular p

Next tactic:
intro q r h
theorem Monic.isRegular {R : Type*} [Ring R] {p : R[X]} (hp : Monic p) : IsRegular p := by
  constructor
  · intro q r h
    

Proof state:
case left
R✝ : Type u
S : Type v
a b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Semiring R✝
p✝ : R✝[X]
R : Type u_1
inst✝ : Ring R
p : R[X]
hp : Monic p
q r : R[X]
h : (fun x => p * x) q = (fun x => p * x) r
⊢ q = r

Next tactic:
dsimp only at h
theorem Monic.isRegular {R : Type*} [Ring R] {p : R[X]} (hp : Monic p) : IsRegular p := by
  constructor
  · intro q r h
    dsimp only at h
    

Proof state:
case left
R✝ : Type u
S : Type v
a b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Semiring R✝
p✝ : R✝[X]
R : Type u_1
inst✝ : Ring R
p : R[X]
hp : Monic p
q r : R[X]
h : p * q = p * r
⊢ q = r

Next tactic:
rw [← sub_eq_zero, ← hp.mul_right_eq_zero_iff, mul_sub, h, sub_self]
theorem Monic.isRegular {R : Type*} [Ring R] {p : R[X]} (hp : Monic p) : IsRegular p := by
  constructor
  · intro q r h
    dsimp only at h
    rw [← sub_eq_zero, ← hp.mul_right_eq_zero_iff, mul_sub, h, sub_self]
  · 

Proof state:
case right
R✝ : Type u
S : Type v
a b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Semiring R✝
p✝ : R✝[X]
R : Type u_1
inst✝ : Ring R
p : R[X]
hp : Monic p
⊢ IsRightRegular p

Next tactic:
intro q r h
theorem Monic.isRegular {R : Type*} [Ring R] {p : R[X]} (hp : Monic p) : IsRegular p := by
  constructor
  · intro q r h
    dsimp only at h
    rw [← sub_eq_zero, ← hp.mul_right_eq_zero_iff, mul_sub, h, sub_self]
  · intro q r h
    

Proof state:
case right
R✝ : Type u
S : Type v
a b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Semiring R✝
p✝ : R✝[X]
R : Type u_1
inst✝ : Ring R
p : R[X]
hp : Monic p
q r : R[X]
h : (fun x => x * p) q = (fun x => x * p) r
⊢ q = r

Next tactic:
simp only at h
theorem Monic.isRegular {R : Type*} [Ring R] {p : R[X]} (hp : Monic p) : IsRegular p := by
  constructor
  · intro q r h
    dsimp only at h
    rw [← sub_eq_zero, ← hp.mul_right_eq_zero_iff, mul_sub, h, sub_self]
  · intro q r h
    simp only at h
    

Proof state:
case right
R✝ : Type u
S : Type v
a b : R✝
m n : ℕ
ι : Type y
inst✝¹ : Semiring R✝
p✝ : R✝[X]
R : Type u_1
inst✝ : Ring R
p : R[X]
hp : Monic p
q r : R[X]
h : q * p = r * p
⊢ q = r

Next tactic:
rw [← sub_eq_zero, ← hp.mul_left_eq_zero_iff, sub_mul, h, sub_self]
theorem degree_smul_of_smul_regular {S : Type*} [Monoid S] [DistribMulAction S R] {k : S}
    (p : R[X]) (h : IsSMulRegular R k) : (k • p).degree = p.degree := by
  

Proof state:
R : Type u
S✝ : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
p✝ : R[X]
S : Type u_1
inst✝¹ : Monoid S
inst✝ : DistribMulAction S R
k : S
p : R[X]
h : IsSMulRegular R k
⊢ degree (k • p) = degree p

Next tactic:
refine' le_antisymm _ _
theorem degree_smul_of_smul_regular {S : Type*} [Monoid S] [DistribMulAction S R] {k : S}
    (p : R[X]) (h : IsSMulRegular R k) : (k • p).degree = p.degree := by
  refine' le_antisymm _ _
  · 

Proof state:
case refine'_1
R : Type u
S✝ : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
p✝ : R[X]
S : Type u_1
inst✝¹ : Monoid S
inst✝ : DistribMulAction S R
k : S
p : R[X]
h : IsSMulRegular R k
⊢ degree (k • p) ≤ degree p

Next tactic:
rw [degree_le_iff_coeff_zero]
theorem degree_smul_of_smul_regular {S : Type*} [Monoid S] [DistribMulAction S R] {k : S}
    (p : R[X]) (h : IsSMulRegular R k) : (k • p).degree = p.degree := by
  refine' le_antisymm _ _
  · rw [degree_le_iff_coeff_zero]
    

Proof state:
case refine'_1
R : Type u
S✝ : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
p✝ : R[X]
S : Type u_1
inst✝¹ : Monoid S
inst✝ : DistribMulAction S R
k : S
p : R[X]
h : IsSMulRegular R k
⊢ ∀ (m : ℕ), degree p < ↑m → coeff (k • p) m = 0

Next tactic:
intro m hm
theorem degree_smul_of_smul_regular {S : Type*} [Monoid S] [DistribMulAction S R] {k : S}
    (p : R[X]) (h : IsSMulRegular R k) : (k • p).degree = p.degree := by
  refine' le_antisymm _ _
  · rw [degree_le_iff_coeff_zero]
    intro m hm
    

Proof state:
case refine'_1
R : Type u
S✝ : Type v
a b : R
m✝ n : ℕ
ι : Type y
inst✝² : Semiring R
p✝ : R[X]
S : Type u_1
inst✝¹ : Monoid S
inst✝ : DistribMulAction S R
k : S
p : R[X]
h : IsSMulRegular R k
m : ℕ
hm : degree p < ↑m
⊢ coeff (k • p) m = 0

Next tactic:
rw [degree_lt_iff_coeff_zero] at hm
theorem degree_smul_of_smul_regular {S : Type*} [Monoid S] [DistribMulAction S R] {k : S}
    (p : R[X]) (h : IsSMulRegular R k) : (k • p).degree = p.degree := by
  refine' le_antisymm _ _
  · rw [degree_le_iff_coeff_zero]
    intro m hm
    rw [degree_lt_iff_coeff_zero] at hm
    

Proof state:
case refine'_1
R : Type u
S✝ : Type v
a b : R
m✝ n : ℕ
ι : Type y
inst✝² : Semiring R
p✝ : R[X]
S : Type u_1
inst✝¹ : Monoid S
inst✝ : DistribMulAction S R
k : S
p : R[X]
h : IsSMulRegular R k
m : ℕ
hm : ∀ (m_1 : ℕ), m ≤ m_1 → coeff p m_1 = 0
⊢ coeff (k • p) m = 0

Next tactic:
simp [hm m le_rfl]
theorem degree_smul_of_smul_regular {S : Type*} [Monoid S] [DistribMulAction S R] {k : S}
    (p : R[X]) (h : IsSMulRegular R k) : (k • p).degree = p.degree := by
  refine' le_antisymm _ _
  · rw [degree_le_iff_coeff_zero]
    intro m hm
    rw [degree_lt_iff_coeff_zero] at hm
    simp [hm m le_rfl]
  · 

Proof state:
case refine'_2
R : Type u
S✝ : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
p✝ : R[X]
S : Type u_1
inst✝¹ : Monoid S
inst✝ : DistribMulAction S R
k : S
p : R[X]
h : IsSMulRegular R k
⊢ degree p ≤ degree (k • p)

Next tactic:
rw [degree_le_iff_coeff_zero]
theorem degree_smul_of_smul_regular {S : Type*} [Monoid S] [DistribMulAction S R] {k : S}
    (p : R[X]) (h : IsSMulRegular R k) : (k • p).degree = p.degree := by
  refine' le_antisymm _ _
  · rw [degree_le_iff_coeff_zero]
    intro m hm
    rw [degree_lt_iff_coeff_zero] at hm
    simp [hm m le_rfl]
  · rw [degree_le_iff_coeff_zero]
    

Proof state:
case refine'_2
R : Type u
S✝ : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
p✝ : R[X]
S : Type u_1
inst✝¹ : Monoid S
inst✝ : DistribMulAction S R
k : S
p : R[X]
h : IsSMulRegular R k
⊢ ∀ (m : ℕ), degree (k • p) < ↑m → coeff p m = 0

Next tactic:
intro m hm