l3lab/ntp-mathlib huggingface dataset:
theorem finrank {n} (h : n ≠ 0) : FiniteDimensional.finrank (ZMod p) (GaloisField p n) = n := by
  set g_poly := (X ^ p ^ n - X : (ZMod p)[X])
  have hp : 1 < p := h_prime.out.one_lt
  have aux : g_poly ≠ 0 := FiniteField.X_pow_card_pow_sub_X_ne_zero _ h hp
  -- Porting note : in the statment of `key`, replaced `g_poly` by its value otherwise the
  -- proof fails
  have key : Fintype.card (g_poly.rootSet (GaloisField p n)) = g_poly.natDegree :=
    card_rootSet_eq_natDegree (galois_poly_separable p _ (dvd_pow (dvd_refl p) h))
      (SplittingField.splits (X ^ p ^ n - X : (ZMod p)[X]))
  have nat_degree_eq : g_poly.natDegree = p ^ n :=
    FiniteField.X_pow_card_pow_sub_X_natDegree_eq _ h hp
  rw [nat_degree_eq] at key
  suffices g_poly.rootSet (GaloisField p n) = Set.univ by
    simp_rw [this, ← Fintype.ofEquiv_card (Equiv.Set.univ _)] at key
    -- Porting note: prevents `card_eq_pow_finrank` from using a wrong instance for `Fintype`
    rw [@card_eq_pow_finrank (ZMod p) _ _ _ _ _ (_), ZMod.card] at key
    exact Nat.pow_right_injective (Nat.Prime.one_lt' p).out key
  rw [Set.eq_univ_iff_forall]
  suffices ∀ (x) (hx : x ∈ (⊤ : Subalgebra (ZMod p) (GaloisField p n))),
      x ∈ (X ^ p ^ n - X : (ZMod p)[X]).rootSet (GaloisField p n)
    by simpa
  rw [← SplittingField.adjoin_rootSet]
  simp_rw [Algebra.mem_adjoin_iff]
  intro x hx
  -- We discharge the `p = 0` separately, to avoid typeclass issues on `ZMod p`.
  cases p; cases hp
  refine Subring.closure_induction hx ?_ ?_ ?_ ?_ ?_ ?_ <;> simp_rw [mem_rootSet_of_ne aux]
  · rintro x (⟨r, rfl⟩ | hx)
    · simp only [map_sub, map_pow, aeval_X]
      rw [← map_pow, ZMod.pow_card_pow, sub_self]
    · dsimp only [GaloisField] at hx
      rwa [mem_rootSet_of_ne aux] at hx
  · rw [← coeff_zero_eq_aeval_zero']
    simp only [coeff_X_pow, coeff_X_zero, sub_zero, _root_.map_eq_zero, ite_eq_right_iff,
      one_ne_zero, coeff_sub]
    intro hn
    exact Nat.not_lt_zero 1 (pow_eq_zero hn.symm ▸ hp)
  · simp
  · simp only [aeval_X_pow, aeval_X, AlgHom.map_sub, add_pow_char_pow, sub_eq_zero]
    intro x y hx hy
    rw [hx, hy]
  · intro x hx
    simp only [sub_eq_zero, aeval_X_pow, aeval_X, AlgHom.map_sub, sub_neg_eq_add] at *
    rw [neg_pow, hx, CharP.neg_one_pow_char_pow]
    simp
  · 

Proof state:
case succ.refine_6
p : ℕ
inst✝ : Fact (Nat.Prime p)
n✝² n✝¹ n : ℕ
h : n ≠ 0
n✝ : ℕ
h_prime : Fact (Nat.Prime (Nat.succ n✝))
g_poly : (ZMod (Nat.succ n✝))[X] := X ^ Nat.succ n✝ ^ n - X
hp : 1 < Nat.succ n✝
aux : g_poly ≠ 0
key : Fintype.card ↑(rootSet g_poly (GaloisField (Nat.succ n✝) n)) = Nat.succ n✝ ^ n
nat_degree_eq : natDegree g_poly = Nat.succ n✝ ^ n
x : GaloisField (Nat.succ n✝) n
hx :
  x ∈
    Subring.closure
      (Set.range ⇑(algebraMap (ZMod (Nat.succ n✝)) (GaloisField (Nat.succ n✝) n)) ∪
        rootSet (X ^ Nat.succ n✝ ^ n - X) (SplittingField (X ^ Nat.succ n✝ ^ n - X)))
⊢ ∀ (x y : GaloisField (Nat.succ n✝) n),
    (aeval x) (X ^ Nat.succ n✝ ^ n - X) = 0 →
      (aeval y) (X ^ Nat.succ n✝ ^ n - X) = 0 → (aeval (x * y)) (X ^ Nat.succ n✝ ^ n - X) = 0

Next tactic:
simp only [aeval_X_pow, aeval_X, AlgHom.map_sub, mul_pow, sub_eq_zero]
theorem finrank {n} (h : n ≠ 0) : FiniteDimensional.finrank (ZMod p) (GaloisField p n) = n := by
  set g_poly := (X ^ p ^ n - X : (ZMod p)[X])
  have hp : 1 < p := h_prime.out.one_lt
  have aux : g_poly ≠ 0 := FiniteField.X_pow_card_pow_sub_X_ne_zero _ h hp
  -- Porting note : in the statment of `key`, replaced `g_poly` by its value otherwise the
  -- proof fails
  have key : Fintype.card (g_poly.rootSet (GaloisField p n)) = g_poly.natDegree :=
    card_rootSet_eq_natDegree (galois_poly_separable p _ (dvd_pow (dvd_refl p) h))
      (SplittingField.splits (X ^ p ^ n - X : (ZMod p)[X]))
  have nat_degree_eq : g_poly.natDegree = p ^ n :=
    FiniteField.X_pow_card_pow_sub_X_natDegree_eq _ h hp
  rw [nat_degree_eq] at key
  suffices g_poly.rootSet (GaloisField p n) = Set.univ by
    simp_rw [this, ← Fintype.ofEquiv_card (Equiv.Set.univ _)] at key
    -- Porting note: prevents `card_eq_pow_finrank` from using a wrong instance for `Fintype`
    rw [@card_eq_pow_finrank (ZMod p) _ _ _ _ _ (_), ZMod.card] at key
    exact Nat.pow_right_injective (Nat.Prime.one_lt' p).out key
  rw [Set.eq_univ_iff_forall]
  suffices ∀ (x) (hx : x ∈ (⊤ : Subalgebra (ZMod p) (GaloisField p n))),
      x ∈ (X ^ p ^ n - X : (ZMod p)[X]).rootSet (GaloisField p n)
    by simpa
  rw [← SplittingField.adjoin_rootSet]
  simp_rw [Algebra.mem_adjoin_iff]
  intro x hx
  -- We discharge the `p = 0` separately, to avoid typeclass issues on `ZMod p`.
  cases p; cases hp
  refine Subring.closure_induction hx ?_ ?_ ?_ ?_ ?_ ?_ <;> simp_rw [mem_rootSet_of_ne aux]
  · rintro x (⟨r, rfl⟩ | hx)
    · simp only [map_sub, map_pow, aeval_X]
      rw [← map_pow, ZMod.pow_card_pow, sub_self]
    · dsimp only [GaloisField] at hx
      rwa [mem_rootSet_of_ne aux] at hx
  · rw [← coeff_zero_eq_aeval_zero']
    simp only [coeff_X_pow, coeff_X_zero, sub_zero, _root_.map_eq_zero, ite_eq_right_iff,
      one_ne_zero, coeff_sub]
    intro hn
    exact Nat.not_lt_zero 1 (pow_eq_zero hn.symm ▸ hp)
  · simp
  · simp only [aeval_X_pow, aeval_X, AlgHom.map_sub, add_pow_char_pow, sub_eq_zero]
    intro x y hx hy
    rw [hx, hy]
  · intro x hx
    simp only [sub_eq_zero, aeval_X_pow, aeval_X, AlgHom.map_sub, sub_neg_eq_add] at *
    rw [neg_pow, hx, CharP.neg_one_pow_char_pow]
    simp
  · simp only [aeval_X_pow, aeval_X, AlgHom.map_sub, mul_pow, sub_eq_zero]
    

Proof state:
case succ.refine_6
p : ℕ
inst✝ : Fact (Nat.Prime p)
n✝² n✝¹ n : ℕ
h : n ≠ 0
n✝ : ℕ
h_prime : Fact (Nat.Prime (Nat.succ n✝))
g_poly : (ZMod (Nat.succ n✝))[X] := X ^ Nat.succ n✝ ^ n - X
hp : 1 < Nat.succ n✝
aux : g_poly ≠ 0
key : Fintype.card ↑(rootSet g_poly (GaloisField (Nat.succ n✝) n)) = Nat.succ n✝ ^ n
nat_degree_eq : natDegree g_poly = Nat.succ n✝ ^ n
x : GaloisField (Nat.succ n✝) n
hx :
  x ∈
    Subring.closure
      (Set.range ⇑(algebraMap (ZMod (Nat.succ n✝)) (GaloisField (Nat.succ n✝) n)) ∪
        rootSet (X ^ Nat.succ n✝ ^ n - X) (SplittingField (X ^ Nat.succ n✝ ^ n - X)))
⊢ ∀ (x y : GaloisField (Nat.succ n✝) n),
    x ^ Nat.succ n✝ ^ n = x → y ^ Nat.succ n✝ ^ n = y → x ^ Nat.succ n✝ ^ n * y ^ Nat.succ n✝ ^ n = x * y

Next tactic:
intro x y hx hy
theorem finrank {n} (h : n ≠ 0) : FiniteDimensional.finrank (ZMod p) (GaloisField p n) = n := by
  set g_poly := (X ^ p ^ n - X : (ZMod p)[X])
  have hp : 1 < p := h_prime.out.one_lt
  have aux : g_poly ≠ 0 := FiniteField.X_pow_card_pow_sub_X_ne_zero _ h hp
  -- Porting note : in the statment of `key`, replaced `g_poly` by its value otherwise the
  -- proof fails
  have key : Fintype.card (g_poly.rootSet (GaloisField p n)) = g_poly.natDegree :=
    card_rootSet_eq_natDegree (galois_poly_separable p _ (dvd_pow (dvd_refl p) h))
      (SplittingField.splits (X ^ p ^ n - X : (ZMod p)[X]))
  have nat_degree_eq : g_poly.natDegree = p ^ n :=
    FiniteField.X_pow_card_pow_sub_X_natDegree_eq _ h hp
  rw [nat_degree_eq] at key
  suffices g_poly.rootSet (GaloisField p n) = Set.univ by
    simp_rw [this, ← Fintype.ofEquiv_card (Equiv.Set.univ _)] at key
    -- Porting note: prevents `card_eq_pow_finrank` from using a wrong instance for `Fintype`
    rw [@card_eq_pow_finrank (ZMod p) _ _ _ _ _ (_), ZMod.card] at key
    exact Nat.pow_right_injective (Nat.Prime.one_lt' p).out key
  rw [Set.eq_univ_iff_forall]
  suffices ∀ (x) (hx : x ∈ (⊤ : Subalgebra (ZMod p) (GaloisField p n))),
      x ∈ (X ^ p ^ n - X : (ZMod p)[X]).rootSet (GaloisField p n)
    by simpa
  rw [← SplittingField.adjoin_rootSet]
  simp_rw [Algebra.mem_adjoin_iff]
  intro x hx
  -- We discharge the `p = 0` separately, to avoid typeclass issues on `ZMod p`.
  cases p; cases hp
  refine Subring.closure_induction hx ?_ ?_ ?_ ?_ ?_ ?_ <;> simp_rw [mem_rootSet_of_ne aux]
  · rintro x (⟨r, rfl⟩ | hx)
    · simp only [map_sub, map_pow, aeval_X]
      rw [← map_pow, ZMod.pow_card_pow, sub_self]
    · dsimp only [GaloisField] at hx
      rwa [mem_rootSet_of_ne aux] at hx
  · rw [← coeff_zero_eq_aeval_zero']
    simp only [coeff_X_pow, coeff_X_zero, sub_zero, _root_.map_eq_zero, ite_eq_right_iff,
      one_ne_zero, coeff_sub]
    intro hn
    exact Nat.not_lt_zero 1 (pow_eq_zero hn.symm ▸ hp)
  · simp
  · simp only [aeval_X_pow, aeval_X, AlgHom.map_sub, add_pow_char_pow, sub_eq_zero]
    intro x y hx hy
    rw [hx, hy]
  · intro x hx
    simp only [sub_eq_zero, aeval_X_pow, aeval_X, AlgHom.map_sub, sub_neg_eq_add] at *
    rw [neg_pow, hx, CharP.neg_one_pow_char_pow]
    simp
  · simp only [aeval_X_pow, aeval_X, AlgHom.map_sub, mul_pow, sub_eq_zero]
    intro x y hx hy
    

Proof state:
case succ.refine_6
p : ℕ
inst✝ : Fact (Nat.Prime p)
n✝² n✝¹ n : ℕ
h : n ≠ 0
n✝ : ℕ
h_prime : Fact (Nat.Prime (Nat.succ n✝))
g_poly : (ZMod (Nat.succ n✝))[X] := X ^ Nat.succ n✝ ^ n - X
hp : 1 < Nat.succ n✝
aux : g_poly ≠ 0
key : Fintype.card ↑(rootSet g_poly (GaloisField (Nat.succ n✝) n)) = Nat.succ n✝ ^ n
nat_degree_eq : natDegree g_poly = Nat.succ n✝ ^ n
x✝ : GaloisField (Nat.succ n✝) n
hx✝ :
  x✝ ∈
    Subring.closure
      (Set.range ⇑(algebraMap (ZMod (Nat.succ n✝)) (GaloisField (Nat.succ n✝) n)) ∪
        rootSet (X ^ Nat.succ n✝ ^ n - X) (SplittingField (X ^ Nat.succ n✝ ^ n - X)))
x y : GaloisField (Nat.succ n✝) n
hx : x ^ Nat.succ n✝ ^ n = x
hy : y ^ Nat.succ n✝ ^ n = y
⊢ x ^ Nat.succ n✝ ^ n * y ^ Nat.succ n✝ ^ n = x * y

Next tactic:
rw [hx, hy]
theorem card (h : n ≠ 0) : Fintype.card (GaloisField p n) = p ^ n := by
  

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
h : n ≠ 0
⊢ Fintype.card (GaloisField p n) = p ^ n

Next tactic:
let b := IsNoetherian.finsetBasis (ZMod p) (GaloisField p n)
theorem card (h : n ≠ 0) : Fintype.card (GaloisField p n) = p ^ n := by
  let b := IsNoetherian.finsetBasis (ZMod p) (GaloisField p n)
  

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
h : n ≠ 0
b : Basis { x // x ∈ IsNoetherian.finsetBasisIndex (ZMod p) (GaloisField p n) } (ZMod p) (GaloisField p n) :=
  IsNoetherian.finsetBasis (ZMod p) (GaloisField p n)
⊢ Fintype.card (GaloisField p n) = p ^ n

Next tactic:
rw [Module.card_fintype b, ← FiniteDimensional.finrank_eq_card_basis b, ZMod.card, finrank p h]
theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by
  

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
⊢ Splits (RingHom.id (ZMod p)) (X ^ p - X)

Next tactic:
have hp : 1 < p := h_prime.out.one_lt
theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by
  have hp : 1 < p := h_prime.out.one_lt
  

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
hp : 1 < p
⊢ Splits (RingHom.id (ZMod p)) (X ^ p - X)

Next tactic:
have h1 : roots (X ^ p - X : (ZMod p)[X]) = Finset.univ.val := by
    convert FiniteField.roots_X_pow_card_sub_X (ZMod p)
    exact (ZMod.card p).symm
theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by
  have hp : 1 < p := h_prime.out.one_lt
  have h1 : roots (X ^ p - X : (ZMod p)[X]) = Finset.univ.val := by
    

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
hp : 1 < p
⊢ roots (X ^ p - X) = univ.val

Next tactic:
convert FiniteField.roots_X_pow_card_sub_X (ZMod p)
theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by
  have hp : 1 < p := h_prime.out.one_lt
  have h1 : roots (X ^ p - X : (ZMod p)[X]) = Finset.univ.val := by
    convert FiniteField.roots_X_pow_card_sub_X (ZMod p)
    

Proof state:
case h.e'_2.h.e'_4.h.h.e'_5.h.e'_6
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
hp : 1 < p
e_2✝ : ZMod.commRing p = EuclideanDomain.toCommRing
⊢ p = Fintype.card (ZMod p)

Next tactic:
exact (ZMod.card p).symm
theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by
  have hp : 1 < p := h_prime.out.one_lt
  have h1 : roots (X ^ p - X : (ZMod p)[X]) = Finset.univ.val := by
    convert FiniteField.roots_X_pow_card_sub_X (ZMod p)
    exact (ZMod.card p).symm
  

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
hp : 1 < p
h1 : roots (X ^ p - X) = univ.val
⊢ Splits (RingHom.id (ZMod p)) (X ^ p - X)

Next tactic:
have h2 := FiniteField.X_pow_card_sub_X_natDegree_eq (ZMod p) hp
theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by
  have hp : 1 < p := h_prime.out.one_lt
  have h1 : roots (X ^ p - X : (ZMod p)[X]) = Finset.univ.val := by
    convert FiniteField.roots_X_pow_card_sub_X (ZMod p)
    exact (ZMod.card p).symm
  have h2 := FiniteField.X_pow_card_sub_X_natDegree_eq (ZMod p) hp
  -- We discharge the `p = 0` separately, to avoid typeclass issues on `ZMod p`.
  

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
hp : 1 < p
h1 : roots (X ^ p - X) = univ.val
h2 : natDegree (X ^ p - X) = p
⊢ Splits (RingHom.id (ZMod p)) (X ^ p - X)

Next tactic:
cases p
theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by
  have hp : 1 < p := h_prime.out.one_lt
  have h1 : roots (X ^ p - X : (ZMod p)[X]) = Finset.univ.val := by
    convert FiniteField.roots_X_pow_card_sub_X (ZMod p)
    exact (ZMod.card p).symm
  have h2 := FiniteField.X_pow_card_sub_X_natDegree_eq (ZMod p) hp
  -- We discharge the `p = 0` separately, to avoid typeclass issues on `ZMod p`.
  cases p; 

Proof state:
case zero
p : ℕ
inst✝ : Fact (Nat.Prime p)
n✝ n : ℕ
h_prime : Fact (Nat.Prime Nat.zero)
hp : 1 < Nat.zero
h1 : roots (X ^ Nat.zero - X) = univ.val
h2 : natDegree (X ^ Nat.zero - X) = Nat.zero
⊢ Splits (RingHom.id (ZMod Nat.zero)) (X ^ Nat.zero - X)
case succ
p : ℕ
inst✝ : Fact (Nat.Prime p)
n✝¹ n n✝ : ℕ
h_prime : Fact (Nat.Prime (Nat.succ n✝))
hp : 1 < Nat.succ n✝
h1 : roots (X ^ Nat.succ n✝ - X) = univ.val
h2 : natDegree (X ^ Nat.succ n✝ - X) = Nat.succ n✝
⊢ Splits (RingHom.id (ZMod (Nat.succ n✝))) (X ^ Nat.succ n✝ - X)

Next tactic:
cases hp
theorem splits_zmod_X_pow_sub_X : Splits (RingHom.id (ZMod p)) (X ^ p - X) := by
  have hp : 1 < p := h_prime.out.one_lt
  have h1 : roots (X ^ p - X : (ZMod p)[X]) = Finset.univ.val := by
    convert FiniteField.roots_X_pow_card_sub_X (ZMod p)
    exact (ZMod.card p).symm
  have h2 := FiniteField.X_pow_card_sub_X_natDegree_eq (ZMod p) hp
  -- We discharge the `p = 0` separately, to avoid typeclass issues on `ZMod p`.
  cases p; cases hp
  

Proof state:
case succ
p : ℕ
inst✝ : Fact (Nat.Prime p)
n✝¹ n n✝ : ℕ
h_prime : Fact (Nat.Prime (Nat.succ n✝))
hp : 1 < Nat.succ n✝
h1 : roots (X ^ Nat.succ n✝ - X) = univ.val
h2 : natDegree (X ^ Nat.succ n✝ - X) = Nat.succ n✝
⊢ Splits (RingHom.id (ZMod (Nat.succ n✝))) (X ^ Nat.succ n✝ - X)

Next tactic:
rw [splits_iff_card_roots, h1, ← Finset.card_def, Finset.card_univ, h2, ZMod.card]
/-- A Galois field with exponent 1 is equivalent to `ZMod` -/
def equivZmodP : GaloisField p 1 ≃ₐ[ZMod p] ZMod p :=
  let h : (X ^ p ^ 1 : (ZMod p)[X]) = X ^ Fintype.card (ZMod p) := by 

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
⊢ X ^ p ^ 1 = X ^ Fintype.card (ZMod p)

Next tactic:
rw [pow_one, ZMod.card p]
/-- A Galois field with exponent 1 is equivalent to `ZMod` -/
def equivZmodP : GaloisField p 1 ≃ₐ[ZMod p] ZMod p :=
  let h : (X ^ p ^ 1 : (ZMod p)[X]) = X ^ Fintype.card (ZMod p) := by rw [pow_one, ZMod.card p]
  let inst : IsSplittingField (ZMod p) (ZMod p) (X ^ p ^ 1 - X) := by 

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
h : X ^ p ^ 1 = X ^ Fintype.card (ZMod p) :=
  Eq.mpr (id (pow_one p ▸ Eq.refl (X ^ p ^ 1 = X ^ Fintype.card (ZMod p))))
    (Eq.mpr (id (ZMod.card p ▸ Eq.refl (X ^ p = X ^ Fintype.card (ZMod p)))) (Eq.refl (X ^ p)))
⊢ IsSplittingField (ZMod p) (ZMod p) (X ^ p ^ 1 - X)

Next tactic:
rw [h]
/-- A Galois field with exponent 1 is equivalent to `ZMod` -/
def equivZmodP : GaloisField p 1 ≃ₐ[ZMod p] ZMod p :=
  let h : (X ^ p ^ 1 : (ZMod p)[X]) = X ^ Fintype.card (ZMod p) := by rw [pow_one, ZMod.card p]
  let inst : IsSplittingField (ZMod p) (ZMod p) (X ^ p ^ 1 - X) := by rw [h]; 

Proof state:
p✝ : ℕ
inst✝ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
h : X ^ p ^ 1 = X ^ Fintype.card (ZMod p) :=
  Eq.mpr (id (pow_one p ▸ Eq.refl (X ^ p ^ 1 = X ^ Fintype.card (ZMod p))))
    (Eq.mpr (id (ZMod.card p ▸ Eq.refl (X ^ p = X ^ Fintype.card (ZMod p)))) (Eq.refl (X ^ p)))
⊢ IsSplittingField (ZMod p) (ZMod p) (X ^ Fintype.card (ZMod p) - X)

Next tactic:
infer_instance
instance (priority := 100) {K K' : Type*} [Field K] [Field K'] [Finite K'] [Algebra K K'] :
    IsGalois K K' := by
  

Proof state:
p✝ : ℕ
inst✝⁷ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
K✝ : Type u_1
inst✝⁶ : Field K✝
inst✝⁵ : Fintype K✝
inst✝⁴ : Algebra (ZMod p) K✝
K : Type u_2
K' : Type u_3
inst✝³ : Field K
inst✝² : Field K'
inst✝¹ : Finite K'
inst✝ : Algebra K K'
⊢ IsGalois K K'

Next tactic:
cases nonempty_fintype K'
instance (priority := 100) {K K' : Type*} [Field K] [Field K'] [Finite K'] [Algebra K K'] :
    IsGalois K K' := by
  cases nonempty_fintype K'
  

Proof state:
case intro
p✝ : ℕ
inst✝⁷ : Fact (Nat.Prime p✝)
n✝ p : ℕ
h_prime : Fact (Nat.Prime p)
n : ℕ
K✝ : Type u_1
inst✝⁶ : Field K✝
inst✝⁵ : Fintype K✝
inst✝⁴ : Algebra (ZMod p) K✝
K : Type u_2
K' : Type u_3
inst✝³ : Field K
inst✝² : Field K'
inst✝¹ : Finite K'
inst✝ : Algebra K K'
val✝ : Fintype K'
⊢ IsGalois K K'

Next tactic:
obtain ⟨p, hp⟩ := CharP.exists K
instance (priority := 100) {K K' : Type*} [Field K] [Field K'] [Finite K'] [Algebra K K'] :
    IsGalois K K' := by
  cases nonempty_fintype K'
  obtain ⟨p, hp⟩ := CharP.exists K
  

Proof state:
case intro.intro
p✝¹ : ℕ
inst✝⁷ : Fact (Nat.Prime p✝¹)
n✝ p✝ : ℕ
h_prime : Fact (Nat.Prime p✝)
n : ℕ
K✝ : Type u_1
inst✝⁶ : Field K✝
inst✝⁵ : Fintype K✝
inst✝⁴ : Algebra (ZMod p✝) K✝
K : Type u_2
K' : Type u_3
inst✝³ : Field K
inst✝² : Field K'
inst✝¹ : Finite K'
inst✝ : Algebra K K'
val✝ : Fintype K'
p : ℕ
hp : CharP K p
⊢ IsGalois K K'

Next tactic:
haveI : CharP K p := hp
instance (priority := 100) {K K' : Type*} [Field K] [Field K'] [Finite K'] [Algebra K K'] :
    IsGalois K K' := by
  cases nonempty_fintype K'
  obtain ⟨p, hp⟩ := CharP.exists K
  haveI : CharP K p := hp
  

Proof state:
case intro.intro
p✝¹ : ℕ
inst✝⁷ : Fact (Nat.Prime p✝¹)
n✝ p✝ : ℕ
h_prime : Fact (Nat.Prime p✝)
n : ℕ
K✝ : Type u_1
inst✝⁶ : Field K✝
inst✝⁵ : Fintype K✝
inst✝⁴ : Algebra (ZMod p✝) K✝
K : Type u_2
K' : Type u_3
inst✝³ : Field K
inst✝² : Field K'
inst✝¹ : Finite K'
inst✝ : Algebra K K'
val✝ : Fintype K'
p : ℕ
hp : CharP K p
this : CharP K p
⊢ IsGalois K K'

Next tactic:
haveI : CharP K' p := charP_of_injective_algebraMap' K K' p
instance (priority := 100) {K K' : Type*} [Field K] [Field K'] [Finite K'] [Algebra K K'] :
    IsGalois K K' := by
  cases nonempty_fintype K'
  obtain ⟨p, hp⟩ := CharP.exists K
  haveI : CharP K p := hp
  haveI : CharP K' p := charP_of_injective_algebraMap' K K' p
  

Proof state:
case intro.intro
p✝¹ : ℕ
inst✝⁷ : Fact (Nat.Prime p✝¹)
n✝ p✝ : ℕ
h_prime : Fact (Nat.Prime p✝)
n : ℕ
K✝ : Type u_1
inst✝⁶ : Field K✝
inst✝⁵ : Fintype K✝
inst✝⁴ : Algebra (ZMod p✝) K✝
K : Type u_2
K' : Type u_3
inst✝³ : Field K
inst✝² : Field K'
inst✝¹ : Finite K'
inst✝ : Algebra K K'
val✝ : Fintype K'
p : ℕ
hp : CharP K p
this✝ : CharP K p
this : CharP K' p
⊢ IsGalois K K'

Next tactic:
exact IsGalois.of_separable_splitting_field
    (galois_poly_separable p (Fintype.card K')
      (let ⟨n, _, hn⟩ := FiniteField.card K' p
      hn.symm ▸ dvd_pow_self p n.ne_zero))
/-- Uniqueness of finite fields:
  Any two finite fields of the same cardinality are (possibly non canonically) isomorphic-/
def algEquivOfCardEq (p : ℕ) [h_prime : Fact p.Prime] [Algebra (ZMod p) K] [Algebra (ZMod p) K']
    (hKK' : Fintype.card K = Fintype.card K') : K ≃ₐ[ZMod p] K' := by
  

Proof state:
p✝ : ℕ
inst✝⁶ : Fact (Nat.Prime p✝)
n : ℕ
K : Type u_1
inst✝⁵ : Field K
inst✝⁴ : Fintype K
K' : Type u_2
inst✝³ : Field K'
inst✝² : Fintype K'
p : ℕ
h_prime : Fact (Nat.Prime p)
inst✝¹ : Algebra (ZMod p) K
inst✝ : Algebra (ZMod p) K'
hKK' : Fintype.card K = Fintype.card K'
⊢ K ≃ₐ[ZMod p] K'

Next tactic:
have : CharP K p := by rw [← Algebra.charP_iff (ZMod p) K p]; exact ZMod.charP p
/-- Uniqueness of finite fields:
  Any two finite fields of the same cardinality are (possibly non canonically) isomorphic-/
def algEquivOfCardEq (p : ℕ) [h_prime : Fact p.Prime] [Algebra (ZMod p) K] [Algebra (ZMod p) K']
    (hKK' : Fintype.card K = Fintype.card K') : K ≃ₐ[ZMod p] K' := by
  have : CharP K p := by 

Proof state:
p✝ : ℕ
inst✝⁶ : Fact (Nat.Prime p✝)
n : ℕ
K : Type u_1
inst✝⁵ : Field K
inst✝⁴ : Fintype K
K' : Type u_2
inst✝³ : Field K'
inst✝² : Fintype K'
p : ℕ
h_prime : Fact (Nat.Prime p)
inst✝¹ : Algebra (ZMod p) K
inst✝ : Algebra (ZMod p) K'
hKK' : Fintype.card K = Fintype.card K'
⊢ CharP K p

Next tactic:
rw [← Algebra.charP_iff (ZMod p) K p]
/-- Uniqueness of finite fields:
  Any two finite fields of the same cardinality are (possibly non canonically) isomorphic-/
def algEquivOfCardEq (p : ℕ) [h_prime : Fact p.Prime] [Algebra (ZMod p) K] [Algebra (ZMod p) K']
    (hKK' : Fintype.card K = Fintype.card K') : K ≃ₐ[ZMod p] K' := by
  have : CharP K p := by rw [← Algebra.charP_iff (ZMod p) K p]; 

Proof state:
p✝ : ℕ
inst✝⁶ : Fact (Nat.Prime p✝)
n : ℕ
K : Type u_1
inst✝⁵ : Field K
inst✝⁴ : Fintype K
K' : Type u_2
inst✝³ : Field K'
inst✝² : Fintype K'
p : ℕ
h_prime : Fact (Nat.Prime p)
inst✝¹ : Algebra (ZMod p) K
inst✝ : Algebra (ZMod p) K'
hKK' : Fintype.card K = Fintype.card K'
⊢ CharP (ZMod p) p

Next tactic:
exact ZMod.charP p
/-- Uniqueness of finite fields:
  Any two finite fields of the same cardinality are (possibly non canonically) isomorphic-/
def algEquivOfCardEq (p : ℕ) [h_prime : Fact p.Prime] [Algebra (ZMod p) K] [Algebra (ZMod p) K']
    (hKK' : Fintype.card K = Fintype.card K') : K ≃ₐ[ZMod p] K' := by
  have : CharP K p := by rw [← Algebra.charP_iff (ZMod p) K p]; exact ZMod.charP p
  

Proof state:
p✝ : ℕ
inst✝⁶ : Fact (Nat.Prime p✝)
n : ℕ
K : Type u_1
inst✝⁵ : Field K
inst✝⁴ : Fintype K
K' : Type u_2
inst✝³ : Field K'
inst✝² : Fintype K'
p : ℕ
h_prime : Fact (Nat.Prime p)
inst✝¹ : Algebra (ZMod p) K
inst✝ : Algebra (ZMod p) K'
hKK' : Fintype.card K = Fintype.card K'
this : CharP K p
⊢ K ≃ₐ[ZMod p] K'

Next tactic:
have : CharP K' p := by rw [← Algebra.charP_iff (ZMod p) K' p]; exact ZMod.charP p
/-- Uniqueness of finite fields:
  Any two finite fields of the same cardinality are (possibly non canonically) isomorphic-/
def algEquivOfCardEq (p : ℕ) [h_prime : Fact p.Prime] [Algebra (ZMod p) K] [Algebra (ZMod p) K']
    (hKK' : Fintype.card K = Fintype.card K') : K ≃ₐ[ZMod p] K' := by
  have : CharP K p := by rw [← Algebra.charP_iff (ZMod p) K p]; exact ZMod.charP p
  have : CharP K' p := by 

Proof state:
p✝ : ℕ
inst✝⁶ : Fact (Nat.Prime p✝)
n : ℕ
K : Type u_1
inst✝⁵ : Field K
inst✝⁴ : Fintype K
K' : Type u_2
inst✝³ : Field K'
inst✝² : Fintype K'
p : ℕ
h_prime : Fact (Nat.Prime p)
inst✝¹ : Algebra (ZMod p) K
inst✝ : Algebra (ZMod p) K'
hKK' : Fintype.card K = Fintype.card K'
this : CharP K p
⊢ CharP K' p

Next tactic:
rw [← Algebra.charP_iff (ZMod p) K' p]
/-- Uniqueness of finite fields:
  Any two finite fields of the same cardinality are (possibly non canonically) isomorphic-/
def algEquivOfCardEq (p : ℕ) [h_prime : Fact p.Prime] [Algebra (ZMod p) K] [Algebra (ZMod p) K']
    (hKK' : Fintype.card K = Fintype.card K') : K ≃ₐ[ZMod p] K' := by
  have : CharP K p := by rw [← Algebra.charP_iff (ZMod p) K p]; exact ZMod.charP p
  have : CharP K' p := by rw [← Algebra.charP_iff (ZMod p) K' p]; 

Proof state:
p✝ : ℕ
inst✝⁶ : Fact (Nat.Prime p✝)
n : ℕ
K : Type u_1
inst✝⁵ : Field K
inst✝⁴ : Fintype K
K' : Type u_2
inst✝³ : Field K'
inst✝² : Fintype K'
p : ℕ
h_prime : Fact (Nat.Prime p)
inst✝¹ : Algebra (ZMod p) K
inst✝ : Algebra (ZMod p) K'
hKK' : Fintype.card K = Fintype.card K'
this : CharP K p
⊢ CharP (ZMod p) p

Next tactic:
exact ZMod.charP p