l3lab/ntp-mathlib huggingface dataset:
/-- Used in the definition of `equivOfEquiv` -/
noncomputable def equivOfEquivAux (hSR : S ≃+* R) :
    { e : L ≃+* M // e.toRingHom.comp (algebraMap S L) = (algebraMap R M).comp hSR.toRingHom } := by
  letI : Algebra R S := RingHom.toAlgebra hSR.symm.toRingHom
  letI : Algebra S R := RingHom.toAlgebra hSR.toRingHom
  letI : IsDomain R := (NoZeroSMulDivisors.algebraMap_injective R M).isDomain _
  letI : IsDomain S := (NoZeroSMulDivisors.algebraMap_injective S L).isDomain _
  letI : Algebra R L := RingHom.toAlgebra ((algebraMap S L).comp (algebraMap R S))
  haveI : IsScalarTower R S L := IsScalarTower.of_algebraMap_eq fun _ => rfl
  haveI : IsScalarTower S R L :=
    IsScalarTower.of_algebraMap_eq (by simp [RingHom.algebraMap_toAlgebra])
  haveI : NoZeroSMulDivisors R S := NoZeroSMulDivisors.of_algebraMap_injective hSR.symm.injective
  refine
    ⟨equivOfAlgebraic' R S L M
        (IsAlgClosure.algebraic.tower_top_of_injective
          (show Function.Injective (algebraMap S R) from hSR.injective)), ?_⟩
  ext x
  simp only [RingEquiv.toRingHom_eq_coe, Function.comp_apply, RingHom.coe_comp,
    AlgEquiv.coe_ringEquiv, RingEquiv.coe_toRingHom]
  conv_lhs => 

Proof state:
k : Type u
inst✝¹⁴ : Field k
K : Type u_1
J : Type u_2
R : Type u
S : Type u_3
L : Type v
M : Type w
inst✝¹³ : Field K
inst✝¹² : Field J
inst✝¹¹ : CommRing R
inst✝¹⁰ : CommRing S
inst✝⁹ : Field L
inst✝⁸ : Field M
inst✝⁷ : Algebra R M
inst✝⁶ : NoZeroSMulDivisors R M
inst✝⁵ : IsAlgClosure R M
inst✝⁴ : Algebra K M
inst✝³ : IsAlgClosure K M
inst✝² : Algebra S L
inst✝¹ : NoZeroSMulDivisors S L
inst✝ : IsAlgClosure S L
hSR : S ≃+* R
this✝⁶ : Algebra R S := RingHom.toAlgebra (RingEquiv.toRingHom (RingEquiv.symm hSR))
this✝⁵ : Algebra S R := RingHom.toAlgebra (RingEquiv.toRingHom hSR)
this✝⁴ : IsDomain R := Function.Injective.isDomain (algebraMap R M) (NoZeroSMulDivisors.algebraMap_injective R M)
this✝³ : IsDomain S := Function.Injective.isDomain (algebraMap S L) (NoZeroSMulDivisors.algebraMap_injective S L)
this✝² : Algebra R L := RingHom.toAlgebra (RingHom.comp (algebraMap S L) (algebraMap R S))
this✝¹ : IsScalarTower R S L
this✝ : IsScalarTower S R L
this : NoZeroSMulDivisors R S
x : S
| (equivOfAlgebraic' R S L M (_ : Algebra.IsAlgebraic R L)) ((algebraMap S L) x)

Next tactic:
rw [← hSR.symm_apply_apply x]
/-- Used in the definition of `equivOfEquiv` -/
noncomputable def equivOfEquivAux (hSR : S ≃+* R) :
    { e : L ≃+* M // e.toRingHom.comp (algebraMap S L) = (algebraMap R M).comp hSR.toRingHom } := by
  letI : Algebra R S := RingHom.toAlgebra hSR.symm.toRingHom
  letI : Algebra S R := RingHom.toAlgebra hSR.toRingHom
  letI : IsDomain R := (NoZeroSMulDivisors.algebraMap_injective R M).isDomain _
  letI : IsDomain S := (NoZeroSMulDivisors.algebraMap_injective S L).isDomain _
  letI : Algebra R L := RingHom.toAlgebra ((algebraMap S L).comp (algebraMap R S))
  haveI : IsScalarTower R S L := IsScalarTower.of_algebraMap_eq fun _ => rfl
  haveI : IsScalarTower S R L :=
    IsScalarTower.of_algebraMap_eq (by simp [RingHom.algebraMap_toAlgebra])
  haveI : NoZeroSMulDivisors R S := NoZeroSMulDivisors.of_algebraMap_injective hSR.symm.injective
  refine
    ⟨equivOfAlgebraic' R S L M
        (IsAlgClosure.algebraic.tower_top_of_injective
          (show Function.Injective (algebraMap S R) from hSR.injective)), ?_⟩
  ext x
  simp only [RingEquiv.toRingHom_eq_coe, Function.comp_apply, RingHom.coe_comp,
    AlgEquiv.coe_ringEquiv, RingEquiv.coe_toRingHom]
  conv_lhs => rw [← hSR.symm_apply_apply x]
  

Proof state:
case a
k : Type u
inst✝¹⁴ : Field k
K : Type u_1
J : Type u_2
R : Type u
S : Type u_3
L : Type v
M : Type w
inst✝¹³ : Field K
inst✝¹² : Field J
inst✝¹¹ : CommRing R
inst✝¹⁰ : CommRing S
inst✝⁹ : Field L
inst✝⁸ : Field M
inst✝⁷ : Algebra R M
inst✝⁶ : NoZeroSMulDivisors R M
inst✝⁵ : IsAlgClosure R M
inst✝⁴ : Algebra K M
inst✝³ : IsAlgClosure K M
inst✝² : Algebra S L
inst✝¹ : NoZeroSMulDivisors S L
inst✝ : IsAlgClosure S L
hSR : S ≃+* R
this✝⁶ : Algebra R S := RingHom.toAlgebra (RingEquiv.toRingHom (RingEquiv.symm hSR))
this✝⁵ : Algebra S R := RingHom.toAlgebra (RingEquiv.toRingHom hSR)
this✝⁴ : IsDomain R := Function.Injective.isDomain (algebraMap R M) (NoZeroSMulDivisors.algebraMap_injective R M)
this✝³ : IsDomain S := Function.Injective.isDomain (algebraMap S L) (NoZeroSMulDivisors.algebraMap_injective S L)
this✝² : Algebra R L := RingHom.toAlgebra (RingHom.comp (algebraMap S L) (algebraMap R S))
this✝¹ : IsScalarTower R S L
this✝ : IsScalarTower S R L
this : NoZeroSMulDivisors R S
x : S
⊢ (equivOfAlgebraic' R S L M (_ : Algebra.IsAlgebraic R L)) ((algebraMap S L) ((RingEquiv.symm hSR) (hSR x))) =
    (algebraMap R M) (hSR x)

Next tactic:
show equivOfAlgebraic' R S L M _ (algebraMap R L (hSR x)) = _
/-- Used in the definition of `equivOfEquiv` -/
noncomputable def equivOfEquivAux (hSR : S ≃+* R) :
    { e : L ≃+* M // e.toRingHom.comp (algebraMap S L) = (algebraMap R M).comp hSR.toRingHom } := by
  letI : Algebra R S := RingHom.toAlgebra hSR.symm.toRingHom
  letI : Algebra S R := RingHom.toAlgebra hSR.toRingHom
  letI : IsDomain R := (NoZeroSMulDivisors.algebraMap_injective R M).isDomain _
  letI : IsDomain S := (NoZeroSMulDivisors.algebraMap_injective S L).isDomain _
  letI : Algebra R L := RingHom.toAlgebra ((algebraMap S L).comp (algebraMap R S))
  haveI : IsScalarTower R S L := IsScalarTower.of_algebraMap_eq fun _ => rfl
  haveI : IsScalarTower S R L :=
    IsScalarTower.of_algebraMap_eq (by simp [RingHom.algebraMap_toAlgebra])
  haveI : NoZeroSMulDivisors R S := NoZeroSMulDivisors.of_algebraMap_injective hSR.symm.injective
  refine
    ⟨equivOfAlgebraic' R S L M
        (IsAlgClosure.algebraic.tower_top_of_injective
          (show Function.Injective (algebraMap S R) from hSR.injective)), ?_⟩
  ext x
  simp only [RingEquiv.toRingHom_eq_coe, Function.comp_apply, RingHom.coe_comp,
    AlgEquiv.coe_ringEquiv, RingEquiv.coe_toRingHom]
  conv_lhs => rw [← hSR.symm_apply_apply x]
  show equivOfAlgebraic' R S L M _ (algebraMap R L (hSR x)) = _
  

Proof state:
case a
k : Type u
inst✝¹⁴ : Field k
K : Type u_1
J : Type u_2
R : Type u
S : Type u_3
L : Type v
M : Type w
inst✝¹³ : Field K
inst✝¹² : Field J
inst✝¹¹ : CommRing R
inst✝¹⁰ : CommRing S
inst✝⁹ : Field L
inst✝⁸ : Field M
inst✝⁷ : Algebra R M
inst✝⁶ : NoZeroSMulDivisors R M
inst✝⁵ : IsAlgClosure R M
inst✝⁴ : Algebra K M
inst✝³ : IsAlgClosure K M
inst✝² : Algebra S L
inst✝¹ : NoZeroSMulDivisors S L
inst✝ : IsAlgClosure S L
hSR : S ≃+* R
this✝⁶ : Algebra R S := RingHom.toAlgebra (RingEquiv.toRingHom (RingEquiv.symm hSR))
this✝⁵ : Algebra S R := RingHom.toAlgebra (RingEquiv.toRingHom hSR)
this✝⁴ : IsDomain R := Function.Injective.isDomain (algebraMap R M) (NoZeroSMulDivisors.algebraMap_injective R M)
this✝³ : IsDomain S := Function.Injective.isDomain (algebraMap S L) (NoZeroSMulDivisors.algebraMap_injective S L)
this✝² : Algebra R L := RingHom.toAlgebra (RingHom.comp (algebraMap S L) (algebraMap R S))
this✝¹ : IsScalarTower R S L
this✝ : IsScalarTower S R L
this : NoZeroSMulDivisors R S
x : S
⊢ (equivOfAlgebraic' R S L M (_ : Algebra.IsAlgebraic R L)) ((algebraMap R L) (hSR x)) = (algebraMap R M) (hSR x)

Next tactic:
rw [AlgEquiv.commutes]
@[simp]
theorem equivOfEquiv_symm_algebraMap (hSR : S ≃+* R) (r : R) :
    (equivOfEquiv L M hSR).symm (algebraMap R M r) = algebraMap S L (hSR.symm r) :=
  (equivOfEquiv L M hSR).injective (by 

Proof state:
k : Type u
inst✝¹⁴ : Field k
K : Type u_1
J : Type u_2
R : Type u
S : Type u_3
L : Type v
M : Type w
inst✝¹³ : Field K
inst✝¹² : Field J
inst✝¹¹ : CommRing R
inst✝¹⁰ : CommRing S
inst✝⁹ : Field L
inst✝⁸ : Field M
inst✝⁷ : Algebra R M
inst✝⁶ : NoZeroSMulDivisors R M
inst✝⁵ : IsAlgClosure R M
inst✝⁴ : Algebra K M
inst✝³ : IsAlgClosure K M
inst✝² : Algebra S L
inst✝¹ : NoZeroSMulDivisors S L
inst✝ : IsAlgClosure S L
hSR : S ≃+* R
r : R
⊢ (equivOfEquiv L M hSR) ((RingEquiv.symm (equivOfEquiv L M hSR)) ((algebraMap R M) r)) =
    (equivOfEquiv L M hSR) ((algebraMap S L) ((RingEquiv.symm hSR) r))

Next tactic:
simp
/-- All `F`-embeddings of a field `K` into another field `A` factor through any intermediate
field of `A/F` in which the minimal polynomial of elements of `K` splits. -/
@[simps]
def IntermediateField.algHomEquivAlgHomOfSplits (L : IntermediateField F A)
    (hL : ∀ x : K, (minpoly F x).Splits (algebraMap F L)) :
    (K →ₐ[F] L) ≃ (K →ₐ[F] A) where
  toFun := L.val.comp
  invFun f := f.codRestrict _ fun x ↦
    ((hK x).isIntegral.map f).mem_intermediateField_of_minpoly_splits <| by
      

Proof state:
k : Type u
inst✝⁵ : Field k
F : Type u_1
K : Type u_2
A : Type u_3
inst✝⁴ : Field F
inst✝³ : Field K
inst✝² : Field A
inst✝¹ : Algebra F K
inst✝ : Algebra F A
hK : Algebra.IsAlgebraic F K
L : IntermediateField F A
hL : ∀ (x : K), Splits (algebraMap F ↥L) (minpoly F x)
f : K →ₐ[F] A
x : K
⊢ Splits (algebraMap F ↥L) (minpoly F (f x))

Next tactic:
rw [minpoly.algHom_eq f f.injective]
/-- All `F`-embeddings of a field `K` into another field `A` factor through any intermediate
field of `A/F` in which the minimal polynomial of elements of `K` splits. -/
@[simps]
def IntermediateField.algHomEquivAlgHomOfSplits (L : IntermediateField F A)
    (hL : ∀ x : K, (minpoly F x).Splits (algebraMap F L)) :
    (K →ₐ[F] L) ≃ (K →ₐ[F] A) where
  toFun := L.val.comp
  invFun f := f.codRestrict _ fun x ↦
    ((hK x).isIntegral.map f).mem_intermediateField_of_minpoly_splits <| by
      rw [minpoly.algHom_eq f f.injective]; 

Proof state:
k : Type u
inst✝⁵ : Field k
F : Type u_1
K : Type u_2
A : Type u_3
inst✝⁴ : Field F
inst✝³ : Field K
inst✝² : Field A
inst✝¹ : Algebra F K
inst✝ : Algebra F A
hK : Algebra.IsAlgebraic F K
L : IntermediateField F A
hL : ∀ (x : K), Splits (algebraMap F ↥L) (minpoly F x)
f : K →ₐ[F] A
x : K
⊢ Splits (algebraMap F ↥L) (minpoly F x)

Next tactic:
exact hL x
/-- All `F`-embeddings of a field `K` into another field `A` factor through any intermediate
field of `A/F` in which the minimal polynomial of elements of `K` splits. -/
@[simps]
def IntermediateField.algHomEquivAlgHomOfSplits (L : IntermediateField F A)
    (hL : ∀ x : K, (minpoly F x).Splits (algebraMap F L)) :
    (K →ₐ[F] L) ≃ (K →ₐ[F] A) where
  toFun := L.val.comp
  invFun f := f.codRestrict _ fun x ↦
    ((hK x).isIntegral.map f).mem_intermediateField_of_minpoly_splits <| by
      rw [minpoly.algHom_eq f f.injective]; exact hL x
  left_inv _ := rfl
  right_inv _ := by 

Proof state:
k : Type u
inst✝⁵ : Field k
F : Type u_1
K : Type u_2
A : Type u_3
inst✝⁴ : Field F
inst✝³ : Field K
inst✝² : Field A
inst✝¹ : Algebra F K
inst✝ : Algebra F A
hK : Algebra.IsAlgebraic F K
L : IntermediateField F A
hL : ∀ (x : K), Splits (algebraMap F ↥L) (minpoly F x)
x✝ : K →ₐ[F] A
⊢ AlgHom.comp (val L) ((fun f => AlgHom.codRestrict f L.toSubalgebra (_ : ∀ (x : K), f x ∈ L)) x✝) = x✝

Next tactic:
rfl
theorem irreducible_factor (f : K[X]) : Irreducible (factor f) := by
  

Proof state:
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ Irreducible (factor f)

Next tactic:
rw [factor]
theorem irreducible_factor (f : K[X]) : Irreducible (factor f) := by
  rw [factor]
  

Proof state:
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ Irreducible (if H : ∃ g, Irreducible g ∧ g ∣ f then Classical.choose H else X)

Next tactic:
split_ifs with H
theorem irreducible_factor (f : K[X]) : Irreducible (factor f) := by
  rw [factor]
  split_ifs with H
  · 

Proof state:
case pos
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
H : ∃ g, Irreducible g ∧ g ∣ f
⊢ Irreducible (Classical.choose H)

Next tactic:
exact (Classical.choose_spec H).1
theorem irreducible_factor (f : K[X]) : Irreducible (factor f) := by
  rw [factor]
  split_ifs with H
  · exact (Classical.choose_spec H).1
  · 

Proof state:
case neg
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
H : ¬∃ g, Irreducible g ∧ g ∣ f
⊢ Irreducible X

Next tactic:
exact irreducible_X
theorem factor_dvd_of_not_isUnit {f : K[X]} (hf1 : ¬IsUnit f) : factor f ∣ f := by
  

Proof state:
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
⊢ factor f ∣ f

Next tactic:
by_cases hf2 : f = 0
theorem factor_dvd_of_not_isUnit {f : K[X]} (hf1 : ¬IsUnit f) : factor f ∣ f := by
  by_cases hf2 : f = 0; · 

Proof state:
case pos
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
hf2 : f = 0
⊢ factor f ∣ f

Next tactic:
rw [hf2]
theorem factor_dvd_of_not_isUnit {f : K[X]} (hf1 : ¬IsUnit f) : factor f ∣ f := by
  by_cases hf2 : f = 0; · rw [hf2]; 

Proof state:
case pos
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
hf2 : f = 0
⊢ factor 0 ∣ 0

Next tactic:
exact dvd_zero _
theorem factor_dvd_of_not_isUnit {f : K[X]} (hf1 : ¬IsUnit f) : factor f ∣ f := by
  by_cases hf2 : f = 0; · rw [hf2]; exact dvd_zero _
  

Proof state:
case neg
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
hf2 : ¬f = 0
⊢ factor f ∣ f

Next tactic:
rw [factor, dif_pos (WfDvdMonoid.exists_irreducible_factor hf1 hf2)]
theorem factor_dvd_of_not_isUnit {f : K[X]} (hf1 : ¬IsUnit f) : factor f ∣ f := by
  by_cases hf2 : f = 0; · rw [hf2]; exact dvd_zero _
  rw [factor, dif_pos (WfDvdMonoid.exists_irreducible_factor hf1 hf2)]
  

Proof state:
case neg
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf1 : ¬IsUnit f
hf2 : ¬f = 0
⊢ Classical.choose (_ : ∃ i, Irreducible i ∧ i ∣ f) ∣ f

Next tactic:
exact (Classical.choose_spec <| WfDvdMonoid.exists_irreducible_factor hf1 hf2).2
theorem X_sub_C_mul_removeFactor (f : K[X]) (hf : f.natDegree ≠ 0) :
    (X - C (AdjoinRoot.root f.factor)) * f.removeFactor = map (AdjoinRoot.of f.factor) f := by
  

Proof state:
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf : natDegree f ≠ 0
⊢ (X - C (AdjoinRoot.root (factor f))) * removeFactor f = map (AdjoinRoot.of (factor f)) f

Next tactic:
let ⟨g, hg⟩ := factor_dvd_of_natDegree_ne_zero hf
theorem X_sub_C_mul_removeFactor (f : K[X]) (hf : f.natDegree ≠ 0) :
    (X - C (AdjoinRoot.root f.factor)) * f.removeFactor = map (AdjoinRoot.of f.factor) f := by
  let ⟨g, hg⟩ := factor_dvd_of_natDegree_ne_zero hf
  

Proof state:
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf : natDegree f ≠ 0
g : K[X]
hg : f = factor f * g
⊢ (X - C (AdjoinRoot.root (factor f))) * removeFactor f = map (AdjoinRoot.of (factor f)) f

Next tactic:
apply (mul_divByMonic_eq_iff_isRoot
    (R := AdjoinRoot f.factor) (a := AdjoinRoot.root f.factor)).mpr
theorem X_sub_C_mul_removeFactor (f : K[X]) (hf : f.natDegree ≠ 0) :
    (X - C (AdjoinRoot.root f.factor)) * f.removeFactor = map (AdjoinRoot.of f.factor) f := by
  let ⟨g, hg⟩ := factor_dvd_of_natDegree_ne_zero hf
  apply (mul_divByMonic_eq_iff_isRoot
    (R := AdjoinRoot f.factor) (a := AdjoinRoot.root f.factor)).mpr
  

Proof state:
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
hf : natDegree f ≠ 0
g : K[X]
hg : f = factor f * g
⊢ IsRoot (map (AdjoinRoot.of (factor f)) f) (AdjoinRoot.root (factor f))

Next tactic:
rw [IsRoot.def, eval_map, hg, eval₂_mul, ← hg, AdjoinRoot.eval₂_root, zero_mul]
theorem natDegree_removeFactor (f : K[X]) : f.removeFactor.natDegree = f.natDegree - 1 := by
  -- Porting note: `(map (AdjoinRoot.of f.factor) f)` was `_`
  

Proof state:
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
⊢ natDegree (removeFactor f) = natDegree f - 1

Next tactic:
rw [removeFactor, natDegree_divByMonic (map (AdjoinRoot.of f.factor) f) (monic_X_sub_C _),
    natDegree_map, natDegree_X_sub_C]
theorem natDegree_removeFactor' {f : K[X]} {n : ℕ} (hfn : f.natDegree = n + 1) :
    f.removeFactor.natDegree = n := by 

Proof state:
F : Type u
K : Type v
L : Type w
inst✝² : Field K
inst✝¹ : Field L
inst✝ : Field F
f : K[X]
n : ℕ
hfn : natDegree f = n + 1
⊢ natDegree (removeFactor f) = n

Next tactic:
rw [natDegree_removeFactor, hfn, n.add_sub_cancel]
protected theorem splits (n : ℕ) :
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n), Splits (algebraMap K <| SplittingFieldAux n f) f :=
  Nat.recOn (motive := fun n => ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n), Splits (algebraMap K <| SplittingFieldAux n f) f) n
    (fun {K} _ _ hf =>
      splits_of_degree_le_one _
        (le_trans degree_le_natDegree <| hf.symm ▸ WithBot.coe_le_coe.2 zero_le_one))
    fun n ih {K} _ f hf => by
    

Proof state:
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]), natDegree f = n → Splits (algebraMap K (SplittingFieldAux n f)) f)
    n
K : Type u
x✝ : Field K
f : K[X]
hf : natDegree f = Nat.succ n
⊢ Splits (algebraMap K (SplittingFieldAux (Nat.succ n) f)) f

Next tactic:
rw [← splits_id_iff_splits, algebraMap_succ, ← map_map, splits_id_iff_splits,
      ← X_sub_C_mul_removeFactor f fun h => by rw [h] at hf; cases hf]
protected theorem splits (n : ℕ) :
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n), Splits (algebraMap K <| SplittingFieldAux n f) f :=
  Nat.recOn (motive := fun n => ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n), Splits (algebraMap K <| SplittingFieldAux n f) f) n
    (fun {K} _ _ hf =>
      splits_of_degree_le_one _
        (le_trans degree_le_natDegree <| hf.symm ▸ WithBot.coe_le_coe.2 zero_le_one))
    fun n ih {K} _ f hf => by
    rw [← splits_id_iff_splits, algebraMap_succ, ← map_map, splits_id_iff_splits,
      ← X_sub_C_mul_removeFactor f fun h => by 

Proof state:
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]), natDegree f = n → Splits (algebraMap K (SplittingFieldAux n f)) f)
    n
K : Type u
x✝ : Field K
f : K[X]
hf : natDegree f = Nat.succ n
h : natDegree f = 0
⊢ False

Next tactic:
rw [h] at hf
protected theorem splits (n : ℕ) :
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n), Splits (algebraMap K <| SplittingFieldAux n f) f :=
  Nat.recOn (motive := fun n => ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n), Splits (algebraMap K <| SplittingFieldAux n f) f) n
    (fun {K} _ _ hf =>
      splits_of_degree_le_one _
        (le_trans degree_le_natDegree <| hf.symm ▸ WithBot.coe_le_coe.2 zero_le_one))
    fun n ih {K} _ f hf => by
    rw [← splits_id_iff_splits, algebraMap_succ, ← map_map, splits_id_iff_splits,
      ← X_sub_C_mul_removeFactor f fun h => by rw [h] at hf; 

Proof state:
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]), natDegree f = n → Splits (algebraMap K (SplittingFieldAux n f)) f)
    n
K : Type u
x✝ : Field K
f : K[X]
hf : 0 = Nat.succ n
h : natDegree f = 0
⊢ False

Next tactic:
cases hf
protected theorem splits (n : ℕ) :
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n), Splits (algebraMap K <| SplittingFieldAux n f) f :=
  Nat.recOn (motive := fun n => ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n), Splits (algebraMap K <| SplittingFieldAux n f) f) n
    (fun {K} _ _ hf =>
      splits_of_degree_le_one _
        (le_trans degree_le_natDegree <| hf.symm ▸ WithBot.coe_le_coe.2 zero_le_one))
    fun n ih {K} _ f hf => by
    rw [← splits_id_iff_splits, algebraMap_succ, ← map_map, splits_id_iff_splits,
      ← X_sub_C_mul_removeFactor f fun h => by rw [h] at hf; cases hf]
    

Proof state:
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]), natDegree f = n → Splits (algebraMap K (SplittingFieldAux n f)) f)
    n
K : Type u
x✝ : Field K
f : K[X]
hf : natDegree f = Nat.succ n
⊢ Splits (algebraMap (AdjoinRoot (factor f)) (SplittingFieldAux n (removeFactor f)))
    ((X - C (AdjoinRoot.root (factor f))) * removeFactor f)

Next tactic:
exact splits_mul _ (splits_X_sub_C _) (ih _ (natDegree_removeFactor' hf))
theorem adjoin_rootSet (n : ℕ) :
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n),
        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤ :=
  Nat.recOn (motive := fun n =>
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n),
        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤)
    n (fun {K} _ f _hf => Algebra.eq_top_iff.2 fun x => Subalgebra.range_le _ ⟨x, rfl⟩)
    fun n ih {K} _ f hfn => by
    

Proof state:
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n → Algebra.adjoin K (rootSet f (SplittingFieldAux n f)) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
⊢ Algebra.adjoin K (rootSet f (SplittingFieldAux (Nat.succ n) f)) = ⊤

Next tactic:
have hndf : f.natDegree ≠ 0 := by intro h; rw [h] at hfn; cases hfn
theorem adjoin_rootSet (n : ℕ) :
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n),
        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤ :=
  Nat.recOn (motive := fun n =>
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n),
        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤)
    n (fun {K} _ f _hf => Algebra.eq_top_iff.2 fun x => Subalgebra.range_le _ ⟨x, rfl⟩)
    fun n ih {K} _ f hfn => by
    have hndf : f.natDegree ≠ 0 := by 

Proof state:
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n → Algebra.adjoin K (rootSet f (SplittingFieldAux n f)) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
⊢ natDegree f ≠ 0

Next tactic:
intro h
theorem adjoin_rootSet (n : ℕ) :
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n),
        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤ :=
  Nat.recOn (motive := fun n =>
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n),
        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤)
    n (fun {K} _ f _hf => Algebra.eq_top_iff.2 fun x => Subalgebra.range_le _ ⟨x, rfl⟩)
    fun n ih {K} _ f hfn => by
    have hndf : f.natDegree ≠ 0 := by intro h; 

Proof state:
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n → Algebra.adjoin K (rootSet f (SplittingFieldAux n f)) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : natDegree f = Nat.succ n
h : natDegree f = 0
⊢ False

Next tactic:
rw [h] at hfn
theorem adjoin_rootSet (n : ℕ) :
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n),
        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤ :=
  Nat.recOn (motive := fun n =>
    ∀ {K : Type u} [Field K],
      ∀ (f : K[X]) (_hfn : f.natDegree = n),
        Algebra.adjoin K (f.rootSet (SplittingFieldAux n f)) = ⊤)
    n (fun {K} _ f _hf => Algebra.eq_top_iff.2 fun x => Subalgebra.range_le _ ⟨x, rfl⟩)
    fun n ih {K} _ f hfn => by
    have hndf : f.natDegree ≠ 0 := by intro h; rw [h] at hfn; 

Proof state:
F : Type u
K✝¹ : Type v
L : Type w
inst✝³ : Field K✝¹
inst✝² : Field L
inst✝¹ : Field F
n✝ : ℕ
K✝ : Type u
inst✝ : Field K✝
n : ℕ
ih :
  (fun n =>
      ∀ {K : Type u} [inst : Field K] (f : K[X]),
        natDegree f = n → Algebra.adjoin K (rootSet f (SplittingFieldAux n f)) = ⊤)
    n
K : Type u
x✝ : Field K
f : K[X]
hfn : 0 = Nat.succ n
h : natDegree f = 0
⊢ False

Next tactic:
cases hfn