l3lab/ntp-mathlib huggingface dataset:
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
      apply_fun fun e => (e y).down at H
      dsimp [LocallyConstant.ofIsClopen] at H
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
H :
  ((ContinuousMap.mk fun x => { down := 1 }) y).down =
    ((ContinuousMap.mk (ULift.up ∘ fun x => if x ∈ V then 0 else 1)) y).down
⊢ False

Next tactic:
erw [ContinuousMap.coe_mk, ContinuousMap.coe_mk, Function.comp_apply, if_pos hyV] at H
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
      apply_fun fun e => (e y).down at H
      dsimp [LocallyConstant.ofIsClopen] at H
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      erw [ContinuousMap.coe_mk, ContinuousMap.coe_mk, Function.comp_apply, if_pos hyV] at H
      

Proof state:
case mp.intro.intro.intro.intro
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
y : (forget Profinite).obj Y
hy : ∀ (a : (forget Profinite).obj X), f a ≠ y
hf : Epi f
C : Set ((forget Profinite).obj Y) := Set.range ⇑f
hC : IsClosed C
U : Set ((forget Profinite).obj Y) := Cᶜ
hyU : y ∈ U
hUy : U ∈ 𝓝 y
V : Set ((forget Profinite).obj Y)
hV : V ∈ {s | IsClopen s}
hyV : y ∈ V
hVU : V ⊆ U
Z : Profinite := of (ULift.{u, 0} (Fin 2))
g : Y ⟶ Z := ContinuousMap.mk ⇑(LocallyConstant.map ULift.up (LocallyConstant.ofIsClopen hV))
h : Y ⟶ Z := ContinuousMap.mk fun x => { down := 1 }
H : { down := 1 }.down = { down := 0 }.down
⊢ False

Next tactic:
exact top_ne_bot H
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
      apply_fun fun e => (e y).down at H
      dsimp [LocallyConstant.ofIsClopen] at H
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      erw [ContinuousMap.coe_mk, ContinuousMap.coe_mk, Function.comp_apply, if_pos hyV] at H
      exact top_ne_bot H
  · 

Proof state:
case mpr
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Function.Surjective ⇑f → Epi f

Next tactic:
rw [← CategoryTheory.epi_iff_surjective]
theorem epi_iff_surjective {X Y : Profinite.{u}} (f : X ⟶ Y) : Epi f ↔ Function.Surjective f := by
  constructor
  · -- Porting note: in mathlib3 `contrapose` saw through `Function.Surjective`.
    dsimp [Function.Surjective]
    contrapose!
    rintro ⟨y, hy⟩ hf
    skip
    let C := Set.range f
    have hC : IsClosed C := (isCompact_range f.continuous).isClosed
    let U := Cᶜ
    have hyU : y ∈ U := by
      refine' Set.mem_compl _
      rintro ⟨y', hy'⟩
      exact hy y' hy'
    have hUy : U ∈ 𝓝 y := hC.compl_mem_nhds hyU
    obtain ⟨V, hV, hyV, hVU⟩ := isTopologicalBasis_isClopen.mem_nhds_iff.mp hUy
    classical
      let Z := of (ULift.{u} <| Fin 2)
      let g : Y ⟶ Z := ⟨(LocallyConstant.ofIsClopen hV).map ULift.up, LocallyConstant.continuous _⟩
      let h : Y ⟶ Z := ⟨fun _ => ⟨1⟩, continuous_const⟩
      have H : h = g := by
        rw [← cancel_epi f]
        ext x
        apply ULift.ext
        dsimp [LocallyConstant.ofIsClopen]
        -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
        erw [comp_apply, ContinuousMap.coe_mk, comp_apply, ContinuousMap.coe_mk,
          Function.comp_apply, if_neg]
        refine' mt (fun α => hVU α) _
        simp only [Set.mem_range_self, not_true, not_false_iff, Set.mem_compl_iff]
      apply_fun fun e => (e y).down at H
      dsimp [LocallyConstant.ofIsClopen] at H
      -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
      erw [ContinuousMap.coe_mk, ContinuousMap.coe_mk, Function.comp_apply, if_pos hyV] at H
      exact top_ne_bot H
  · rw [← CategoryTheory.epi_iff_surjective]
    

Proof state:
case mpr
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Epi ⇑f → Epi f

Next tactic:
apply (forget Profinite).epi_of_epi_map
instance {X Y : Profinite} (f : X ⟶ Y) [Epi f] : @Epi CompHaus _ _ _ f := by
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
inst✝ : Epi f
⊢ Epi f

Next tactic:
erw [CompHaus.epi_iff_surjective, ← epi_iff_surjective]
instance {X Y : Profinite} (f : X ⟶ Y) [Epi f] : @Epi CompHaus _ _ _ f := by
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  erw [CompHaus.epi_iff_surjective, ← epi_iff_surjective]; 

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
inst✝ : Epi f
⊢ Epi f

Next tactic:
assumption
instance {X Y : Profinite} (f : X ⟶ Y) [@Epi CompHaus _ _ _ f] : Epi f := by
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
inst✝ : Epi f
⊢ Epi f

Next tactic:
erw [epi_iff_surjective, ← CompHaus.epi_iff_surjective]
instance {X Y : Profinite} (f : X ⟶ Y) [@Epi CompHaus _ _ _ f] : Epi f := by
  -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
  erw [epi_iff_surjective, ← CompHaus.epi_iff_surjective]; 

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
inst✝ : Epi f
⊢ Epi f

Next tactic:
assumption
theorem mono_iff_injective {X Y : Profinite.{u}} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  

Proof state:
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Mono f ↔ Function.Injective ⇑f

Next tactic:
constructor
theorem mono_iff_injective {X Y : Profinite.{u}} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · 

Proof state:
case mp
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Mono f → Function.Injective ⇑f

Next tactic:
intro h
theorem mono_iff_injective {X Y : Profinite.{u}} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro h
    

Proof state:
case mp
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
h : Mono f
⊢ Function.Injective ⇑f

Next tactic:
haveI : Limits.PreservesLimits profiniteToCompHaus := inferInstance
theorem mono_iff_injective {X Y : Profinite.{u}} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro h
    haveI : Limits.PreservesLimits profiniteToCompHaus := inferInstance
    

Proof state:
case mp
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
h : Mono f
this : Limits.PreservesLimits profiniteToCompHaus
⊢ Function.Injective ⇑f

Next tactic:
haveI : Mono (profiniteToCompHaus.map f) := inferInstance
theorem mono_iff_injective {X Y : Profinite.{u}} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro h
    haveI : Limits.PreservesLimits profiniteToCompHaus := inferInstance
    haveI : Mono (profiniteToCompHaus.map f) := inferInstance
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    

Proof state:
case mp
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
h : Mono f
this✝ : Limits.PreservesLimits profiniteToCompHaus
this : Mono (profiniteToCompHaus.map f)
⊢ Function.Injective ⇑f

Next tactic:
erw [← CompHaus.mono_iff_injective]
theorem mono_iff_injective {X Y : Profinite.{u}} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro h
    haveI : Limits.PreservesLimits profiniteToCompHaus := inferInstance
    haveI : Mono (profiniteToCompHaus.map f) := inferInstance
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    erw [← CompHaus.mono_iff_injective]
    

Proof state:
case mp
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
h : Mono f
this✝ : Limits.PreservesLimits profiniteToCompHaus
this : Mono (profiniteToCompHaus.map f)
⊢ Mono f

Next tactic:
assumption
theorem mono_iff_injective {X Y : Profinite.{u}} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro h
    haveI : Limits.PreservesLimits profiniteToCompHaus := inferInstance
    haveI : Mono (profiniteToCompHaus.map f) := inferInstance
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    erw [← CompHaus.mono_iff_injective]
    assumption
  · 

Proof state:
case mpr
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Function.Injective ⇑f → Mono f

Next tactic:
rw [← CategoryTheory.mono_iff_injective]
theorem mono_iff_injective {X Y : Profinite.{u}} (f : X ⟶ Y) : Mono f ↔ Function.Injective f := by
  constructor
  · intro h
    haveI : Limits.PreservesLimits profiniteToCompHaus := inferInstance
    haveI : Mono (profiniteToCompHaus.map f) := inferInstance
    -- This used to be `rw`, but we need `erw` after leanprover/lean4#2644
    erw [← CompHaus.mono_iff_injective]
    assumption
  · rw [← CategoryTheory.mono_iff_injective]
    

Proof state:
case mpr
X✝ Y✝ : Profinite
f✝ : X✝ ⟶ Y✝
X Y : Profinite
f : X ⟶ Y
⊢ Mono ⇑f → Mono f

Next tactic:
exact (forget Profinite).mono_of_mono_map (f := f)
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
⊢ q = 0 ∨ IsPrimePow q

Next tactic:
apply or_iff_not_imp_left.2
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
⊢ ¬q = 0 → IsPrimePow q

Next tactic:
intro q_pos
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
⊢ IsPrimePow q

Next tactic:
let K := LocalRing.ResidueField R
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
⊢ IsPrimePow q

Next tactic:
haveI RM_char := ringChar.charP K
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
⊢ IsPrimePow q

Next tactic:
let r := ringChar K
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  let r := ringChar K
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
r : ℕ := ringChar K
⊢ IsPrimePow q

Next tactic:
let n := q.factorization r
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  let r := ringChar K
  let n := q.factorization r
  -- `r := char(R/m)` is either prime or zero:
  

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
r : ℕ := ringChar K
n : ℕ := (Nat.factorization q) r
⊢ IsPrimePow q

Next tactic:
cases' CharP.char_is_prime_or_zero K r with r_prime r_zero
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  let r := ringChar K
  let n := q.factorization r
  -- `r := char(R/m)` is either prime or zero:
  cases' CharP.char_is_prime_or_zero K r with r_prime r_zero
  · 

Proof state:
case inl
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
r : ℕ := ringChar K
n : ℕ := (Nat.factorization q) r
r_prime : Nat.Prime r
⊢ IsPrimePow q

Next tactic:
let a := q / r ^ n
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  let r := ringChar K
  let n := q.factorization r
  -- `r := char(R/m)` is either prime or zero:
  cases' CharP.char_is_prime_or_zero K r with r_prime r_zero
  · let a := q / r ^ n
    -- If `r` is prime, we can write it as `r = a * q^n` ...
    

Proof state:
case inl
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
r : ℕ := ringChar K
n : ℕ := (Nat.factorization q) r
r_prime : Nat.Prime r
a : ℕ := q / r ^ n
⊢ IsPrimePow q

Next tactic:
have q_eq_a_mul_rn : q = r ^ n * a := by rw [Nat.mul_div_cancel' (Nat.ord_proj_dvd q r)]
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  let r := ringChar K
  let n := q.factorization r
  -- `r := char(R/m)` is either prime or zero:
  cases' CharP.char_is_prime_or_zero K r with r_prime r_zero
  · let a := q / r ^ n
    -- If `r` is prime, we can write it as `r = a * q^n` ...
    have q_eq_a_mul_rn : q = r ^ n * a := by 

Proof state:
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
r : ℕ := ringChar K
n : ℕ := (Nat.factorization q) r
r_prime : Nat.Prime r
a : ℕ := q / r ^ n
⊢ q = r ^ n * a

Next tactic:
rw [Nat.mul_div_cancel' (Nat.ord_proj_dvd q r)]
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  let r := ringChar K
  let n := q.factorization r
  -- `r := char(R/m)` is either prime or zero:
  cases' CharP.char_is_prime_or_zero K r with r_prime r_zero
  · let a := q / r ^ n
    -- If `r` is prime, we can write it as `r = a * q^n` ...
    have q_eq_a_mul_rn : q = r ^ n * a := by rw [Nat.mul_div_cancel' (Nat.ord_proj_dvd q r)]
    

Proof state:
case inl
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
r : ℕ := ringChar K
n : ℕ := (Nat.factorization q) r
r_prime : Nat.Prime r
a : ℕ := q / r ^ n
q_eq_a_mul_rn : q = r ^ n * a
⊢ IsPrimePow q

Next tactic:
have r_ne_dvd_a := Nat.not_dvd_ord_compl r_prime q_pos
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  let r := ringChar K
  let n := q.factorization r
  -- `r := char(R/m)` is either prime or zero:
  cases' CharP.char_is_prime_or_zero K r with r_prime r_zero
  · let a := q / r ^ n
    -- If `r` is prime, we can write it as `r = a * q^n` ...
    have q_eq_a_mul_rn : q = r ^ n * a := by rw [Nat.mul_div_cancel' (Nat.ord_proj_dvd q r)]
    have r_ne_dvd_a := Nat.not_dvd_ord_compl r_prime q_pos
    

Proof state:
case inl
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
r : ℕ := ringChar K
n : ℕ := (Nat.factorization q) r
r_prime : Nat.Prime r
a : ℕ := q / r ^ n
q_eq_a_mul_rn : q = r ^ n * a
r_ne_dvd_a : ¬r ∣ q / r ^ (Nat.factorization q) r
⊢ IsPrimePow q

Next tactic:
have rn_dvd_q : r ^ n ∣ q := ⟨a, q_eq_a_mul_rn⟩
/-- In a local ring the characteristics is either zero or a prime power. -/
theorem charP_zero_or_prime_power (R : Type*) [CommRing R] [LocalRing R] (q : ℕ)
    [char_R_q : CharP R q] : q = 0 ∨ IsPrimePow q := by
  -- Assume `q := char(R)` is not zero.
  apply or_iff_not_imp_left.2
  intro q_pos
  let K := LocalRing.ResidueField R
  haveI RM_char := ringChar.charP K
  let r := ringChar K
  let n := q.factorization r
  -- `r := char(R/m)` is either prime or zero:
  cases' CharP.char_is_prime_or_zero K r with r_prime r_zero
  · let a := q / r ^ n
    -- If `r` is prime, we can write it as `r = a * q^n` ...
    have q_eq_a_mul_rn : q = r ^ n * a := by rw [Nat.mul_div_cancel' (Nat.ord_proj_dvd q r)]
    have r_ne_dvd_a := Nat.not_dvd_ord_compl r_prime q_pos
    have rn_dvd_q : r ^ n ∣ q := ⟨a, q_eq_a_mul_rn⟩
    

Proof state:
case inl
R : Type u_1
inst✝¹ : CommRing R
inst✝ : LocalRing R
q : ℕ
char_R_q : CharP R q
q_pos : ¬q = 0
K : Type u_1 := LocalRing.ResidueField R
RM_char : CharP K (ringChar K)
r : ℕ := ringChar K
n : ℕ := (Nat.factorization q) r
r_prime : Nat.Prime r
a : ℕ := q / r ^ n
q_eq_a_mul_rn : q = r ^ n * a
r_ne_dvd_a : ¬r ∣ q / r ^ (Nat.factorization q) r
rn_dvd_q : r ^ n ∣ q
⊢ IsPrimePow q

Next tactic:
rw [mul_comm] at q_eq_a_mul_rn