l3lab/ntp-mathlib huggingface dataset:
theorem one_lt_rootMultiplicity_iff_isRoot_iterate_derivative
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ ∀ m ≤ 1, (derivative^[m] p).IsRoot t :=
  lt_rootMultiplicity_iff_isRoot_iterate_derivative_of_mem_nonZeroDivisors h
    (by 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
⊢ ↑(Nat.factorial 1) ∈ nonZeroDivisors R

Next tactic:
rw [Nat.factorial_one, Nat.cast_one]
theorem one_lt_rootMultiplicity_iff_isRoot_iterate_derivative
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ ∀ m ≤ 1, (derivative^[m] p).IsRoot t :=
  lt_rootMultiplicity_iff_isRoot_iterate_derivative_of_mem_nonZeroDivisors h
    (by rw [Nat.factorial_one, Nat.cast_one]; 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
⊢ 1 ∈ nonZeroDivisors R

Next tactic:
exact Submonoid.one_mem _
theorem one_lt_rootMultiplicity_iff_isRoot
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ p.IsRoot t ∧ (derivative p).IsRoot t := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
⊢ 1 < rootMultiplicity t p ↔ IsRoot p t ∧ IsRoot (derivative p) t

Next tactic:
rw [one_lt_rootMultiplicity_iff_isRoot_iterate_derivative h]
theorem one_lt_rootMultiplicity_iff_isRoot
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ p.IsRoot t ∧ (derivative p).IsRoot t := by
  rw [one_lt_rootMultiplicity_iff_isRoot_iterate_derivative h]
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
⊢ (∀ m ≤ 1, IsRoot ((⇑derivative)^[m] p) t) ↔ IsRoot p t ∧ IsRoot (derivative p) t

Next tactic:
refine ⟨fun h ↦ ⟨h 0 (by norm_num), h 1 (by norm_num)⟩, fun ⟨h0, h1⟩ m hm ↦ ?_⟩
theorem one_lt_rootMultiplicity_iff_isRoot
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ p.IsRoot t ∧ (derivative p).IsRoot t := by
  rw [one_lt_rootMultiplicity_iff_isRoot_iterate_derivative h]
  refine ⟨fun h ↦ ⟨h 0 (by 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h✝ : p ≠ 0
h : ∀ m ≤ 1, IsRoot ((⇑derivative)^[m] p) t
⊢ 0 ≤ 1

Next tactic:
norm_num
theorem one_lt_rootMultiplicity_iff_isRoot
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ p.IsRoot t ∧ (derivative p).IsRoot t := by
  rw [one_lt_rootMultiplicity_iff_isRoot_iterate_derivative h]
  refine ⟨fun h ↦ ⟨h 0 (by norm_num), h 1 (by 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h✝ : p ≠ 0
h : ∀ m ≤ 1, IsRoot ((⇑derivative)^[m] p) t
⊢ 1 ≤ 1

Next tactic:
norm_num
theorem one_lt_rootMultiplicity_iff_isRoot
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ p.IsRoot t ∧ (derivative p).IsRoot t := by
  rw [one_lt_rootMultiplicity_iff_isRoot_iterate_derivative h]
  refine ⟨fun h ↦ ⟨h 0 (by norm_num), h 1 (by norm_num)⟩, fun ⟨h0, h1⟩ m hm ↦ ?_⟩
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
x✝ : IsRoot p t ∧ IsRoot (derivative p) t
m : ℕ
hm : m ≤ 1
h0 : IsRoot p t
h1 : IsRoot (derivative p) t
⊢ IsRoot ((⇑derivative)^[m] p) t

Next tactic:
obtain (_|_|m) := m
theorem one_lt_rootMultiplicity_iff_isRoot
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ p.IsRoot t ∧ (derivative p).IsRoot t := by
  rw [one_lt_rootMultiplicity_iff_isRoot_iterate_derivative h]
  refine ⟨fun h ↦ ⟨h 0 (by norm_num), h 1 (by norm_num)⟩, fun ⟨h0, h1⟩ m hm ↦ ?_⟩
  obtain (_|_|m) := m
  

Proof state:
case zero
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
x✝ : IsRoot p t ∧ IsRoot (derivative p) t
h0 : IsRoot p t
h1 : IsRoot (derivative p) t
hm : Nat.zero ≤ 1
⊢ IsRoot ((⇑derivative)^[Nat.zero] p) t
case succ.zero
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
x✝ : IsRoot p t ∧ IsRoot (derivative p) t
h0 : IsRoot p t
h1 : IsRoot (derivative p) t
hm : Nat.succ Nat.zero ≤ 1
⊢ IsRoot ((⇑derivative)^[Nat.succ Nat.zero] p) t
case succ.succ
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
x✝ : IsRoot p t ∧ IsRoot (derivative p) t
h0 : IsRoot p t
h1 : IsRoot (derivative p) t
m : ℕ
hm : Nat.succ (Nat.succ m) ≤ 1
⊢ IsRoot ((⇑derivative)^[Nat.succ (Nat.succ m)] p) t

Next tactic:
exacts [h0, h1, by linarith [hm]]
theorem one_lt_rootMultiplicity_iff_isRoot
    {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ p.IsRoot t ∧ (derivative p).IsRoot t := by
  rw [one_lt_rootMultiplicity_iff_isRoot_iterate_derivative h]
  refine ⟨fun h ↦ ⟨h 0 (by norm_num), h 1 (by norm_num)⟩, fun ⟨h0, h1⟩ m hm ↦ ?_⟩
  obtain (_|_|m) := m
  exacts [h0, h1, by 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : CommRing R
p : R[X]
t : R
h : p ≠ 0
x✝ : IsRoot p t ∧ IsRoot (derivative p) t
h0 : IsRoot p t
h1 : IsRoot (derivative p) t
m : ℕ
hm : Nat.succ (Nat.succ m) ≤ 1
⊢ IsRoot ((⇑derivative)^[Nat.succ (Nat.succ m)] p) t

Next tactic:
linarith [hm]
theorem one_lt_rootMultiplicity_iff_isRoot_gcd
    [GCDMonoid R[X]] {p : R[X]} {t : R} (h : p ≠ 0) :
    1 < p.rootMultiplicity t ↔ (gcd p (derivative p)).IsRoot t := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : GCDMonoid R[X]
p : R[X]
t : R
h : p ≠ 0
⊢ 1 < rootMultiplicity t p ↔ IsRoot (gcd p (derivative p)) t

Next tactic:
simp_rw [one_lt_rootMultiplicity_iff_isRoot h, ← dvd_iff_isRoot, dvd_gcd_iff]
theorem derivative_rootMultiplicity_of_root [CharZero R] {p : R[X]} {t : R} (hpt : p.IsRoot t) :
    p.derivative.rootMultiplicity t = p.rootMultiplicity t - 1 := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : CharZero R
p : R[X]
t : R
hpt : IsRoot p t
⊢ rootMultiplicity t (derivative p) = rootMultiplicity t p - 1

Next tactic:
by_cases h : p = 0
theorem derivative_rootMultiplicity_of_root [CharZero R] {p : R[X]} {t : R} (hpt : p.IsRoot t) :
    p.derivative.rootMultiplicity t = p.rootMultiplicity t - 1 := by
  by_cases h : p = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : CharZero R
p : R[X]
t : R
hpt : IsRoot p t
h : p = 0
⊢ rootMultiplicity t (derivative p) = rootMultiplicity t p - 1

Next tactic:
rw [h, map_zero, rootMultiplicity_zero]
theorem derivative_rootMultiplicity_of_root [CharZero R] {p : R[X]} {t : R} (hpt : p.IsRoot t) :
    p.derivative.rootMultiplicity t = p.rootMultiplicity t - 1 := by
  by_cases h : p = 0
  · rw [h, map_zero, rootMultiplicity_zero]
  

Proof state:
case neg
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : CharZero R
p : R[X]
t : R
hpt : IsRoot p t
h : ¬p = 0
⊢ rootMultiplicity t (derivative p) = rootMultiplicity t p - 1

Next tactic:
exact derivative_rootMultiplicity_of_root_of_mem_nonZeroDivisors hpt <|
    mem_nonZeroDivisors_of_ne_zero <| Nat.cast_ne_zero.2 ((rootMultiplicity_pos h).2 hpt).ne'
theorem rootMultiplicity_sub_one_le_derivative_rootMultiplicity [CharZero R] (p : R[X]) (t : R) :
    p.rootMultiplicity t - 1 ≤ p.derivative.rootMultiplicity t := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : CharZero R
p : R[X]
t : R
⊢ rootMultiplicity t p - 1 ≤ rootMultiplicity t (derivative p)

Next tactic:
by_cases h : p.IsRoot t
theorem rootMultiplicity_sub_one_le_derivative_rootMultiplicity [CharZero R] (p : R[X]) (t : R) :
    p.rootMultiplicity t - 1 ≤ p.derivative.rootMultiplicity t := by
  by_cases h : p.IsRoot t
  · 

Proof state:
case pos
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : CharZero R
p : R[X]
t : R
h : IsRoot p t
⊢ rootMultiplicity t p - 1 ≤ rootMultiplicity t (derivative p)

Next tactic:
exact (derivative_rootMultiplicity_of_root h).symm.le
theorem rootMultiplicity_sub_one_le_derivative_rootMultiplicity [CharZero R] (p : R[X]) (t : R) :
    p.rootMultiplicity t - 1 ≤ p.derivative.rootMultiplicity t := by
  by_cases h : p.IsRoot t
  · exact (derivative_rootMultiplicity_of_root h).symm.le
  · 

Proof state:
case neg
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : CharZero R
p : R[X]
t : R
h : ¬IsRoot p t
⊢ rootMultiplicity t p - 1 ≤ rootMultiplicity t (derivative p)

Next tactic:
rw [rootMultiplicity_eq_zero h, zero_tsub]
theorem rootMultiplicity_sub_one_le_derivative_rootMultiplicity [CharZero R] (p : R[X]) (t : R) :
    p.rootMultiplicity t - 1 ≤ p.derivative.rootMultiplicity t := by
  by_cases h : p.IsRoot t
  · exact (derivative_rootMultiplicity_of_root h).symm.le
  · rw [rootMultiplicity_eq_zero h, zero_tsub]
    

Proof state:
case neg
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : CharZero R
p : R[X]
t : R
h : ¬IsRoot p t
⊢ 0 ≤ rootMultiplicity t (derivative p)

Next tactic:
exact zero_le _
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
p : R[X]
⊢ C ↑(normUnit (leadingCoeff p)) * C ↑(normUnit (leadingCoeff p))⁻¹ = 1

Next tactic:
rw [← RingHom.map_mul, Units.mul_inv, C_1]
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
p : R[X]
⊢ C ↑(normUnit (leadingCoeff p))⁻¹ * C ↑(normUnit (leadingCoeff p)) = 1

Next tactic:
rw [← RingHom.map_mul, Units.inv_mul, C_1]
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
⊢ ↑((fun p =>
          { val := C ↑(normUnit (leadingCoeff p)), inv := C ↑(normUnit (leadingCoeff p))⁻¹,
            val_inv := (_ : C ↑(normUnit (leadingCoeff p)) * C ↑(normUnit (leadingCoeff p))⁻¹ = 1),
            inv_val := (_ : C ↑(normUnit (leadingCoeff p))⁻¹ * C ↑(normUnit (leadingCoeff p)) = 1) })
        0) =
    ↑1

Next tactic:
simp
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by simp)
  normUnit_mul hp0 hq0 :=
    Units.ext
      (by
        

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
a✝ b✝ : R[X]
hp0 : a✝ ≠ 0
hq0 : b✝ ≠ 0
⊢ ↑((fun p =>
          { val := C ↑(normUnit (leadingCoeff p)), inv := C ↑(normUnit (leadingCoeff p))⁻¹,
            val_inv := (_ : C ↑(normUnit (leadingCoeff p)) * C ↑(normUnit (leadingCoeff p))⁻¹ = 1),
            inv_val := (_ : C ↑(normUnit (leadingCoeff p))⁻¹ * C ↑(normUnit (leadingCoeff p)) = 1) })
        (a✝ * b✝)) =
    ↑((fun p =>
            { val := C ↑(normUnit (leadingCoeff p)), inv := C ↑(normUnit (leadingCoeff p))⁻¹,
              val_inv := (_ : C ↑(normUnit (leadingCoeff p)) * C ↑(normUnit (leadingCoeff p))⁻¹ = 1),
              inv_val := (_ : C ↑(normUnit (leadingCoeff p))⁻¹ * C ↑(normUnit (leadingCoeff p)) = 1) })
          a✝ *
        (fun p =>
            { val := C ↑(normUnit (leadingCoeff p)), inv := C ↑(normUnit (leadingCoeff p))⁻¹,
              val_inv := (_ : C ↑(normUnit (leadingCoeff p)) * C ↑(normUnit (leadingCoeff p))⁻¹ = 1),
              inv_val := (_ : C ↑(normUnit (leadingCoeff p))⁻¹ * C ↑(normUnit (leadingCoeff p)) = 1) })
          b✝)

Next tactic:
dsimp
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by simp)
  normUnit_mul hp0 hq0 :=
    Units.ext
      (by
        dsimp
        

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
a✝ b✝ : R[X]
hp0 : a✝ ≠ 0
hq0 : b✝ ≠ 0
⊢ C ↑(normUnit (leadingCoeff (a✝ * b✝))) = C ↑(normUnit (leadingCoeff a✝)) * C ↑(normUnit (leadingCoeff b✝))

Next tactic:
rw [Ne.def, ← leadingCoeff_eq_zero] at *
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by simp)
  normUnit_mul hp0 hq0 :=
    Units.ext
      (by
        dsimp
        rw [Ne.def, ← leadingCoeff_eq_zero] at *
        

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
a✝ b✝ : R[X]
hp0 : ¬leadingCoeff a✝ = 0
hq0 : ¬leadingCoeff b✝ = 0
⊢ C ↑(normUnit (leadingCoeff (a✝ * b✝))) = C ↑(normUnit (leadingCoeff a✝)) * C ↑(normUnit (leadingCoeff b✝))

Next tactic:
rw [leadingCoeff_mul, normUnit_mul hp0 hq0, Units.val_mul, C_mul]
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by simp)
  normUnit_mul hp0 hq0 :=
    Units.ext
      (by
        dsimp
        rw [Ne.def, ← leadingCoeff_eq_zero] at *
        rw [leadingCoeff_mul, normUnit_mul hp0 hq0, Units.val_mul, C_mul])
  normUnit_coe_units u :=
    Units.ext
      (by
        

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
u : R[X]ˣ
⊢ ↑((fun p =>
          { val := C ↑(normUnit (leadingCoeff p)), inv := C ↑(normUnit (leadingCoeff p))⁻¹,
            val_inv := (_ : C ↑(normUnit (leadingCoeff p)) * C ↑(normUnit (leadingCoeff p))⁻¹ = 1),
            inv_val := (_ : C ↑(normUnit (leadingCoeff p))⁻¹ * C ↑(normUnit (leadingCoeff p)) = 1) })
        ↑u) =
    ↑u⁻¹

Next tactic:
dsimp
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by simp)
  normUnit_mul hp0 hq0 :=
    Units.ext
      (by
        dsimp
        rw [Ne.def, ← leadingCoeff_eq_zero] at *
        rw [leadingCoeff_mul, normUnit_mul hp0 hq0, Units.val_mul, C_mul])
  normUnit_coe_units u :=
    Units.ext
      (by
        dsimp
        

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
u : R[X]ˣ
⊢ C ↑(normUnit (leadingCoeff ↑u)) = ↑u⁻¹

Next tactic:
rw [← mul_one u⁻¹, Units.val_mul, Units.eq_inv_mul_iff_mul_eq]
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by simp)
  normUnit_mul hp0 hq0 :=
    Units.ext
      (by
        dsimp
        rw [Ne.def, ← leadingCoeff_eq_zero] at *
        rw [leadingCoeff_mul, normUnit_mul hp0 hq0, Units.val_mul, C_mul])
  normUnit_coe_units u :=
    Units.ext
      (by
        dsimp
        rw [← mul_one u⁻¹, Units.val_mul, Units.eq_inv_mul_iff_mul_eq]
        

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
u : R[X]ˣ
⊢ ↑u * C ↑(normUnit (leadingCoeff ↑u)) = ↑1

Next tactic:
rcases Polynomial.isUnit_iff.1 ⟨u, rfl⟩ with ⟨_, ⟨w, rfl⟩, h2⟩
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by simp)
  normUnit_mul hp0 hq0 :=
    Units.ext
      (by
        dsimp
        rw [Ne.def, ← leadingCoeff_eq_zero] at *
        rw [leadingCoeff_mul, normUnit_mul hp0 hq0, Units.val_mul, C_mul])
  normUnit_coe_units u :=
    Units.ext
      (by
        dsimp
        rw [← mul_one u⁻¹, Units.val_mul, Units.eq_inv_mul_iff_mul_eq]
        rcases Polynomial.isUnit_iff.1 ⟨u, rfl⟩ with ⟨_, ⟨w, rfl⟩, h2⟩
        

Proof state:
case intro.intro.intro
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
u : R[X]ˣ
w : Rˣ
h2 : C ↑w = ↑u
⊢ ↑u * C ↑(normUnit (leadingCoeff ↑u)) = ↑1

Next tactic:
rw [← h2, leadingCoeff_C, normUnit_coe_units, ← C_mul, Units.mul_inv, C_1]
instance instNormalizationMonoid : NormalizationMonoid R[X] where
  normUnit p :=
    ⟨C ↑(normUnit p.leadingCoeff), C ↑(normUnit p.leadingCoeff)⁻¹, by
      rw [← RingHom.map_mul, Units.mul_inv, C_1], by rw [← RingHom.map_mul, Units.inv_mul, C_1]⟩
  normUnit_zero := Units.ext (by simp)
  normUnit_mul hp0 hq0 :=
    Units.ext
      (by
        dsimp
        rw [Ne.def, ← leadingCoeff_eq_zero] at *
        rw [leadingCoeff_mul, normUnit_mul hp0 hq0, Units.val_mul, C_mul])
  normUnit_coe_units u :=
    Units.ext
      (by
        dsimp
        rw [← mul_one u⁻¹, Units.val_mul, Units.eq_inv_mul_iff_mul_eq]
        rcases Polynomial.isUnit_iff.1 ⟨u, rfl⟩ with ⟨_, ⟨w, rfl⟩, h2⟩
        rw [← h2, leadingCoeff_C, normUnit_coe_units, ← C_mul, Units.mul_inv, C_1]
        

Proof state:
case intro.intro.intro
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
u : R[X]ˣ
w : Rˣ
h2 : C ↑w = ↑u
⊢ 1 = ↑1

Next tactic:
rfl
@[simp]
theorem coe_normUnit {p : R[X]} : (normUnit p : R[X]) = C ↑(normUnit p.leadingCoeff) := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
p : R[X]
⊢ ↑(normUnit p) = C ↑(normUnit (leadingCoeff p))

Next tactic:
simp [normUnit]
theorem leadingCoeff_normalize (p : R[X]) :
    leadingCoeff (normalize p) = normalize (leadingCoeff p) := by 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
p : R[X]
⊢ leadingCoeff (normalize p) = normalize (leadingCoeff p)

Next tactic:
simp
theorem Monic.normalize_eq_self {p : R[X]} (hp : p.Monic) : normalize p = p := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
p : R[X]
hp : Monic p
⊢ normalize p = p

Next tactic:
simp only [Polynomial.coe_normUnit, normalize_apply, hp.leadingCoeff, normUnit_one,
    Units.val_one, Polynomial.C.map_one, mul_one]
theorem roots_normalize {p : R[X]} : (normalize p).roots = p.roots := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : CommRing R
inst✝¹ : IsDomain R
inst✝ : NormalizationMonoid R
p : R[X]
⊢ roots (normalize p) = roots p

Next tactic:
rw [normalize_apply, mul_comm, coe_normUnit, roots_C_mul _ (normUnit (leadingCoeff p)).ne_zero]
theorem degree_pos_of_ne_zero_of_nonunit (hp0 : p ≠ 0) (hp : ¬IsUnit p) : 0 < degree p :=
  lt_of_not_ge fun h => by
    

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : DivisionRing R
p q : R[X]
hp0 : p ≠ 0
hp : ¬IsUnit p
h : 0 ≥ degree p
⊢ False

Next tactic:
rw [eq_C_of_degree_le_zero h] at hp0 hp
theorem degree_pos_of_ne_zero_of_nonunit (hp0 : p ≠ 0) (hp : ¬IsUnit p) : 0 < degree p :=
  lt_of_not_ge fun h => by
    rw [eq_C_of_degree_le_zero h] at hp0 hp
    

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : DivisionRing R
p q : R[X]
hp0 : C (coeff p 0) ≠ 0
hp : ¬IsUnit (C (coeff p 0))
h : 0 ≥ degree p
⊢ False

Next tactic:
exact hp (IsUnit.map C (IsUnit.mk0 (coeff p 0) (mt C_inj.2 (by simpa using hp0))))
theorem degree_pos_of_ne_zero_of_nonunit (hp0 : p ≠ 0) (hp : ¬IsUnit p) : 0 < degree p :=
  lt_of_not_ge fun h => by
    rw [eq_C_of_degree_le_zero h] at hp0 hp
    exact hp (IsUnit.map C (IsUnit.mk0 (coeff p 0) (mt C_inj.2 (by 

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : DivisionRing R
p q : R[X]
hp0 : C (coeff p 0) ≠ 0
hp : ¬IsUnit (C (coeff p 0))
h : 0 ≥ degree p
⊢ ¬C (coeff p 0) = C 0

Next tactic:
simpa using hp0
theorem monic_mul_leadingCoeff_inv (h : p ≠ 0) : Monic (p * C (leadingCoeff p)⁻¹) := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : DivisionRing R
p q : R[X]
h : p ≠ 0
⊢ Monic (p * C (leadingCoeff p)⁻¹)

Next tactic:
rw [Monic, leadingCoeff_mul, leadingCoeff_C,
    mul_inv_cancel (show leadingCoeff p ≠ 0 from mt leadingCoeff_eq_zero.1 h)]
theorem degree_mul_leadingCoeff_inv (p : R[X]) (h : q ≠ 0) :
    degree (p * C (leadingCoeff q)⁻¹) = degree p := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : DivisionRing R
p✝ q p : R[X]
h : q ≠ 0
⊢ degree (p * C (leadingCoeff q)⁻¹) = degree p

Next tactic:
have h₁ : (leadingCoeff q)⁻¹ ≠ 0 := inv_ne_zero (mt leadingCoeff_eq_zero.1 h)
theorem degree_mul_leadingCoeff_inv (p : R[X]) (h : q ≠ 0) :
    degree (p * C (leadingCoeff q)⁻¹) = degree p := by
  have h₁ : (leadingCoeff q)⁻¹ ≠ 0 := inv_ne_zero (mt leadingCoeff_eq_zero.1 h)
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝ : DivisionRing R
p✝ q p : R[X]
h : q ≠ 0
h₁ : (leadingCoeff q)⁻¹ ≠ 0
⊢ degree (p * C (leadingCoeff q)⁻¹) = degree p

Next tactic:
rw [degree_mul, degree_C h₁, add_zero]
@[simp]
theorem map_eq_zero [Semiring S] [Nontrivial S] (f : R →+* S) : p.map f = 0 ↔ p = 0 := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : DivisionRing R
p q : R[X]
inst✝¹ : Semiring S
inst✝ : Nontrivial S
f : R →+* S
⊢ map f p = 0 ↔ p = 0

Next tactic:
simp only [Polynomial.ext_iff]
@[simp]
theorem map_eq_zero [Semiring S] [Nontrivial S] (f : R →+* S) : p.map f = 0 ↔ p = 0 := by
  simp only [Polynomial.ext_iff]
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : DivisionRing R
p q : R[X]
inst✝¹ : Semiring S
inst✝ : Nontrivial S
f : R →+* S
⊢ (∀ (n : ℕ), coeff (map f p) n = coeff 0 n) ↔ ∀ (n : ℕ), coeff p n = coeff 0 n

Next tactic:
congr!
@[simp]
theorem map_eq_zero [Semiring S] [Nontrivial S] (f : R →+* S) : p.map f = 0 ↔ p = 0 := by
  simp only [Polynomial.ext_iff]
  congr!
  

Proof state:
case a.h.a
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : DivisionRing R
p q : R[X]
inst✝¹ : Semiring S
inst✝ : Nontrivial S
f : R →+* S
a✝ : ℕ
⊢ coeff (map f p) a✝ = coeff 0 a✝ ↔ coeff p a✝ = coeff 0 a✝

Next tactic:
simp [map_eq_zero, coeff_map, coeff_zero]
@[simp]
theorem leadingCoeff_map [Semiring S] [Nontrivial S] (f : R →+* S) :
    leadingCoeff (p.map f) = f (leadingCoeff p) := by
  

Proof state:
R : Type u
S : Type v
k : Type y
A : Type z
a b : R
n : ℕ
inst✝² : DivisionRing R
p q : R[X]
inst✝¹ : Semiring S
inst✝ : Nontrivial S
f : R →+* S
⊢ leadingCoeff (map f p) = f (leadingCoeff p)

Next tactic:
simp only [← coeff_natDegree, coeff_map f, natDegree_map]