l3lab/ntp-mathlib huggingface dataset:
/-- A polynomial lifts if and only if it can be lifted to a polynomial of the same degree. -/
theorem mem_lifts_and_degree_eq {p : S[X]} (hlifts : p ∈ lifts f) :
    ∃ q : R[X], map f q = p ∧ q.degree = p.degree := by
  generalize hd : p.natDegree = d
  revert hd p
  induction' d using Nat.strong_induction_on with n hn
  intros p hlifts hdeg
  by_cases erase_zero : p.eraseLead = 0
  · rw [← eraseLead_add_monomial_natDegree_leadingCoeff p, erase_zero, zero_add, leadingCoeff]
    exact
      monomial_mem_lifts_and_degree_eq
        (monomial_mem_lifts p.natDegree ((lifts_iff_coeff_lifts p).1 hlifts p.natDegree))
  have deg_erase := Or.resolve_right (eraseLead_natDegree_lt_or_eraseLead_eq_zero p) erase_zero
  have pzero : p ≠ 0 := by
    intro habs
    exfalso
    rw [habs, eraseLead_zero, eq_self_iff_true, not_true] at erase_zero
    exact erase_zero
  have lead_zero : p.coeff p.natDegree ≠ 0 := by
    rw [← leadingCoeff, Ne.def, leadingCoeff_eq_zero]; exact pzero
  obtain ⟨lead, hlead⟩ :=
    monomial_mem_lifts_and_degree_eq
      (monomial_mem_lifts p.natDegree ((lifts_iff_coeff_lifts p).1 hlifts p.natDegree))
  have deg_lead : lead.degree = p.natDegree := by
    rw [hlead.2, ← C_mul_X_pow_eq_monomial, degree_C_mul_X_pow p.natDegree lead_zero]
  rw [hdeg] at deg_erase
  obtain ⟨erase, herase⟩ :=
    hn p.eraseLead.natDegree deg_erase (erase_mem_lifts p.natDegree hlifts)
      (refl p.eraseLead.natDegree)
  use erase + lead
  constructor
  · simp only [hlead, herase, Polynomial.map_add]
    rw [← eraseLead, ← leadingCoeff]
    rw [eraseLead_add_monomial_natDegree_leadingCoeff p]
  

Proof state:
case h.right
R : Type u
inst✝¹ : Semiring R
S : Type v
inst✝ : Semiring S
f : R →+* S
n : ℕ
hn : ∀ m < n, ∀ {p : S[X]}, p ∈ lifts f → natDegree p = m → ∃ q, map f q = p ∧ degree q = degree p
p : S[X]
hlifts : p ∈ lifts f
hdeg : natDegree p = n
erase_zero : ¬eraseLead p = 0
deg_erase : natDegree (eraseLead p) < n
pzero : p ≠ 0
lead_zero : coeff p (natDegree p) ≠ 0
lead : R[X]
hlead :
  map f lead = (monomial (natDegree p)) (coeff p (natDegree p)) ∧
    degree lead = degree ((monomial (natDegree p)) (coeff p (natDegree p)))
deg_lead : degree lead = ↑(natDegree p)
erase : R[X]
herase : map f erase = Polynomial.erase (natDegree p) p ∧ degree erase = degree (Polynomial.erase (natDegree p) p)
⊢ degree (erase + lead) = degree p

Next tactic:
rw [degree_eq_natDegree pzero, ← deg_lead]
/-- A polynomial lifts if and only if it can be lifted to a polynomial of the same degree. -/
theorem mem_lifts_and_degree_eq {p : S[X]} (hlifts : p ∈ lifts f) :
    ∃ q : R[X], map f q = p ∧ q.degree = p.degree := by
  generalize hd : p.natDegree = d
  revert hd p
  induction' d using Nat.strong_induction_on with n hn
  intros p hlifts hdeg
  by_cases erase_zero : p.eraseLead = 0
  · rw [← eraseLead_add_monomial_natDegree_leadingCoeff p, erase_zero, zero_add, leadingCoeff]
    exact
      monomial_mem_lifts_and_degree_eq
        (monomial_mem_lifts p.natDegree ((lifts_iff_coeff_lifts p).1 hlifts p.natDegree))
  have deg_erase := Or.resolve_right (eraseLead_natDegree_lt_or_eraseLead_eq_zero p) erase_zero
  have pzero : p ≠ 0 := by
    intro habs
    exfalso
    rw [habs, eraseLead_zero, eq_self_iff_true, not_true] at erase_zero
    exact erase_zero
  have lead_zero : p.coeff p.natDegree ≠ 0 := by
    rw [← leadingCoeff, Ne.def, leadingCoeff_eq_zero]; exact pzero
  obtain ⟨lead, hlead⟩ :=
    monomial_mem_lifts_and_degree_eq
      (monomial_mem_lifts p.natDegree ((lifts_iff_coeff_lifts p).1 hlifts p.natDegree))
  have deg_lead : lead.degree = p.natDegree := by
    rw [hlead.2, ← C_mul_X_pow_eq_monomial, degree_C_mul_X_pow p.natDegree lead_zero]
  rw [hdeg] at deg_erase
  obtain ⟨erase, herase⟩ :=
    hn p.eraseLead.natDegree deg_erase (erase_mem_lifts p.natDegree hlifts)
      (refl p.eraseLead.natDegree)
  use erase + lead
  constructor
  · simp only [hlead, herase, Polynomial.map_add]
    rw [← eraseLead, ← leadingCoeff]
    rw [eraseLead_add_monomial_natDegree_leadingCoeff p]
  rw [degree_eq_natDegree pzero, ← deg_lead]
  

Proof state:
case h.right
R : Type u
inst✝¹ : Semiring R
S : Type v
inst✝ : Semiring S
f : R →+* S
n : ℕ
hn : ∀ m < n, ∀ {p : S[X]}, p ∈ lifts f → natDegree p = m → ∃ q, map f q = p ∧ degree q = degree p
p : S[X]
hlifts : p ∈ lifts f
hdeg : natDegree p = n
erase_zero : ¬eraseLead p = 0
deg_erase : natDegree (eraseLead p) < n
pzero : p ≠ 0
lead_zero : coeff p (natDegree p) ≠ 0
lead : R[X]
hlead :
  map f lead = (monomial (natDegree p)) (coeff p (natDegree p)) ∧
    degree lead = degree ((monomial (natDegree p)) (coeff p (natDegree p)))
deg_lead : degree lead = ↑(natDegree p)
erase : R[X]
herase : map f erase = Polynomial.erase (natDegree p) p ∧ degree erase = degree (Polynomial.erase (natDegree p) p)
⊢ degree (erase + lead) = degree lead

Next tactic:
apply degree_add_eq_right_of_degree_lt
/-- A polynomial lifts if and only if it can be lifted to a polynomial of the same degree. -/
theorem mem_lifts_and_degree_eq {p : S[X]} (hlifts : p ∈ lifts f) :
    ∃ q : R[X], map f q = p ∧ q.degree = p.degree := by
  generalize hd : p.natDegree = d
  revert hd p
  induction' d using Nat.strong_induction_on with n hn
  intros p hlifts hdeg
  by_cases erase_zero : p.eraseLead = 0
  · rw [← eraseLead_add_monomial_natDegree_leadingCoeff p, erase_zero, zero_add, leadingCoeff]
    exact
      monomial_mem_lifts_and_degree_eq
        (monomial_mem_lifts p.natDegree ((lifts_iff_coeff_lifts p).1 hlifts p.natDegree))
  have deg_erase := Or.resolve_right (eraseLead_natDegree_lt_or_eraseLead_eq_zero p) erase_zero
  have pzero : p ≠ 0 := by
    intro habs
    exfalso
    rw [habs, eraseLead_zero, eq_self_iff_true, not_true] at erase_zero
    exact erase_zero
  have lead_zero : p.coeff p.natDegree ≠ 0 := by
    rw [← leadingCoeff, Ne.def, leadingCoeff_eq_zero]; exact pzero
  obtain ⟨lead, hlead⟩ :=
    monomial_mem_lifts_and_degree_eq
      (monomial_mem_lifts p.natDegree ((lifts_iff_coeff_lifts p).1 hlifts p.natDegree))
  have deg_lead : lead.degree = p.natDegree := by
    rw [hlead.2, ← C_mul_X_pow_eq_monomial, degree_C_mul_X_pow p.natDegree lead_zero]
  rw [hdeg] at deg_erase
  obtain ⟨erase, herase⟩ :=
    hn p.eraseLead.natDegree deg_erase (erase_mem_lifts p.natDegree hlifts)
      (refl p.eraseLead.natDegree)
  use erase + lead
  constructor
  · simp only [hlead, herase, Polynomial.map_add]
    rw [← eraseLead, ← leadingCoeff]
    rw [eraseLead_add_monomial_natDegree_leadingCoeff p]
  rw [degree_eq_natDegree pzero, ← deg_lead]
  apply degree_add_eq_right_of_degree_lt
  

Proof state:
case h.right.h
R : Type u
inst✝¹ : Semiring R
S : Type v
inst✝ : Semiring S
f : R →+* S
n : ℕ
hn : ∀ m < n, ∀ {p : S[X]}, p ∈ lifts f → natDegree p = m → ∃ q, map f q = p ∧ degree q = degree p
p : S[X]
hlifts : p ∈ lifts f
hdeg : natDegree p = n
erase_zero : ¬eraseLead p = 0
deg_erase : natDegree (eraseLead p) < n
pzero : p ≠ 0
lead_zero : coeff p (natDegree p) ≠ 0
lead : R[X]
hlead :
  map f lead = (monomial (natDegree p)) (coeff p (natDegree p)) ∧
    degree lead = degree ((monomial (natDegree p)) (coeff p (natDegree p)))
deg_lead : degree lead = ↑(natDegree p)
erase : R[X]
herase : map f erase = Polynomial.erase (natDegree p) p ∧ degree erase = degree (Polynomial.erase (natDegree p) p)
⊢ degree erase < degree lead

Next tactic:
rw [herase.2, deg_lead, ← degree_eq_natDegree pzero]
/-- A polynomial lifts if and only if it can be lifted to a polynomial of the same degree. -/
theorem mem_lifts_and_degree_eq {p : S[X]} (hlifts : p ∈ lifts f) :
    ∃ q : R[X], map f q = p ∧ q.degree = p.degree := by
  generalize hd : p.natDegree = d
  revert hd p
  induction' d using Nat.strong_induction_on with n hn
  intros p hlifts hdeg
  by_cases erase_zero : p.eraseLead = 0
  · rw [← eraseLead_add_monomial_natDegree_leadingCoeff p, erase_zero, zero_add, leadingCoeff]
    exact
      monomial_mem_lifts_and_degree_eq
        (monomial_mem_lifts p.natDegree ((lifts_iff_coeff_lifts p).1 hlifts p.natDegree))
  have deg_erase := Or.resolve_right (eraseLead_natDegree_lt_or_eraseLead_eq_zero p) erase_zero
  have pzero : p ≠ 0 := by
    intro habs
    exfalso
    rw [habs, eraseLead_zero, eq_self_iff_true, not_true] at erase_zero
    exact erase_zero
  have lead_zero : p.coeff p.natDegree ≠ 0 := by
    rw [← leadingCoeff, Ne.def, leadingCoeff_eq_zero]; exact pzero
  obtain ⟨lead, hlead⟩ :=
    monomial_mem_lifts_and_degree_eq
      (monomial_mem_lifts p.natDegree ((lifts_iff_coeff_lifts p).1 hlifts p.natDegree))
  have deg_lead : lead.degree = p.natDegree := by
    rw [hlead.2, ← C_mul_X_pow_eq_monomial, degree_C_mul_X_pow p.natDegree lead_zero]
  rw [hdeg] at deg_erase
  obtain ⟨erase, herase⟩ :=
    hn p.eraseLead.natDegree deg_erase (erase_mem_lifts p.natDegree hlifts)
      (refl p.eraseLead.natDegree)
  use erase + lead
  constructor
  · simp only [hlead, herase, Polynomial.map_add]
    rw [← eraseLead, ← leadingCoeff]
    rw [eraseLead_add_monomial_natDegree_leadingCoeff p]
  rw [degree_eq_natDegree pzero, ← deg_lead]
  apply degree_add_eq_right_of_degree_lt
  rw [herase.2, deg_lead, ← degree_eq_natDegree pzero]
  

Proof state:
case h.right.h
R : Type u
inst✝¹ : Semiring R
S : Type v
inst✝ : Semiring S
f : R →+* S
n : ℕ
hn : ∀ m < n, ∀ {p : S[X]}, p ∈ lifts f → natDegree p = m → ∃ q, map f q = p ∧ degree q = degree p
p : S[X]
hlifts : p ∈ lifts f
hdeg : natDegree p = n
erase_zero : ¬eraseLead p = 0
deg_erase : natDegree (eraseLead p) < n
pzero : p ≠ 0
lead_zero : coeff p (natDegree p) ≠ 0
lead : R[X]
hlead :
  map f lead = (monomial (natDegree p)) (coeff p (natDegree p)) ∧
    degree lead = degree ((monomial (natDegree p)) (coeff p (natDegree p)))
deg_lead : degree lead = ↑(natDegree p)
erase : R[X]
herase : map f erase = Polynomial.erase (natDegree p) p ∧ degree erase = degree (Polynomial.erase (natDegree p) p)
⊢ degree (Polynomial.erase (natDegree p) p) < degree p

Next tactic:
exact degree_erase_lt pzero
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  

Proof state:
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
⊢ ∃ q, map f q = p ∧ degree q = degree p ∧ Monic q

Next tactic:
cases' subsingleton_or_nontrivial R with hR hR
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · 

Proof state:
case inl
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Subsingleton R
⊢ ∃ q, map f q = p ∧ degree q = degree p ∧ Monic q

Next tactic:
obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    

Proof state:
case inl.intro
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Subsingleton R
q : R[X]
hq : map f q = p ∧ degree q = degree p
⊢ ∃ q, map f q = p ∧ degree q = degree p ∧ Monic q

Next tactic:
exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  

Proof state:
case inr
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
⊢ ∃ q, map f q = p ∧ degree q = degree p ∧ Monic q

Next tactic:
have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    

Proof state:
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
⊢ erase (natDegree p) p + X ^ natDegree p = p

Next tactic:
simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  

Proof state:
case inr
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
⊢ ∃ q, map f q = p ∧ degree q = degree p ∧ Monic q

Next tactic:
by_cases h0 : erase p.natDegree p = 0
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  by_cases h0 : erase p.natDegree p = 0
  · 

Proof state:
case pos
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
h0 : erase (natDegree p) p = 0
⊢ ∃ q, map f q = p ∧ degree q = degree p ∧ Monic q

Next tactic:
rw [← H, h0, zero_add]
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  by_cases h0 : erase p.natDegree p = 0
  · rw [← H, h0, zero_add]
    

Proof state:
case pos
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
h0 : erase (natDegree p) p = 0
⊢ ∃ q, map f q = X ^ natDegree p ∧ degree q = degree (X ^ natDegree p) ∧ Monic q

Next tactic:
refine' ⟨X ^ p.natDegree, _, _, monic_X_pow p.natDegree⟩
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  by_cases h0 : erase p.natDegree p = 0
  · rw [← H, h0, zero_add]
    refine' ⟨X ^ p.natDegree, _, _, monic_X_pow p.natDegree⟩
    · 

Proof state:
case pos.refine'_1
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
h0 : erase (natDegree p) p = 0
⊢ map f (X ^ natDegree p) = X ^ natDegree p

Next tactic:
rw [Polynomial.map_pow, map_X]
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  by_cases h0 : erase p.natDegree p = 0
  · rw [← H, h0, zero_add]
    refine' ⟨X ^ p.natDegree, _, _, monic_X_pow p.natDegree⟩
    · rw [Polynomial.map_pow, map_X]
    · 

Proof state:
case pos.refine'_2
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
h0 : erase (natDegree p) p = 0
⊢ degree (X ^ natDegree p) = degree (X ^ natDegree p)

Next tactic:
rw [degree_X_pow, degree_X_pow]
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  by_cases h0 : erase p.natDegree p = 0
  · rw [← H, h0, zero_add]
    refine' ⟨X ^ p.natDegree, _, _, monic_X_pow p.natDegree⟩
    · rw [Polynomial.map_pow, map_X]
    · rw [degree_X_pow, degree_X_pow]
  

Proof state:
case neg
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
h0 : ¬erase (natDegree p) p = 0
⊢ ∃ q, map f q = p ∧ degree q = degree p ∧ Monic q

Next tactic:
obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq (erase_mem_lifts p.natDegree hlifts)
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  by_cases h0 : erase p.natDegree p = 0
  · rw [← H, h0, zero_add]
    refine' ⟨X ^ p.natDegree, _, _, monic_X_pow p.natDegree⟩
    · rw [Polynomial.map_pow, map_X]
    · rw [degree_X_pow, degree_X_pow]
  obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq (erase_mem_lifts p.natDegree hlifts)
  

Proof state:
case neg.intro
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
h0 : ¬erase (natDegree p) p = 0
q : R[X]
hq : map f q = erase (natDegree p) p ∧ degree q = degree (erase (natDegree p) p)
⊢ ∃ q, map f q = p ∧ degree q = degree p ∧ Monic q

Next tactic:
have p_neq_0 : p ≠ 0 := by intro hp; apply h0; rw [hp]; simp only [natDegree_zero, erase_zero]
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  by_cases h0 : erase p.natDegree p = 0
  · rw [← H, h0, zero_add]
    refine' ⟨X ^ p.natDegree, _, _, monic_X_pow p.natDegree⟩
    · rw [Polynomial.map_pow, map_X]
    · rw [degree_X_pow, degree_X_pow]
  obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq (erase_mem_lifts p.natDegree hlifts)
  have p_neq_0 : p ≠ 0 := by 

Proof state:
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
h0 : ¬erase (natDegree p) p = 0
q : R[X]
hq : map f q = erase (natDegree p) p ∧ degree q = degree (erase (natDegree p) p)
⊢ p ≠ 0

Next tactic:
intro hp
/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial
of the same degree. -/
theorem lifts_and_degree_eq_and_monic [Nontrivial S] {p : S[X]} (hlifts : p ∈ lifts f)
    (hp : p.Monic) : ∃ q : R[X], map f q = p ∧ q.degree = p.degree ∧ q.Monic := by
  cases' subsingleton_or_nontrivial R with hR hR
  · obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts
    exact ⟨q, hq.1, hq.2, monic_of_subsingleton _⟩
  have H : erase p.natDegree p + X ^ p.natDegree = p := by
    simpa only [hp.leadingCoeff, C_1, one_mul, eraseLead] using eraseLead_add_C_mul_X_pow p
  by_cases h0 : erase p.natDegree p = 0
  · rw [← H, h0, zero_add]
    refine' ⟨X ^ p.natDegree, _, _, monic_X_pow p.natDegree⟩
    · rw [Polynomial.map_pow, map_X]
    · rw [degree_X_pow, degree_X_pow]
  obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq (erase_mem_lifts p.natDegree hlifts)
  have p_neq_0 : p ≠ 0 := by intro hp; 

Proof state:
R : Type u
inst✝² : Semiring R
S : Type v
inst✝¹ : Semiring S
f : R →+* S
inst✝ : Nontrivial S
p : S[X]
hlifts : p ∈ lifts f
hp✝ : Monic p
hR : Nontrivial R
H : erase (natDegree p) p + X ^ natDegree p = p
h0 : ¬erase (natDegree p) p = 0
q : R[X]
hq : map f q = erase (natDegree p) p ∧ degree q = degree (erase (natDegree p) p)
hp : p = 0
⊢ False

Next tactic:
apply h0