l3lab/ntp-mathlib huggingface dataset:
theorem char_is_prime_of_two_le (p : ℕ) [hc : CharP R p] (hp : 2 ≤ p) : Nat.Prime p :=
  suffices ∀ (d) (_ : d ∣ p), d = 1 ∨ d = p from Nat.prime_def_lt''.mpr ⟨hp, this⟩
  fun (d : ℕ) (hdvd : ∃ e, p = d * e) =>
  let ⟨e, hmul⟩ := hdvd
  have : (p : R) = 0 := (cast_eq_zero_iff R p p).mpr (dvd_refl p)
  have : (d : R) * e = 0 := @Nat.cast_mul R _ d e ▸ hmul ▸ this
  Or.elim (eq_zero_or_eq_zero_of_mul_eq_zero this)
    (fun hd : (d : R) = 0 =>
      have : p ∣ d := (cast_eq_zero_iff R p d).mp hd
      show d = 1 ∨ d = p from Or.inr (this.antisymm' ⟨e, hmul⟩))
    fun he : (e : R) = 0 =>
    have : p ∣ e := (cast_eq_zero_iff R p e).mp he
    have : e ∣ p := dvd_of_mul_left_eq d (Eq.symm hmul)
    have : e = p := ‹e ∣ p›.antisymm ‹p ∣ e›
    have h₀ : 0 < p := two_pos.trans_le hp
    have : d * p = 1 * p := by rw [‹e = p›] at hmul; 

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : NoZeroDivisors R
p : ℕ
hc : CharP R p
hp : 2 ≤ p
d : ℕ
hdvd : ∃ e, p = d * e
e : ℕ
hmul : p = d * p
this✝³ : ↑p = 0
this✝² : ↑d * ↑e = 0
he : ↑e = 0
this✝¹ : p ∣ e
this✝ : e ∣ p
this : e = p
h₀ : 0 < p
⊢ d * p = 1 * p

Next tactic:
rw [one_mul]
theorem char_is_prime_of_two_le (p : ℕ) [hc : CharP R p] (hp : 2 ≤ p) : Nat.Prime p :=
  suffices ∀ (d) (_ : d ∣ p), d = 1 ∨ d = p from Nat.prime_def_lt''.mpr ⟨hp, this⟩
  fun (d : ℕ) (hdvd : ∃ e, p = d * e) =>
  let ⟨e, hmul⟩ := hdvd
  have : (p : R) = 0 := (cast_eq_zero_iff R p p).mpr (dvd_refl p)
  have : (d : R) * e = 0 := @Nat.cast_mul R _ d e ▸ hmul ▸ this
  Or.elim (eq_zero_or_eq_zero_of_mul_eq_zero this)
    (fun hd : (d : R) = 0 =>
      have : p ∣ d := (cast_eq_zero_iff R p d).mp hd
      show d = 1 ∨ d = p from Or.inr (this.antisymm' ⟨e, hmul⟩))
    fun he : (e : R) = 0 =>
    have : p ∣ e := (cast_eq_zero_iff R p e).mp he
    have : e ∣ p := dvd_of_mul_left_eq d (Eq.symm hmul)
    have : e = p := ‹e ∣ p›.antisymm ‹p ∣ e›
    have h₀ : 0 < p := two_pos.trans_le hp
    have : d * p = 1 * p := by rw [‹e = p›] at hmul; rw [one_mul]; 

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : NoZeroDivisors R
p : ℕ
hc : CharP R p
hp : 2 ≤ p
d : ℕ
hdvd : ∃ e, p = d * e
e : ℕ
hmul : p = d * p
this✝³ : ↑p = 0
this✝² : ↑d * ↑e = 0
he : ↑e = 0
this✝¹ : p ∣ e
this✝ : e ∣ p
this : e = p
h₀ : 0 < p
⊢ d * p = p

Next tactic:
exact Eq.symm hmul
instance (priority := 100) CharOne.subsingleton [CharP R 1] : Subsingleton R :=
  Subsingleton.intro <|
    suffices ∀ r : R, r = 0 from fun a b => show a = b by rw [this a, this b]
    fun r =>
    calc
      r = 1 * r := by 

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : CharP R 1
r : R
⊢ r = 1 * r

Next tactic:
rw [one_mul]
instance (priority := 100) CharOne.subsingleton [CharP R 1] : Subsingleton R :=
  Subsingleton.intro <|
    suffices ∀ r : R, r = 0 from fun a b => show a = b by rw [this a, this b]
    fun r =>
    calc
      r = 1 * r := by rw [one_mul]
      _ = (1 : ℕ) * r := by 

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : CharP R 1
r : R
⊢ 1 * r = ↑1 * r

Next tactic:
rw [Nat.cast_one]
instance (priority := 100) CharOne.subsingleton [CharP R 1] : Subsingleton R :=
  Subsingleton.intro <|
    suffices ∀ r : R, r = 0 from fun a b => show a = b by rw [this a, this b]
    fun r =>
    calc
      r = 1 * r := by rw [one_mul]
      _ = (1 : ℕ) * r := by rw [Nat.cast_one]
      _ = 0 * r := by 

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : CharP R 1
r : R
⊢ ↑1 * r = 0 * r

Next tactic:
rw [CharP.cast_eq_zero]
instance (priority := 100) CharOne.subsingleton [CharP R 1] : Subsingleton R :=
  Subsingleton.intro <|
    suffices ∀ r : R, r = 0 from fun a b => show a = b by rw [this a, this b]
    fun r =>
    calc
      r = 1 * r := by rw [one_mul]
      _ = (1 : ℕ) * r := by rw [Nat.cast_one]
      _ = 0 * r := by rw [CharP.cast_eq_zero]
      _ = 0 := by 

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : CharP R 1
r : R
⊢ 0 * r = 0

Next tactic:
rw [zero_mul]
instance (priority := 100) CharOne.subsingleton [CharP R 1] : Subsingleton R :=
  Subsingleton.intro <|
    suffices ∀ r : R, r = 0 from fun a b => show a = b by 

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : CharP R 1
this : ∀ (r : R), r = 0
a b : R
⊢ a = b

Next tactic:
rw [this a, this b]
theorem ringChar_ne_one [Nontrivial R] : ringChar R ≠ 1 := by
  

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : Nontrivial R
⊢ ringChar R ≠ 1

Next tactic:
intro h
theorem ringChar_ne_one [Nontrivial R] : ringChar R ≠ 1 := by
  intro h
  

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : Nontrivial R
h : ringChar R = 1
⊢ False

Next tactic:
apply zero_ne_one' R
theorem ringChar_ne_one [Nontrivial R] : ringChar R ≠ 1 := by
  intro h
  apply zero_ne_one' R
  

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : Nontrivial R
h : ringChar R = 1
⊢ 0 = 1

Next tactic:
symm
theorem ringChar_ne_one [Nontrivial R] : ringChar R ≠ 1 := by
  intro h
  apply zero_ne_one' R
  symm
  

Proof state:
R : Type u_1
inst✝¹ : NonAssocSemiring R
inst✝ : Nontrivial R
h : ringChar R = 1
⊢ 1 = 0

Next tactic:
rw [← Nat.cast_one, ringChar.spec, h]
theorem nontrivial_of_char_ne_one {v : ℕ} (hv : v ≠ 1) [hr : CharP R v] : Nontrivial R :=
  ⟨⟨(1 : ℕ), 0, fun h =>
      hv <| by 

Proof state:
R : Type u_1
inst✝ : NonAssocSemiring R
v : ℕ
hv : v ≠ 1
hr : CharP R v
h : ↑1 = 0
⊢ v = 1

Next tactic:
rwa [CharP.cast_eq_zero_iff _ v, Nat.dvd_one] at h
/-- We have `2 ≠ 0` in a nontrivial ring whose characteristic is not `2`. -/
protected theorem Ring.two_ne_zero {R : Type*} [NonAssocSemiring R] [Nontrivial R]
    (hR : ringChar R ≠ 2) : (2 : R) ≠ 0 := by
  

Proof state:
R✝ : Type u_1
R : Type u_2
inst✝¹ : NonAssocSemiring R
inst✝ : Nontrivial R
hR : ringChar R ≠ 2
⊢ 2 ≠ 0

Next tactic:
rw [Ne.def, (by norm_cast : (2 : R) = (2 : ℕ)), ringChar.spec, Nat.dvd_prime Nat.prime_two]
/-- We have `2 ≠ 0` in a nontrivial ring whose characteristic is not `2`. -/
protected theorem Ring.two_ne_zero {R : Type*} [NonAssocSemiring R] [Nontrivial R]
    (hR : ringChar R ≠ 2) : (2 : R) ≠ 0 := by
  rw [Ne.def, (by 

Proof state:
R✝ : Type u_1
R : Type u_2
inst✝¹ : NonAssocSemiring R
inst✝ : Nontrivial R
hR : ringChar R ≠ 2
⊢ 2 = ↑2

Next tactic:
norm_cast
/-- We have `2 ≠ 0` in a nontrivial ring whose characteristic is not `2`. -/
protected theorem Ring.two_ne_zero {R : Type*} [NonAssocSemiring R] [Nontrivial R]
    (hR : ringChar R ≠ 2) : (2 : R) ≠ 0 := by
  rw [Ne.def, (by norm_cast : (2 : R) = (2 : ℕ)), ringChar.spec, Nat.dvd_prime Nat.prime_two]
  

Proof state:
R✝ : Type u_1
R : Type u_2
inst✝¹ : NonAssocSemiring R
inst✝ : Nontrivial R
hR : ringChar R ≠ 2
⊢ ¬(ringChar R = 1 ∨ ringChar R = 2)

Next tactic:
exact mt (or_iff_left hR).mp CharP.ringChar_ne_one
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      

Proof state:
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
⊢ ∀ (x : ℕ), ↑x = 0 ↔ n ∣ x

Next tactic:
have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by 

Proof state:
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
⊢ ↑n = 0

Next tactic:
rw [← hn, CharP.cast_card_eq_zero]
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      

Proof state:
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
⊢ ∀ (x : ℕ), ↑x = 0 ↔ n ∣ x

Next tactic:
intro k
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      

Proof state:
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
⊢ ↑k = 0 ↔ n ∣ k

Next tactic:
constructor
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      constructor
      · 

Proof state:
case mp
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
⊢ ↑k = 0 → n ∣ k

Next tactic:
intro h
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      constructor
      · intro h
        

Proof state:
case mp
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
h : ↑k = 0
⊢ n ∣ k

Next tactic:
rw [← Nat.mod_add_div k n, Nat.cast_add, Nat.cast_mul, H, zero_mul,
          add_zero] at h
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      constructor
      · intro h
        rw [← Nat.mod_add_div k n, Nat.cast_add, Nat.cast_mul, H, zero_mul,
          add_zero] at h
        

Proof state:
case mp
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
h : ↑(k % n) = 0
⊢ n ∣ k

Next tactic:
rw [Nat.dvd_iff_mod_eq_zero]
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      constructor
      · intro h
        rw [← Nat.mod_add_div k n, Nat.cast_add, Nat.cast_mul, H, zero_mul,
          add_zero] at h
        rw [Nat.dvd_iff_mod_eq_zero]
        

Proof state:
case mp
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
h : ↑(k % n) = 0
⊢ k % n = 0

Next tactic:
apply hR _ (Nat.mod_lt _ _) h
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      constructor
      · intro h
        rw [← Nat.mod_add_div k n, Nat.cast_add, Nat.cast_mul, H, zero_mul,
          add_zero] at h
        rw [Nat.dvd_iff_mod_eq_zero]
        apply hR _ (Nat.mod_lt _ _) h
        

Proof state:
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
h : ↑(k % n) = 0
⊢ n > 0

Next tactic:
rw [← hn, gt_iff_lt, Fintype.card_pos_iff]
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      constructor
      · intro h
        rw [← Nat.mod_add_div k n, Nat.cast_add, Nat.cast_mul, H, zero_mul,
          add_zero] at h
        rw [Nat.dvd_iff_mod_eq_zero]
        apply hR _ (Nat.mod_lt _ _) h
        rw [← hn, gt_iff_lt, Fintype.card_pos_iff]
        

Proof state:
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
h : ↑(k % n) = 0
⊢ Nonempty R

Next tactic:
exact ⟨0⟩
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      constructor
      · intro h
        rw [← Nat.mod_add_div k n, Nat.cast_add, Nat.cast_mul, H, zero_mul,
          add_zero] at h
        rw [Nat.dvd_iff_mod_eq_zero]
        apply hR _ (Nat.mod_lt _ _) h
        rw [← hn, gt_iff_lt, Fintype.card_pos_iff]
        exact ⟨0⟩
      · 

Proof state:
case mpr
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
⊢ n ∣ k → ↑k = 0

Next tactic:
rintro ⟨k, rfl⟩
theorem charP_of_ne_zero (hn : Fintype.card R = n) (hR : ∀ i < n, (i : R) = 0 → i = 0) :
    CharP R n :=
  { cast_eq_zero_iff' := by
      have H : (n : R) = 0 := by rw [← hn, CharP.cast_card_eq_zero]
      intro k
      constructor
      · intro h
        rw [← Nat.mod_add_div k n, Nat.cast_add, Nat.cast_mul, H, zero_mul,
          add_zero] at h
        rw [Nat.dvd_iff_mod_eq_zero]
        apply hR _ (Nat.mod_lt _ _) h
        rw [← hn, gt_iff_lt, Fintype.card_pos_iff]
        exact ⟨0⟩
      · rintro ⟨k, rfl⟩
        

Proof state:
case mpr.intro
R : Type u_1
inst✝¹ : NonAssocRing R
inst✝ : Fintype R
n : ℕ
hn : Fintype.card R = n
hR : ∀ i < n, ↑i = 0 → i = 0
H : ↑n = 0
k : ℕ
⊢ ↑(n * k) = 0

Next tactic:
rw [Nat.cast_mul, H, zero_mul]
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  

Proof state:
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n✝ : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
hn : Fintype.card R = p ^ n
hR : ∀ i ≤ n, ↑p ^ i = 0 → i = n
⊢ CharP R (p ^ n)

Next tactic:
obtain ⟨c, hc⟩ := CharP.exists R
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  obtain ⟨c, hc⟩ := CharP.exists R
  

Proof state:
case intro
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n✝ : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
hn : Fintype.card R = p ^ n
hR : ∀ i ≤ n, ↑p ^ i = 0 → i = n
c : ℕ
hc : CharP R c
⊢ CharP R (p ^ n)

Next tactic:
have hcpn : c ∣ p ^ n := by rw [← CharP.cast_eq_zero_iff R c, ← hn, CharP.cast_card_eq_zero]
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  obtain ⟨c, hc⟩ := CharP.exists R
  have hcpn : c ∣ p ^ n := by 

Proof state:
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n✝ : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
hn : Fintype.card R = p ^ n
hR : ∀ i ≤ n, ↑p ^ i = 0 → i = n
c : ℕ
hc : CharP R c
⊢ c ∣ p ^ n

Next tactic:
rw [← CharP.cast_eq_zero_iff R c, ← hn, CharP.cast_card_eq_zero]
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  obtain ⟨c, hc⟩ := CharP.exists R
  have hcpn : c ∣ p ^ n := by rw [← CharP.cast_eq_zero_iff R c, ← hn, CharP.cast_card_eq_zero]
  

Proof state:
case intro
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n✝ : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
hn : Fintype.card R = p ^ n
hR : ∀ i ≤ n, ↑p ^ i = 0 → i = n
c : ℕ
hc : CharP R c
hcpn : c ∣ p ^ n
⊢ CharP R (p ^ n)

Next tactic:
obtain ⟨i, hi, hc⟩ : ∃ i ≤ n, c = p ^ i := by rwa [Nat.dvd_prime_pow hp.1] at hcpn
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  obtain ⟨c, hc⟩ := CharP.exists R
  have hcpn : c ∣ p ^ n := by rw [← CharP.cast_eq_zero_iff R c, ← hn, CharP.cast_card_eq_zero]
  obtain ⟨i, hi, hc⟩ : ∃ i ≤ n, c = p ^ i := by 

Proof state:
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n✝ : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
hn : Fintype.card R = p ^ n
hR : ∀ i ≤ n, ↑p ^ i = 0 → i = n
c : ℕ
hc : CharP R c
hcpn : c ∣ p ^ n
⊢ ∃ i ≤ n, c = p ^ i

Next tactic:
rwa [Nat.dvd_prime_pow hp.1] at hcpn
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  obtain ⟨c, hc⟩ := CharP.exists R
  have hcpn : c ∣ p ^ n := by rw [← CharP.cast_eq_zero_iff R c, ← hn, CharP.cast_card_eq_zero]
  obtain ⟨i, hi, hc⟩ : ∃ i ≤ n, c = p ^ i := by rwa [Nat.dvd_prime_pow hp.1] at hcpn
  

Proof state:
case intro.intro.intro
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n✝ : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
hn : Fintype.card R = p ^ n
hR : ∀ i ≤ n, ↑p ^ i = 0 → i = n
c : ℕ
hc✝ : CharP R c
hcpn : c ∣ p ^ n
i : ℕ
hi : i ≤ n
hc : c = p ^ i
⊢ CharP R (p ^ n)

Next tactic:
obtain rfl : i = n := by
    apply hR i hi
    rw [← Nat.cast_pow, ← hc, CharP.cast_eq_zero]
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  obtain ⟨c, hc⟩ := CharP.exists R
  have hcpn : c ∣ p ^ n := by rw [← CharP.cast_eq_zero_iff R c, ← hn, CharP.cast_card_eq_zero]
  obtain ⟨i, hi, hc⟩ : ∃ i ≤ n, c = p ^ i := by rwa [Nat.dvd_prime_pow hp.1] at hcpn
  obtain rfl : i = n := by
    

Proof state:
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n✝ : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
hn : Fintype.card R = p ^ n
hR : ∀ i ≤ n, ↑p ^ i = 0 → i = n
c : ℕ
hc✝ : CharP R c
hcpn : c ∣ p ^ n
i : ℕ
hi : i ≤ n
hc : c = p ^ i
⊢ i = n

Next tactic:
apply hR i hi
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  obtain ⟨c, hc⟩ := CharP.exists R
  have hcpn : c ∣ p ^ n := by rw [← CharP.cast_eq_zero_iff R c, ← hn, CharP.cast_card_eq_zero]
  obtain ⟨i, hi, hc⟩ : ∃ i ≤ n, c = p ^ i := by rwa [Nat.dvd_prime_pow hp.1] at hcpn
  obtain rfl : i = n := by
    apply hR i hi
    

Proof state:
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n✝ : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
hn : Fintype.card R = p ^ n
hR : ∀ i ≤ n, ↑p ^ i = 0 → i = n
c : ℕ
hc✝ : CharP R c
hcpn : c ∣ p ^ n
i : ℕ
hi : i ≤ n
hc : c = p ^ i
⊢ ↑p ^ i = 0

Next tactic:
rw [← Nat.cast_pow, ← hc, CharP.cast_eq_zero]
theorem charP_of_prime_pow_injective (R) [Ring R] [Fintype R] (p : ℕ) [hp : Fact p.Prime] (n : ℕ)
    (hn : Fintype.card R = p ^ n) (hR : ∀ i ≤ n, (p : R) ^ i = 0 → i = n) : CharP R (p ^ n) := by
  obtain ⟨c, hc⟩ := CharP.exists R
  have hcpn : c ∣ p ^ n := by rw [← CharP.cast_eq_zero_iff R c, ← hn, CharP.cast_card_eq_zero]
  obtain ⟨i, hi, hc⟩ : ∃ i ≤ n, c = p ^ i := by rwa [Nat.dvd_prime_pow hp.1] at hcpn
  obtain rfl : i = n := by
    apply hR i hi
    rw [← Nat.cast_pow, ← hc, CharP.cast_eq_zero]
  

Proof state:
case intro.intro.intro
R✝ : Type u_1
inst✝³ : NonAssocRing R✝
inst✝² : Fintype R✝
n : ℕ
R : Type u_2
inst✝¹ : Ring R
inst✝ : Fintype R
p : ℕ
hp : Fact (Nat.Prime p)
c : ℕ
hc✝ : CharP R c
i : ℕ
hc : c = p ^ i
hn : Fintype.card R = p ^ i
hR : ∀ i_1 ≤ i, ↑p ^ i_1 = 0 → i_1 = i
hcpn : c ∣ p ^ i
hi : i ≤ i
⊢ CharP R (p ^ i)

Next tactic:
rwa [← hc]
/-- The characteristic of the product of rings is the least common multiple of the
characteristics of the two rings. -/
instance Nat.lcm.charP [CharP S q] : CharP (R × S) (Nat.lcm p q) where
  cast_eq_zero_iff' := by
    

Proof state:
R : Type u_1
S : Type v
inst✝³ : AddMonoidWithOne R
inst✝² : AddMonoidWithOne S
p q : ℕ
inst✝¹ : CharP R p
inst✝ : CharP S q
⊢ ∀ (x : ℕ), ↑x = 0 ↔ lcm p q ∣ x

Next tactic:
simp [Prod.ext_iff, CharP.cast_eq_zero_iff R p, CharP.cast_eq_zero_iff S q, Nat.lcm_dvd_iff]
/-- The characteristic of the product of two rings of the same characteristic
  is the same as the characteristic of the rings -/
instance Prod.charP [CharP S p] : CharP (R × S) p := by
  

Proof state:
R : Type u_1
S : Type v
inst✝³ : AddMonoidWithOne R
inst✝² : AddMonoidWithOne S
p q : ℕ
inst✝¹ : CharP R p
inst✝ : CharP S p
⊢ CharP (R × S) p

Next tactic:
convert Nat.lcm.charP R S p p
/-- The characteristic of the product of two rings of the same characteristic
  is the same as the characteristic of the rings -/
instance Prod.charP [CharP S p] : CharP (R × S) p := by
  convert Nat.lcm.charP R S p p; 

Proof state:
case h.e'_3
R : Type u_1
S : Type v
inst✝³ : AddMonoidWithOne R
inst✝² : AddMonoidWithOne S
p q : ℕ
inst✝¹ : CharP R p
inst✝ : CharP S p
⊢ p = Nat.lcm p p

Next tactic:
simp
/-- If two integers from `{0, 1, -1}` result in equal elements in a ring `R`
that is nontrivial and of characteristic not `2`, then they are equal. -/
theorem Int.cast_injOn_of_ringChar_ne_two {R : Type*} [NonAssocRing R] [Nontrivial R]
    (hR : ringChar R ≠ 2) : ({0, 1, -1} : Set ℤ).InjOn ((↑) : ℤ → R) := by
  

Proof state:
R✝ : Type u_1
R : Type u_2
inst✝¹ : NonAssocRing R
inst✝ : Nontrivial R
hR : ringChar R ≠ 2
⊢ Set.InjOn Int.cast {0, 1, -1}

Next tactic:
rintro _ (rfl | rfl | rfl) _ (rfl | rfl | rfl) h
/-- If two integers from `{0, 1, -1}` result in equal elements in a ring `R`
that is nontrivial and of characteristic not `2`, then they are equal. -/
theorem Int.cast_injOn_of_ringChar_ne_two {R : Type*} [NonAssocRing R] [Nontrivial R]
    (hR : ringChar R ≠ 2) : ({0, 1, -1} : Set ℤ).InjOn ((↑) : ℤ → R) := by
  rintro _ (rfl | rfl | rfl) _ (rfl | rfl | rfl) h <;>
  

Proof state:
case inl.inl
R✝ : Type u_1
R : Type u_2
inst✝¹ : NonAssocRing R
inst✝ : Nontrivial R
hR : ringChar R ≠ 2
h : ↑0 = ↑0
⊢ 0 = 0

Next tactic:
simp only
    [cast_neg, cast_one, cast_zero, neg_eq_zero, one_ne_zero, zero_ne_one, zero_eq_neg] at h ⊢
/-- If two integers from `{0, 1, -1}` result in equal elements in a ring `R`
that is nontrivial and of characteristic not `2`, then they are equal. -/
theorem Int.cast_injOn_of_ringChar_ne_two {R : Type*} [NonAssocRing R] [Nontrivial R]
    (hR : ringChar R ≠ 2) : ({0, 1, -1} : Set ℤ).InjOn ((↑) : ℤ → R) := by
  rintro _ (rfl | rfl | rfl) _ (rfl | rfl | rfl) h <;>
  

Proof state:
case inl.inr.inl
R✝ : Type u_1
R : Type u_2
inst✝¹ : NonAssocRing R
inst✝ : Nontrivial R
hR : ringChar R ≠ 2
h : ↑0 = ↑1
⊢ 0 = 1

Next tactic:
simp only
    [cast_neg, cast_one, cast_zero, neg_eq_zero, one_ne_zero, zero_ne_one, zero_eq_neg] at h ⊢
/-- If two integers from `{0, 1, -1}` result in equal elements in a ring `R`
that is nontrivial and of characteristic not `2`, then they are equal. -/
theorem Int.cast_injOn_of_ringChar_ne_two {R : Type*} [NonAssocRing R] [Nontrivial R]
    (hR : ringChar R ≠ 2) : ({0, 1, -1} : Set ℤ).InjOn ((↑) : ℤ → R) := by
  rintro _ (rfl | rfl | rfl) _ (rfl | rfl | rfl) h <;>
  

Proof state:
case inl.inr.inr
R✝ : Type u_1
R : Type u_2
inst✝¹ : NonAssocRing R
inst✝ : Nontrivial R
hR : ringChar R ≠ 2
h : ↑0 = ↑(-1)
⊢ 0 = -1

Next tactic:
simp only
    [cast_neg, cast_one, cast_zero, neg_eq_zero, one_ne_zero, zero_ne_one, zero_eq_neg] at h ⊢
/-- If two integers from `{0, 1, -1}` result in equal elements in a ring `R`
that is nontrivial and of characteristic not `2`, then they are equal. -/
theorem Int.cast_injOn_of_ringChar_ne_two {R : Type*} [NonAssocRing R] [Nontrivial R]
    (hR : ringChar R ≠ 2) : ({0, 1, -1} : Set ℤ).InjOn ((↑) : ℤ → R) := by
  rintro _ (rfl | rfl | rfl) _ (rfl | rfl | rfl) h <;>
  

Proof state:
case inr.inl.inl
R✝ : Type u_1
R : Type u_2
inst✝¹ : NonAssocRing R
inst✝ : Nontrivial R
hR : ringChar R ≠ 2
h : ↑1 = ↑0
⊢ 1 = 0

Next tactic:
simp only
    [cast_neg, cast_one, cast_zero, neg_eq_zero, one_ne_zero, zero_ne_one, zero_eq_neg] at h ⊢