l3lab/ntp-mathlib huggingface dataset:
theorem splits_mul {f g : K[X]} (hf : Splits i f) (hg : Splits i g) : Splits i (f * g) :=
  letI := Classical.decEq L
  if h : (f * g).map i = 0 then Or.inl h
  else
    Or.inr @fun p hp hpf =>
      ((PrincipalIdealRing.irreducible_iff_prime.1 hp).2.2 _ _
            (show p ∣ map i f * map i g by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g : K[X]
hf : Splits i f
hg : Splits i g
this : DecidableEq L := Classical.decEq L
h : ¬map i (f * g) = 0
p : L[X]
hp : Irreducible p
hpf : p ∣ map i (f * g)
⊢ p ∣ map i f * map i g

Next tactic:
convert hpf
theorem splits_mul {f g : K[X]} (hf : Splits i f) (hg : Splits i g) : Splits i (f * g) :=
  letI := Classical.decEq L
  if h : (f * g).map i = 0 then Or.inl h
  else
    Or.inr @fun p hp hpf =>
      ((PrincipalIdealRing.irreducible_iff_prime.1 hp).2.2 _ _
            (show p ∣ map i f * map i g by convert hpf; 

Proof state:
case h.e'_4
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g : K[X]
hf : Splits i f
hg : Splits i g
this : DecidableEq L := Classical.decEq L
h : ¬map i (f * g) = 0
p : L[X]
hp : Irreducible p
hpf : p ∣ map i (f * g)
⊢ map i f * map i g = map i (f * g)

Next tactic:
rw [Polynomial.map_mul]
theorem splits_mul {f g : K[X]} (hf : Splits i f) (hg : Splits i g) : Splits i (f * g) :=
  letI := Classical.decEq L
  if h : (f * g).map i = 0 then Or.inl h
  else
    Or.inr @fun p hp hpf =>
      ((PrincipalIdealRing.irreducible_iff_prime.1 hp).2.2 _ _
            (show p ∣ map i f * map i g by convert hpf; rw [Polynomial.map_mul])).elim
        (hf.resolve_left (fun hf => by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g : K[X]
hf✝ : Splits i f
hg : Splits i g
this : DecidableEq L := Classical.decEq L
h : ¬map i (f * g) = 0
p : L[X]
hp : Irreducible p
hpf : p ∣ map i (f * g)
hf : map i f = 0
⊢ False

Next tactic:
simp [hf] at h
theorem splits_mul {f g : K[X]} (hf : Splits i f) (hg : Splits i g) : Splits i (f * g) :=
  letI := Classical.decEq L
  if h : (f * g).map i = 0 then Or.inl h
  else
    Or.inr @fun p hp hpf =>
      ((PrincipalIdealRing.irreducible_iff_prime.1 hp).2.2 _ _
            (show p ∣ map i f * map i g by convert hpf; rw [Polynomial.map_mul])).elim
        (hf.resolve_left (fun hf => by simp [hf] at h) hp)
        (hg.resolve_left (fun hg => by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g : K[X]
hf : Splits i f
hg✝ : Splits i g
this : DecidableEq L := Classical.decEq L
h : ¬map i (f * g) = 0
p : L[X]
hp : Irreducible p
hpf : p ∣ map i (f * g)
hg : map i g = 0
⊢ False

Next tactic:
simp [hg] at h
theorem splits_of_splits_mul' {f g : K[X]} (hfg : (f * g).map i ≠ 0) (h : Splits i (f * g)) :
    Splits i f ∧ Splits i g :=
  ⟨Or.inr @fun g hgi hg =>
      Or.resolve_left h hfg hgi (by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g✝ : K[X]
hfg : map i (f * g✝) ≠ 0
h : Splits i (f * g✝)
g : L[X]
hgi : Irreducible g
hg : g ∣ map i f
⊢ g ∣ map i (f * g✝)

Next tactic:
rw [Polynomial.map_mul]
theorem splits_of_splits_mul' {f g : K[X]} (hfg : (f * g).map i ≠ 0) (h : Splits i (f * g)) :
    Splits i f ∧ Splits i g :=
  ⟨Or.inr @fun g hgi hg =>
      Or.resolve_left h hfg hgi (by rw [Polynomial.map_mul]; 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g✝ : K[X]
hfg : map i (f * g✝) ≠ 0
h : Splits i (f * g✝)
g : L[X]
hgi : Irreducible g
hg : g ∣ map i f
⊢ g ∣ map i f * map i g✝

Next tactic:
exact hg.trans (dvd_mul_right _ _)
theorem splits_of_splits_mul' {f g : K[X]} (hfg : (f * g).map i ≠ 0) (h : Splits i (f * g)) :
    Splits i f ∧ Splits i g :=
  ⟨Or.inr @fun g hgi hg =>
      Or.resolve_left h hfg hgi (by rw [Polynomial.map_mul]; exact hg.trans (dvd_mul_right _ _)),
    Or.inr @fun g hgi hg =>
      Or.resolve_left h hfg hgi (by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g✝ : K[X]
hfg : map i (f * g✝) ≠ 0
h : Splits i (f * g✝)
g : L[X]
hgi : Irreducible g
hg : g ∣ map i g✝
⊢ g ∣ map i (f * g✝)

Next tactic:
rw [Polynomial.map_mul]
theorem splits_of_splits_mul' {f g : K[X]} (hfg : (f * g).map i ≠ 0) (h : Splits i (f * g)) :
    Splits i f ∧ Splits i g :=
  ⟨Or.inr @fun g hgi hg =>
      Or.resolve_left h hfg hgi (by rw [Polynomial.map_mul]; exact hg.trans (dvd_mul_right _ _)),
    Or.inr @fun g hgi hg =>
      Or.resolve_left h hfg hgi (by rw [Polynomial.map_mul]; 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f g✝ : K[X]
hfg : map i (f * g✝) ≠ 0
h : Splits i (f * g✝)
g : L[X]
hgi : Irreducible g
hg : g ∣ map i g✝
⊢ g ∣ map i f * map i g✝

Next tactic:
exact hg.trans (dvd_mul_left _ _)
theorem splits_map_iff (j : L →+* F) {f : K[X]} : Splits j (f.map i) ↔ Splits (j.comp i) f := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
j : L →+* F
f : K[X]
⊢ Splits j (map i f) ↔ Splits (RingHom.comp j i) f

Next tactic:
simp [Splits, Polynomial.map_map]
theorem splits_prod {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, (s j).Splits i) → (∏ x in t, s x).Splits i := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t : Finset ι
⊢ (∀ j ∈ t, Splits i (s j)) → Splits i (∏ x in t, s x)

Next tactic:
classical
  refine' Finset.induction_on t (fun _ => splits_one i) fun a t hat ih ht => _
  rw [Finset.forall_mem_insert] at ht; rw [Finset.prod_insert hat]
  exact splits_mul i ht.1 (ih ht.2)
theorem splits_prod {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, (s j).Splits i) → (∏ x in t, s x).Splits i := by
  classical
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t : Finset ι
⊢ (∀ j ∈ t, Splits i (s j)) → Splits i (∏ x in t, s x)

Next tactic:
refine' Finset.induction_on t (fun _ => splits_one i) fun a t hat ih ht => _
theorem splits_prod {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, (s j).Splits i) → (∏ x in t, s x).Splits i := by
  classical
  refine' Finset.induction_on t (fun _ => splits_one i) fun a t hat ih ht => _
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t✝ : Finset ι
a : ι
t : Finset ι
hat : a ∉ t
ih : (∀ j ∈ t, Splits i (s j)) → Splits i (∏ x in t, s x)
ht : ∀ j ∈ insert a t, Splits i (s j)
⊢ Splits i (∏ x in insert a t, s x)

Next tactic:
rw [Finset.forall_mem_insert] at ht
theorem splits_prod {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, (s j).Splits i) → (∏ x in t, s x).Splits i := by
  classical
  refine' Finset.induction_on t (fun _ => splits_one i) fun a t hat ih ht => _
  rw [Finset.forall_mem_insert] at ht; 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t✝ : Finset ι
a : ι
t : Finset ι
hat : a ∉ t
ih : (∀ j ∈ t, Splits i (s j)) → Splits i (∏ x in t, s x)
ht : Splits i (s a) ∧ ∀ x ∈ t, Splits i (s x)
⊢ Splits i (∏ x in insert a t, s x)

Next tactic:
rw [Finset.prod_insert hat]
theorem splits_prod {ι : Type u} {s : ι → K[X]} {t : Finset ι} :
    (∀ j ∈ t, (s j).Splits i) → (∏ x in t, s x).Splits i := by
  classical
  refine' Finset.induction_on t (fun _ => splits_one i) fun a t hat ih ht => _
  rw [Finset.forall_mem_insert] at ht; rw [Finset.prod_insert hat]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
ι : Type u
s : ι → K[X]
t✝ : Finset ι
a : ι
t : Finset ι
hat : a ∉ t
ih : (∀ j ∈ t, Splits i (s j)) → Splits i (∏ x in t, s x)
ht : Splits i (s a) ∧ ∀ x ∈ t, Splits i (s x)
⊢ Splits i (s a * ∏ x in t, s x)

Next tactic:
exact splits_mul i ht.1 (ih ht.2)
theorem splits_pow {f : K[X]} (hf : f.Splits i) (n : ℕ) : (f ^ n).Splits i := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hf : Splits i f
n : ℕ
⊢ Splits i (f ^ n)

Next tactic:
rw [← Finset.card_range n, ← Finset.prod_const]
theorem splits_pow {f : K[X]} (hf : f.Splits i) (n : ℕ) : (f ^ n).Splits i := by
  rw [← Finset.card_range n, ← Finset.prod_const]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hf : Splits i f
n : ℕ
⊢ Splits i (∏ _x in Finset.range n, f)

Next tactic:
exact splits_prod i fun j _ => hf
theorem splits_id_iff_splits {f : K[X]} : (f.map i).Splits (RingHom.id L) ↔ f.Splits i := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
⊢ Splits (RingHom.id L) (map i f) ↔ Splits i f

Next tactic:
rw [splits_map_iff, RingHom.id_comp]
theorem exists_root_of_splits' {f : K[X]} (hs : Splits i f) (hf0 : degree (f.map i) ≠ 0) :
    ∃ x, eval₂ i x f = 0 :=
  letI := Classical.decEq L
  if hf0' : f.map i = 0 then by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hs : Splits i f
hf0 : degree (map i f) ≠ 0
this : DecidableEq L := Classical.decEq L
hf0' : map i f = 0
⊢ ∃ x, eval₂ i x f = 0

Next tactic:
simp [eval₂_eq_eval_map, hf0']
theorem exists_root_of_splits' {f : K[X]} (hs : Splits i f) (hf0 : degree (f.map i) ≠ 0) :
    ∃ x, eval₂ i x f = 0 :=
  letI := Classical.decEq L
  if hf0' : f.map i = 0 then by simp [eval₂_eq_eval_map, hf0']
  else
    let ⟨g, hg⟩ :=
      WfDvdMonoid.exists_irreducible_factor
        (show ¬IsUnit (f.map i) from mt isUnit_iff_degree_eq_zero.1 hf0) hf0'
    let ⟨x, hx⟩ := exists_root_of_degree_eq_one (hs.resolve_left hf0' hg.1 hg.2)
    let ⟨i, hi⟩ := hg.2
    ⟨x, by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
f : K[X]
hs : Splits i✝ f
hf0 : degree (map i✝ f) ≠ 0
this : DecidableEq L := Classical.decEq L
hf0' : ¬map i✝ f = 0
g : L[X]
hg : Irreducible g ∧ g ∣ map i✝ f
x : L
hx : IsRoot g x
i : L[X]
hi : map i✝ f = g * i
⊢ eval₂ i✝ x f = 0

Next tactic:
rw [← eval_map, hi, eval_mul, show _ = _ from hx, zero_mul]
theorem roots_ne_zero_of_splits' {f : K[X]} (hs : Splits i f) (hf0 : natDegree (f.map i) ≠ 0) :
    (f.map i).roots ≠ 0 :=
  let ⟨x, hx⟩ := exists_root_of_splits' i hs fun h => hf0 <| natDegree_eq_of_degree_eq_some h
  fun h => by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hs : Splits i f
hf0 : natDegree (map i f) ≠ 0
x : L
hx : eval₂ i x f = 0
h : roots (map i f) = 0
⊢ False

Next tactic:
rw [← eval_map] at hx
theorem roots_ne_zero_of_splits' {f : K[X]} (hs : Splits i f) (hf0 : natDegree (f.map i) ≠ 0) :
    (f.map i).roots ≠ 0 :=
  let ⟨x, hx⟩ := exists_root_of_splits' i hs fun h => hf0 <| natDegree_eq_of_degree_eq_some h
  fun h => by
  rw [← eval_map] at hx
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hs : Splits i f
hf0 : natDegree (map i f) ≠ 0
x : L
hx : eval x (map i f) = 0
h : roots (map i f) = 0
⊢ False

Next tactic:
have : f.map i ≠ 0 := by intro; simp_all
theorem roots_ne_zero_of_splits' {f : K[X]} (hs : Splits i f) (hf0 : natDegree (f.map i) ≠ 0) :
    (f.map i).roots ≠ 0 :=
  let ⟨x, hx⟩ := exists_root_of_splits' i hs fun h => hf0 <| natDegree_eq_of_degree_eq_some h
  fun h => by
  rw [← eval_map] at hx
  have : f.map i ≠ 0 := by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hs : Splits i f
hf0 : natDegree (map i f) ≠ 0
x : L
hx : eval x (map i f) = 0
h : roots (map i f) = 0
⊢ map i f ≠ 0

Next tactic:
intro
theorem roots_ne_zero_of_splits' {f : K[X]} (hs : Splits i f) (hf0 : natDegree (f.map i) ≠ 0) :
    (f.map i).roots ≠ 0 :=
  let ⟨x, hx⟩ := exists_root_of_splits' i hs fun h => hf0 <| natDegree_eq_of_degree_eq_some h
  fun h => by
  rw [← eval_map] at hx
  have : f.map i ≠ 0 := by intro; 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hs : Splits i f
hf0 : natDegree (map i f) ≠ 0
x : L
hx : eval x (map i f) = 0
h : roots (map i f) = 0
a✝ : map i f = 0
⊢ False

Next tactic:
simp_all
theorem roots_ne_zero_of_splits' {f : K[X]} (hs : Splits i f) (hf0 : natDegree (f.map i) ≠ 0) :
    (f.map i).roots ≠ 0 :=
  let ⟨x, hx⟩ := exists_root_of_splits' i hs fun h => hf0 <| natDegree_eq_of_degree_eq_some h
  fun h => by
  rw [← eval_map] at hx
  have : f.map i ≠ 0 := by intro; simp_all
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i : K →+* L
f : K[X]
hs : Splits i f
hf0 : natDegree (map i f) ≠ 0
x : L
hx : eval x (map i f) = 0
h : roots (map i f) = 0
this : map i f ≠ 0
⊢ False

Next tactic:
cases h.subst ((mem_roots this).2 hx)
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
⊢ natDegree (map i p) = Multiset.card (roots (map i p))

Next tactic:
by_cases hp : p.map i = 0
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · 

Proof state:
case pos
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
hp : map i p = 0
⊢ natDegree (map i p) = Multiset.card (roots (map i p))

Next tactic:
rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  

Proof state:
case neg
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
hp : ¬map i p = 0
⊢ natDegree (map i p) = Multiset.card (roots (map i p))

Next tactic:
obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  

Proof state:
case neg.intro.intro.intro
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hsplit : Splits i p
hp : ¬map i p = 0
q : L[X]
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
⊢ natDegree (map i p) = Multiset.card (roots (map i p))

Next tactic:
rw [← splits_id_iff_splits, ← he] at hsplit
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  

Proof state:
case neg.intro.intro.intro
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
hp : ¬map i p = 0
q : L[X]
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
⊢ natDegree (map i p) = Multiset.card (roots (map i p))

Next tactic:
rw [← he] at hp
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  

Proof state:
case neg.intro.intro.intro
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
⊢ natDegree (map i p) = Multiset.card (roots (map i p))

Next tactic:
have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
h : q = 0
⊢ Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0

Next tactic:
rw [h, mul_zero]
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  

Proof state:
case neg.intro.intro.intro
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
⊢ natDegree (map i p) = Multiset.card (roots (map i p))

Next tactic:
rw [← hd, add_right_eq_self]
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  rw [← hd, add_right_eq_self]
  

Proof state:
case neg.intro.intro.intro
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
⊢ natDegree q = 0

Next tactic:
by_contra h
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  rw [← hd, add_right_eq_self]
  by_contra h
  

Proof state:
case neg.intro.intro.intro
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
h : ¬natDegree q = 0
⊢ False

Next tactic:
have h' : (map (RingHom.id L) q).natDegree ≠ 0 := by simp [h]
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  rw [← hd, add_right_eq_self]
  by_contra h
  have h' : (map (RingHom.id L) q).natDegree ≠ 0 := by 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
h : ¬natDegree q = 0
⊢ natDegree (map (RingHom.id L) q) ≠ 0

Next tactic:
simp [h]
theorem natDegree_eq_card_roots' {p : K[X]} {i : K →+* L} (hsplit : Splits i p) :
    (p.map i).natDegree = Multiset.card (p.map i).roots := by
  by_cases hp : p.map i = 0
  · rw [hp, natDegree_zero, roots_zero, Multiset.card_zero]
  obtain ⟨q, he, hd, hr⟩ := exists_prod_multiset_X_sub_C_mul (p.map i)
  rw [← splits_id_iff_splits, ← he] at hsplit
  rw [← he] at hp
  have hq : q ≠ 0 := fun h => hp (by rw [h, mul_zero])
  rw [← hd, add_right_eq_self]
  by_contra h
  have h' : (map (RingHom.id L) q).natDegree ≠ 0 := by simp [h]
  

Proof state:
case neg.intro.intro.intro
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝² : CommRing K
inst✝¹ : Field L
inst✝ : Field F
i✝ : K →+* L
p : K[X]
i : K →+* L
q : L[X]
hp : ¬Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = 0
hsplit : Splits (RingHom.id L) (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q)
he : Multiset.prod (Multiset.map (fun a => X - C a) (roots (map i p))) * q = map i p
hd : Multiset.card (roots (map i p)) + natDegree q = natDegree (map i p)
hr : roots q = 0
hq : q ≠ 0
h : ¬natDegree q = 0
h' : natDegree (map (RingHom.id L) q) ≠ 0
⊢ False

Next tactic:
have := roots_ne_zero_of_splits' (RingHom.id L) (splits_of_splits_mul' _ ?_ hsplit).2 h'