l3lab/ntp-mathlib huggingface dataset:
theorem eq_one_of_map_eq_one {S : Type*} [Semiring S] [Nontrivial S] (f : R →+* S) (hp : p.Monic)
    (map_eq : p.map f = 1) : p = 1 := by
  nontriviality R
  have hdeg : p.degree = 0 := by
    rw [← degree_map_eq_of_leadingCoeff_ne_zero f _, map_eq, degree_one]
    · rw [hp.leadingCoeff, f.map_one]
      exact one_ne_zero
  have hndeg : p.natDegree = 0 :=
    WithBot.coe_eq_coe.mp ((degree_eq_natDegree hp.ne_zero).symm.trans hdeg)
  

Proof state:
R : Type u
S✝ : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
p q r : R[X]
S : Type u_1
inst✝¹ : Semiring S
inst✝ : Nontrivial S
f : R →+* S
hp : Monic p
map_eq : Polynomial.map f p = 1
✝ : Nontrivial R
hdeg : degree p = 0
hndeg : natDegree p = 0
⊢ p = 1

Next tactic:
convert eq_C_of_degree_eq_zero hdeg
theorem eq_one_of_map_eq_one {S : Type*} [Semiring S] [Nontrivial S] (f : R →+* S) (hp : p.Monic)
    (map_eq : p.map f = 1) : p = 1 := by
  nontriviality R
  have hdeg : p.degree = 0 := by
    rw [← degree_map_eq_of_leadingCoeff_ne_zero f _, map_eq, degree_one]
    · rw [hp.leadingCoeff, f.map_one]
      exact one_ne_zero
  have hndeg : p.natDegree = 0 :=
    WithBot.coe_eq_coe.mp ((degree_eq_natDegree hp.ne_zero).symm.trans hdeg)
  convert eq_C_of_degree_eq_zero hdeg
  

Proof state:
case h.e'_3
R : Type u
S✝ : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
p q r : R[X]
S : Type u_1
inst✝¹ : Semiring S
inst✝ : Nontrivial S
f : R →+* S
hp : Monic p
map_eq : Polynomial.map f p = 1
✝ : Nontrivial R
hdeg : degree p = 0
hndeg : natDegree p = 0
⊢ 1 = C (coeff p 0)

Next tactic:
rw [← hndeg, ← Polynomial.leadingCoeff, hp.leadingCoeff, C.map_one]
theorem natDegree_pow (hp : p.Monic) (n : ℕ) : (p ^ n).natDegree = n * p.natDegree := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n✝ : ℕ
ι : Type y
inst✝ : Semiring R
p q r : R[X]
hp : Monic p
n : ℕ
⊢ natDegree (p ^ n) = n * natDegree p

Next tactic:
induction' n with n hn
theorem natDegree_pow (hp : p.Monic) (n : ℕ) : (p ^ n).natDegree = n * p.natDegree := by
  induction' n with n hn
  · 

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

Next tactic:
simp
theorem natDegree_pow (hp : p.Monic) (n : ℕ) : (p ^ n).natDegree = n * p.natDegree := by
  induction' n with n hn
  · simp
  · 

Proof state:
case succ
R : Type u
S : Type v
a b : R
m n✝ : ℕ
ι : Type y
inst✝ : Semiring R
p q r : R[X]
hp : Monic p
n : ℕ
hn : natDegree (p ^ n) = n * natDegree p
⊢ natDegree (p ^ Nat.succ n) = Nat.succ n * natDegree p

Next tactic:
rw [pow_succ, hp.natDegree_mul (hp.pow n), hn, Nat.succ_mul, add_comm]
@[simp]
theorem natDegree_pow_X_add_C [Nontrivial R] (n : ℕ) (r : R) : ((X + C r) ^ n).natDegree = n := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n✝ : ℕ
ι : Type y
inst✝¹ : Semiring R
p q r✝ : R[X]
inst✝ : Nontrivial R
n : ℕ
r : R
⊢ natDegree ((X + C r) ^ n) = n

Next tactic:
rw [(monic_X_add_C r).natDegree_pow, natDegree_X_add_C, mul_one]
theorem Monic.eq_one_of_isUnit (hm : Monic p) (hpu : IsUnit p) : p = 1 := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p q r : R[X]
hm : Monic p
hpu : IsUnit p
⊢ p = 1

Next tactic:
nontriviality R
theorem Monic.eq_one_of_isUnit (hm : Monic p) (hpu : IsUnit p) : p = 1 := by
  nontriviality R
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p q r : R[X]
hm : Monic p
hpu : IsUnit p
✝ : Nontrivial R
⊢ p = 1

Next tactic:
obtain ⟨q, h⟩ := hpu.exists_right_inv
theorem Monic.eq_one_of_isUnit (hm : Monic p) (hpu : IsUnit p) : p = 1 := by
  nontriviality R
  obtain ⟨q, h⟩ := hpu.exists_right_inv
  

Proof state:
case intro
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p q✝ r : R[X]
hm : Monic p
hpu : IsUnit p
✝ : Nontrivial R
q : R[X]
h : p * q = 1
⊢ p = 1

Next tactic:
have := hm.natDegree_mul' (right_ne_zero_of_mul_eq_one h)
theorem Monic.eq_one_of_isUnit (hm : Monic p) (hpu : IsUnit p) : p = 1 := by
  nontriviality R
  obtain ⟨q, h⟩ := hpu.exists_right_inv
  have := hm.natDegree_mul' (right_ne_zero_of_mul_eq_one h)
  

Proof state:
case intro
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p q✝ r : R[X]
hm : Monic p
hpu : IsUnit p
✝ : Nontrivial R
q : R[X]
h : p * q = 1
this : natDegree (p * q) = natDegree p + natDegree q
⊢ p = 1

Next tactic:
rw [h, natDegree_one, eq_comm, add_eq_zero_iff] at this
theorem Monic.eq_one_of_isUnit (hm : Monic p) (hpu : IsUnit p) : p = 1 := by
  nontriviality R
  obtain ⟨q, h⟩ := hpu.exists_right_inv
  have := hm.natDegree_mul' (right_ne_zero_of_mul_eq_one h)
  rw [h, natDegree_one, eq_comm, add_eq_zero_iff] at this
  

Proof state:
case intro
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p q✝ r : R[X]
hm : Monic p
hpu : IsUnit p
✝ : Nontrivial R
q : R[X]
h : p * q = 1
this : natDegree p = 0 ∧ natDegree q = 0
⊢ p = 1

Next tactic:
exact hm.natDegree_eq_zero_iff_eq_one.mp this.1
theorem eq_of_monic_of_associated (hp : p.Monic) (hq : q.Monic) (hpq : Associated p q) : p = q := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p q r : R[X]
hp : Monic p
hq : Monic q
hpq : Associated p q
⊢ p = q

Next tactic:
obtain ⟨u, rfl⟩ := hpq
theorem eq_of_monic_of_associated (hp : p.Monic) (hq : q.Monic) (hpq : Associated p q) : p = q := by
  obtain ⟨u, rfl⟩ := hpq
  

Proof state:
case intro
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : Semiring R
p r : R[X]
hp : Monic p
u : R[X]ˣ
hq : Monic (p * ↑u)
⊢ p = p * ↑u

Next tactic:
rw [(hp.of_mul_monic_left hq).eq_one_of_isUnit u.isUnit, mul_one]
theorem monic_multiset_prod_of_monic (t : Multiset ι) (f : ι → R[X]) (ht : ∀ i ∈ t, Monic (f i)) :
    Monic (t.map f).prod := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
ht : ∀ i ∈ t, Monic (f i)
⊢ Monic (Multiset.prod (Multiset.map f t))

Next tactic:
revert ht
theorem monic_multiset_prod_of_monic (t : Multiset ι) (f : ι → R[X]) (ht : ∀ i ∈ t, Monic (f i)) :
    Monic (t.map f).prod := by
  revert ht
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
⊢ (∀ i ∈ t, Monic (f i)) → Monic (Multiset.prod (Multiset.map f t))

Next tactic:
refine' t.induction_on _ _
theorem monic_multiset_prod_of_monic (t : Multiset ι) (f : ι → R[X]) (ht : ∀ i ∈ t, Monic (f i)) :
    Monic (t.map f).prod := by
  revert ht
  refine' t.induction_on _ _; · 

Proof state:
case refine'_1
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
⊢ (∀ i ∈ 0, Monic (f i)) → Monic (Multiset.prod (Multiset.map f 0))

Next tactic:
simp
theorem monic_multiset_prod_of_monic (t : Multiset ι) (f : ι → R[X]) (ht : ∀ i ∈ t, Monic (f i)) :
    Monic (t.map f).prod := by
  revert ht
  refine' t.induction_on _ _; · simp
  

Proof state:
case refine'_2
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
⊢ ∀ ⦃a : ι⦄ {s : Multiset ι},
    ((∀ i ∈ s, Monic (f i)) → Monic (Multiset.prod (Multiset.map f s))) →
      (∀ i ∈ a ::ₘ s, Monic (f i)) → Monic (Multiset.prod (Multiset.map f (a ::ₘ s)))

Next tactic:
intro a t ih ht
theorem monic_multiset_prod_of_monic (t : Multiset ι) (f : ι → R[X]) (ht : ∀ i ∈ t, Monic (f i)) :
    Monic (t.map f).prod := by
  revert ht
  refine' t.induction_on _ _; · simp
  intro a t ih ht
  

Proof state:
case refine'_2
R : Type u
S : Type v
a✝ b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t✝ : Multiset ι
f : ι → R[X]
a : ι
t : Multiset ι
ih : (∀ i ∈ t, Monic (f i)) → Monic (Multiset.prod (Multiset.map f t))
ht : ∀ i ∈ a ::ₘ t, Monic (f i)
⊢ Monic (Multiset.prod (Multiset.map f (a ::ₘ t)))

Next tactic:
rw [Multiset.map_cons, Multiset.prod_cons]
theorem monic_multiset_prod_of_monic (t : Multiset ι) (f : ι → R[X]) (ht : ∀ i ∈ t, Monic (f i)) :
    Monic (t.map f).prod := by
  revert ht
  refine' t.induction_on _ _; · simp
  intro a t ih ht
  rw [Multiset.map_cons, Multiset.prod_cons]
  

Proof state:
case refine'_2
R : Type u
S : Type v
a✝ b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t✝ : Multiset ι
f : ι → R[X]
a : ι
t : Multiset ι
ih : (∀ i ∈ t, Monic (f i)) → Monic (Multiset.prod (Multiset.map f t))
ht : ∀ i ∈ a ::ₘ t, Monic (f i)
⊢ Monic (f a * Multiset.prod (Multiset.map f t))

Next tactic:
exact (ht _ (Multiset.mem_cons_self _ _)).mul (ih fun _ hi => ht _ (Multiset.mem_cons_of_mem hi))
theorem Monic.nextCoeff_multiset_prod (t : Multiset ι) (f : ι → R[X]) (h : ∀ i ∈ t, Monic (f i)) :
    nextCoeff (t.map f).prod = (t.map fun i => nextCoeff (f i)).sum := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
h : ∀ i ∈ t, Monic (f i)
⊢ nextCoeff (Multiset.prod (Multiset.map f t)) = Multiset.sum (Multiset.map (fun i => nextCoeff (f i)) t)

Next tactic:
revert h
theorem Monic.nextCoeff_multiset_prod (t : Multiset ι) (f : ι → R[X]) (h : ∀ i ∈ t, Monic (f i)) :
    nextCoeff (t.map f).prod = (t.map fun i => nextCoeff (f i)).sum := by
  revert h
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
⊢ (∀ i ∈ t, Monic (f i)) →
    nextCoeff (Multiset.prod (Multiset.map f t)) = Multiset.sum (Multiset.map (fun i => nextCoeff (f i)) t)

Next tactic:
refine' Multiset.induction_on t _ fun a t ih ht => _
theorem Monic.nextCoeff_multiset_prod (t : Multiset ι) (f : ι → R[X]) (h : ∀ i ∈ t, Monic (f i)) :
    nextCoeff (t.map f).prod = (t.map fun i => nextCoeff (f i)).sum := by
  revert h
  refine' Multiset.induction_on t _ fun a t ih ht => _
  · 

Proof state:
case refine'_1
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
⊢ (∀ i ∈ 0, Monic (f i)) →
    nextCoeff (Multiset.prod (Multiset.map f 0)) = Multiset.sum (Multiset.map (fun i => nextCoeff (f i)) 0)

Next tactic:
simp only [Multiset.not_mem_zero, forall_prop_of_true, forall_prop_of_false, Multiset.map_zero,
      Multiset.prod_zero, Multiset.sum_zero, not_false_iff, forall_true_iff]
theorem Monic.nextCoeff_multiset_prod (t : Multiset ι) (f : ι → R[X]) (h : ∀ i ∈ t, Monic (f i)) :
    nextCoeff (t.map f).prod = (t.map fun i => nextCoeff (f i)).sum := by
  revert h
  refine' Multiset.induction_on t _ fun a t ih ht => _
  · simp only [Multiset.not_mem_zero, forall_prop_of_true, forall_prop_of_false, Multiset.map_zero,
      Multiset.prod_zero, Multiset.sum_zero, not_false_iff, forall_true_iff]
    

Proof state:
case refine'_1
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
⊢ nextCoeff 1 = 0

Next tactic:
rw [← C_1]
theorem Monic.nextCoeff_multiset_prod (t : Multiset ι) (f : ι → R[X]) (h : ∀ i ∈ t, Monic (f i)) :
    nextCoeff (t.map f).prod = (t.map fun i => nextCoeff (f i)).sum := by
  revert h
  refine' Multiset.induction_on t _ fun a t ih ht => _
  · simp only [Multiset.not_mem_zero, forall_prop_of_true, forall_prop_of_false, Multiset.map_zero,
      Multiset.prod_zero, Multiset.sum_zero, not_false_iff, forall_true_iff]
    rw [← C_1]
    

Proof state:
case refine'_1
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t : Multiset ι
f : ι → R[X]
⊢ nextCoeff (C 1) = 0

Next tactic:
rw [nextCoeff_C_eq_zero]
theorem Monic.nextCoeff_multiset_prod (t : Multiset ι) (f : ι → R[X]) (h : ∀ i ∈ t, Monic (f i)) :
    nextCoeff (t.map f).prod = (t.map fun i => nextCoeff (f i)).sum := by
  revert h
  refine' Multiset.induction_on t _ fun a t ih ht => _
  · simp only [Multiset.not_mem_zero, forall_prop_of_true, forall_prop_of_false, Multiset.map_zero,
      Multiset.prod_zero, Multiset.sum_zero, not_false_iff, forall_true_iff]
    rw [← C_1]
    rw [nextCoeff_C_eq_zero]
  · 

Proof state:
case refine'_2
R : Type u
S : Type v
a✝ b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t✝ : Multiset ι
f : ι → R[X]
a : ι
t : Multiset ι
ih :
  (∀ i ∈ t, Monic (f i)) →
    nextCoeff (Multiset.prod (Multiset.map f t)) = Multiset.sum (Multiset.map (fun i => nextCoeff (f i)) t)
ht : ∀ i ∈ a ::ₘ t, Monic (f i)
⊢ nextCoeff (Multiset.prod (Multiset.map f (a ::ₘ t))) =
    Multiset.sum (Multiset.map (fun i => nextCoeff (f i)) (a ::ₘ t))

Next tactic:
rw [Multiset.map_cons, Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons,
      Monic.nextCoeff_mul, ih]
theorem Monic.nextCoeff_multiset_prod (t : Multiset ι) (f : ι → R[X]) (h : ∀ i ∈ t, Monic (f i)) :
    nextCoeff (t.map f).prod = (t.map fun i => nextCoeff (f i)).sum := by
  revert h
  refine' Multiset.induction_on t _ fun a t ih ht => _
  · simp only [Multiset.not_mem_zero, forall_prop_of_true, forall_prop_of_false, Multiset.map_zero,
      Multiset.prod_zero, Multiset.sum_zero, not_false_iff, forall_true_iff]
    rw [← C_1]
    rw [nextCoeff_C_eq_zero]
  · rw [Multiset.map_cons, Multiset.prod_cons, Multiset.map_cons, Multiset.sum_cons,
      Monic.nextCoeff_mul, ih]
    

Proof state:
case refine'_2
R : Type u
S : Type v
a✝ b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t✝ : Multiset ι
f : ι → R[X]
a : ι
t : Multiset ι
ih :
  (∀ i ∈ t, Monic (f i)) →
    nextCoeff (Multiset.prod (Multiset.map f t)) = Multiset.sum (Multiset.map (fun i => nextCoeff (f i)) t)
ht : ∀ i ∈ a ::ₘ t, Monic (f i)
⊢ ∀ i ∈ t, Monic (f i)
case refine'_2.hp
R : Type u
S : Type v
a✝ b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t✝ : Multiset ι
f : ι → R[X]
a : ι
t : Multiset ι
ih :
  (∀ i ∈ t, Monic (f i)) →
    nextCoeff (Multiset.prod (Multiset.map f t)) = Multiset.sum (Multiset.map (fun i => nextCoeff (f i)) t)
ht : ∀ i ∈ a ::ₘ t, Monic (f i)
⊢ Monic (f a)
case refine'_2.hq
R : Type u
S : Type v
a✝ b : R
m n : ℕ
ι : Type y
inst✝ : CommSemiring R
p : R[X]
t✝ : Multiset ι
f : ι → R[X]
a : ι
t : Multiset ι
ih :
  (∀ i ∈ t, Monic (f i)) →
    nextCoeff (Multiset.prod (Multiset.map f t)) = Multiset.sum (Multiset.map (fun i => nextCoeff (f i)) t)
ht : ∀ i ∈ a ::ₘ t, Monic (f i)
⊢ Monic (Multiset.prod (Multiset.map f t))

Next tactic:
exacts [fun i hi => ht i (Multiset.mem_cons_of_mem hi), ht a (Multiset.mem_cons_self _ _),
      monic_multiset_prod_of_monic _ _ fun b bs => ht _ (Multiset.mem_cons_of_mem bs)]
@[simp]
theorem Monic.natDegree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).natDegree = P.natDegree := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
⊢ natDegree (Polynomial.map f P) = natDegree P

Next tactic:
refine' le_antisymm (natDegree_map_le _ _) (le_natDegree_of_ne_zero _)
@[simp]
theorem Monic.natDegree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).natDegree = P.natDegree := by
  refine' le_antisymm (natDegree_map_le _ _) (le_natDegree_of_ne_zero _)
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
⊢ coeff (Polynomial.map f P) (natDegree P) ≠ 0

Next tactic:
rw [coeff_map, Monic.coeff_natDegree hmo, RingHom.map_one]
@[simp]
theorem Monic.natDegree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).natDegree = P.natDegree := by
  refine' le_antisymm (natDegree_map_le _ _) (le_natDegree_of_ne_zero _)
  rw [coeff_map, Monic.coeff_natDegree hmo, RingHom.map_one]
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
⊢ 1 ≠ 0

Next tactic:
exact one_ne_zero
@[simp]
theorem Monic.degree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).degree = P.degree := by
  

Proof state:
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
⊢ degree (Polynomial.map f P) = degree P

Next tactic:
by_cases hP : P = 0
@[simp]
theorem Monic.degree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).degree = P.degree := by
  by_cases hP : P = 0
  · 

Proof state:
case pos
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
hP : P = 0
⊢ degree (Polynomial.map f P) = degree P

Next tactic:
simp [hP]
@[simp]
theorem Monic.degree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).degree = P.degree := by
  by_cases hP : P = 0
  · simp [hP]
  · 

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
hP : ¬P = 0
⊢ degree (Polynomial.map f P) = degree P

Next tactic:
refine' le_antisymm (degree_map_le _ _) _
@[simp]
theorem Monic.degree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).degree = P.degree := by
  by_cases hP : P = 0
  · simp [hP]
  · refine' le_antisymm (degree_map_le _ _) _
    

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
hP : ¬P = 0
⊢ degree P ≤ degree (Polynomial.map f P)

Next tactic:
rw [degree_eq_natDegree hP]
@[simp]
theorem Monic.degree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).degree = P.degree := by
  by_cases hP : P = 0
  · simp [hP]
  · refine' le_antisymm (degree_map_le _ _) _
    rw [degree_eq_natDegree hP]
    

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
hP : ¬P = 0
⊢ ↑(natDegree P) ≤ degree (Polynomial.map f P)

Next tactic:
refine' le_degree_of_ne_zero _
@[simp]
theorem Monic.degree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).degree = P.degree := by
  by_cases hP : P = 0
  · simp [hP]
  · refine' le_antisymm (degree_map_le _ _) _
    rw [degree_eq_natDegree hP]
    refine' le_degree_of_ne_zero _
    

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
hP : ¬P = 0
⊢ coeff (Polynomial.map f P) (natDegree P) ≠ 0

Next tactic:
rw [coeff_map, Monic.coeff_natDegree hmo, RingHom.map_one]
@[simp]
theorem Monic.degree_map [Semiring S] [Nontrivial S] {P : R[X]} (hmo : P.Monic) (f : R →+* S) :
    (P.map f).degree = P.degree := by
  by_cases hP : P = 0
  · simp [hP]
  · refine' le_antisymm (degree_map_le _ _) _
    rw [degree_eq_natDegree hP]
    refine' le_degree_of_ne_zero _
    rw [coeff_map, Monic.coeff_natDegree hmo, RingHom.map_one]
    

Proof state:
case neg
R : Type u
S : Type v
a b : R
m n : ℕ
ι : Type y
inst✝² : Semiring R
inst✝¹ : Semiring S
inst✝ : Nontrivial S
P : R[X]
hmo : Monic P
f : R →+* S
hP : ¬P = 0
⊢ 1 ≠ 0

Next tactic:
exact one_ne_zero
theorem degree_map_eq_of_injective (p : R[X]) : degree (p.map f) = degree p :=
  letI := Classical.decEq R
  if h : p = 0 then by 

Proof state:
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]
this : DecidableEq R := Classical.decEq R
h : p = 0
⊢ degree (map f p) = degree p

Next tactic:
simp [h]
theorem degree_map_eq_of_injective (p : R[X]) : degree (p.map f) = degree p :=
  letI := Classical.decEq R
  if h : p = 0 then by simp [h]
  else
    degree_map_eq_of_leadingCoeff_ne_zero _
      (by 

Proof state:
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]
this : DecidableEq R := Classical.decEq R
h : ¬p = 0
⊢ f (leadingCoeff p) ≠ 0

Next tactic:
rw [← f.map_zero]
theorem degree_map_eq_of_injective (p : R[X]) : degree (p.map f) = degree p :=
  letI := Classical.decEq R
  if h : p = 0 then by simp [h]
  else
    degree_map_eq_of_leadingCoeff_ne_zero _
      (by rw [← f.map_zero]; 

Proof state:
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]
this : DecidableEq R := Classical.decEq R
h : ¬p = 0
⊢ f (leadingCoeff p) ≠ f 0

Next tactic:
exact mt hf.eq_iff.1 (mt leadingCoeff_eq_zero.1 h)
theorem leadingCoeff_map' (p : R[X]) : leadingCoeff (p.map f) = f (leadingCoeff p) := by
  

Proof state:
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]
⊢ leadingCoeff (map f p) = f (leadingCoeff p)

Next tactic:
unfold leadingCoeff
theorem leadingCoeff_map' (p : R[X]) : leadingCoeff (p.map f) = f (leadingCoeff p) := by
  unfold leadingCoeff
  

Proof state:
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]
⊢ coeff (map f p) (natDegree (map f p)) = f (coeff p (natDegree p))

Next tactic:
rw [coeff_map, natDegree_map_eq_of_injective hf p]
theorem nextCoeff_map (p : R[X]) : (p.map f).nextCoeff = f p.nextCoeff := by
  

Proof state:
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]
⊢ nextCoeff (map f p) = f (nextCoeff p)

Next tactic:
unfold nextCoeff
theorem nextCoeff_map (p : R[X]) : (p.map f).nextCoeff = f p.nextCoeff := by
  unfold nextCoeff
  

Proof state:
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]
⊢ (if natDegree (map f p) = 0 then 0 else coeff (map f p) (natDegree (map f p) - 1)) =
    f (if natDegree p = 0 then 0 else coeff p (natDegree p - 1))

Next tactic:
rw [natDegree_map_eq_of_injective hf]
theorem nextCoeff_map (p : R[X]) : (p.map f).nextCoeff = f p.nextCoeff := by
  unfold nextCoeff
  rw [natDegree_map_eq_of_injective hf]
  

Proof state:
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]
⊢ (if natDegree p = 0 then 0 else coeff (map f p) (natDegree p - 1)) =
    f (if natDegree p = 0 then 0 else coeff p (natDegree p - 1))

Next tactic:
split_ifs
theorem nextCoeff_map (p : R[X]) : (p.map f).nextCoeff = f p.nextCoeff := by
  unfold nextCoeff
  rw [natDegree_map_eq_of_injective hf]
  split_ifs <;> 

Proof state:
case pos
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]
h✝ : natDegree p = 0
⊢ 0 = f 0

Next tactic:
simp [*]
theorem nextCoeff_map (p : R[X]) : (p.map f).nextCoeff = f p.nextCoeff := by
  unfold nextCoeff
  rw [natDegree_map_eq_of_injective hf]
  split_ifs <;> 

Proof state:
case neg
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]
h✝ : ¬natDegree p = 0
⊢ coeff (map f p) (natDegree p - 1) = f (coeff p (natDegree p - 1))

Next tactic:
simp [*]
theorem leadingCoeff_of_injective (p : R[X]) : leadingCoeff (p.map f) = f (leadingCoeff p) := by
  

Proof state:
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]
⊢ leadingCoeff (map f p) = f (leadingCoeff p)

Next tactic:
delta leadingCoeff
theorem leadingCoeff_of_injective (p : R[X]) : leadingCoeff (p.map f) = f (leadingCoeff p) := by
  delta leadingCoeff
  

Proof state:
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]
⊢ coeff (map f p) (natDegree (map f p)) = f (coeff p (natDegree p))

Next tactic:
rw [coeff_map f, natDegree_map_eq_of_injective hf p]
theorem monic_of_injective {p : R[X]} (hp : (p.map f).Monic) : p.Monic := by
  

Proof state:
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)
⊢ Monic p

Next tactic:
apply hf