l3lab/ntp-mathlib huggingface dataset:
/-- The coercions are respectively `Nat.cast` and `ZMod.cast`. -/
@[simp]
theorem nat_cast_comp_val [NeZero n] : ((↑) : ℕ → R) ∘ (val : ZMod n → ℕ) = (↑) := by
  cases n
  · 

Proof state:
case zero
R : Type u_1
inst✝¹ : Ring R
inst✝ : NeZero Nat.zero
⊢ Nat.cast ∘ val = cast

Next tactic:
cases NeZero.ne 0 rfl
/-- The coercions are respectively `Nat.cast` and `ZMod.cast`. -/
@[simp]
theorem nat_cast_comp_val [NeZero n] : ((↑) : ℕ → R) ∘ (val : ZMod n → ℕ) = (↑) := by
  cases n
  · cases NeZero.ne 0 rfl
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
n✝ : ℕ
inst✝ : NeZero (Nat.succ n✝)
⊢ Nat.cast ∘ val = cast

Next tactic:
rfl
/-- The coercions are respectively `Int.cast`, `ZMod.cast`, and `ZMod.cast`. -/
@[simp]
theorem int_cast_comp_cast : ((↑) : ℤ → R) ∘ ((↑) : ZMod n → ℤ) = (↑) := by
  

Proof state:
n : ℕ
R : Type u_1
inst✝ : Ring R
⊢ Int.cast ∘ cast = cast

Next tactic:
cases n
/-- The coercions are respectively `Int.cast`, `ZMod.cast`, and `ZMod.cast`. -/
@[simp]
theorem int_cast_comp_cast : ((↑) : ℤ → R) ∘ ((↑) : ZMod n → ℤ) = (↑) := by
  cases n
  · 

Proof state:
case zero
R : Type u_1
inst✝ : Ring R
⊢ Int.cast ∘ cast = cast

Next tactic:
exact congr_arg (Int.cast ∘ ·) ZMod.cast_id'
/-- The coercions are respectively `Int.cast`, `ZMod.cast`, and `ZMod.cast`. -/
@[simp]
theorem int_cast_comp_cast : ((↑) : ℤ → R) ∘ ((↑) : ZMod n → ℤ) = (↑) := by
  cases n
  · exact congr_arg (Int.cast ∘ ·) ZMod.cast_id'
  · 

Proof state:
case succ
R : Type u_1
inst✝ : Ring R
n✝ : ℕ
⊢ Int.cast ∘ cast = cast

Next tactic:
ext
/-- The coercions are respectively `Int.cast`, `ZMod.cast`, and `ZMod.cast`. -/
@[simp]
theorem int_cast_comp_cast : ((↑) : ℤ → R) ∘ ((↑) : ZMod n → ℤ) = (↑) := by
  cases n
  · exact congr_arg (Int.cast ∘ ·) ZMod.cast_id'
  · ext
    

Proof state:
case succ.h
R : Type u_1
inst✝ : Ring R
n✝ : ℕ
x✝ : ZMod (Nat.succ n✝)
⊢ (Int.cast ∘ cast) x✝ = ↑x✝

Next tactic:
simp [ZMod, ZMod.cast]
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  

Proof state:
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : ZMod n
⊢ ↑(a + b) = if ↑n ≤ ↑a + ↑b then ↑a + ↑b - ↑n else ↑a + ↑b

Next tactic:
cases' n with n
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · 

Proof state:
case zero
n : ℕ
R : Type u_1
inst✝ : Ring R
a b : ZMod Nat.zero
⊢ ↑(a + b) = if ↑Nat.zero ≤ ↑a + ↑b then ↑a + ↑b - ↑Nat.zero else ↑a + ↑b

Next tactic:
simp
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; 

Proof state:
case zero
n : ℕ
R : Type u_1
inst✝ : Ring R
a b : ZMod Nat.zero
⊢ ↑(a + b) = ↑a + ↑b

Next tactic:
rfl
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; rfl
  

Proof state:
case succ
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : ZMod (Nat.succ n)
⊢ ↑(a + b) = if ↑(Nat.succ n) ≤ ↑a + ↑b then ↑a + ↑b - ↑(Nat.succ n) else ↑a + ↑b

Next tactic:
change Fin (n + 1) at a b
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; rfl
  change Fin (n + 1) at a b
  

Proof state:
case succ
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : Fin (n + 1)
⊢ ↑(a + b) = if ↑(Nat.succ n) ≤ ↑a + ↑b then ↑a + ↑b - ↑(Nat.succ n) else ↑a + ↑b

Next tactic:
change ((((a + b) : Fin (n + 1)) : ℕ) : ℤ) = if ((n + 1 : ℕ) : ℤ) ≤ (a : ℕ) + b then _ else _
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; rfl
  change Fin (n + 1) at a b
  change ((((a + b) : Fin (n + 1)) : ℕ) : ℤ) = if ((n + 1 : ℕ) : ℤ) ≤ (a : ℕ) + b then _ else _
  

Proof state:
case succ
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : Fin (n + 1)
⊢ ↑↑(a + b) = if ↑(n + 1) ≤ ↑↑a + ↑↑b then ↑a + ↑b - ↑(Nat.succ n) else ↑a + ↑b

Next tactic:
simp only [Fin.val_add_eq_ite, Int.ofNat_succ, Int.ofNat_le]
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; rfl
  change Fin (n + 1) at a b
  change ((((a + b) : Fin (n + 1)) : ℕ) : ℤ) = if ((n + 1 : ℕ) : ℤ) ≤ (a : ℕ) + b then _ else _
  simp only [Fin.val_add_eq_ite, Int.ofNat_succ, Int.ofNat_le]
  

Proof state:
case succ
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : Fin (n + 1)
⊢ ↑(if n + 1 ≤ ↑a + ↑b then ↑a + ↑b - (n + 1) else ↑a + ↑b) = if ↑n + 1 ≤ ↑↑a + ↑↑b then ↑a + ↑b - (↑n + 1) else ↑a + ↑b

Next tactic:
norm_cast
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; rfl
  change Fin (n + 1) at a b
  change ((((a + b) : Fin (n + 1)) : ℕ) : ℤ) = if ((n + 1 : ℕ) : ℤ) ≤ (a : ℕ) + b then _ else _
  simp only [Fin.val_add_eq_ite, Int.ofNat_succ, Int.ofNat_le]
  norm_cast
  

Proof state:
case succ
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : Fin (n + 1)
⊢ ↑(if n + 1 ≤ ↑a + ↑b then ↑a + ↑b - (n + 1) else ↑a + ↑b) = if n + 1 ≤ ↑a + ↑b then ↑a + ↑b - ↑(n + 1) else ↑a + ↑b

Next tactic:
split_ifs with h
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; rfl
  change Fin (n + 1) at a b
  change ((((a + b) : Fin (n + 1)) : ℕ) : ℤ) = if ((n + 1 : ℕ) : ℤ) ≤ (a : ℕ) + b then _ else _
  simp only [Fin.val_add_eq_ite, Int.ofNat_succ, Int.ofNat_le]
  norm_cast
  split_ifs with h
  · 

Proof state:
case pos
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : Fin (n + 1)
h : n + 1 ≤ ↑a + ↑b
⊢ ↑(↑a + ↑b - (n + 1)) = ↑a + ↑b - ↑(n + 1)

Next tactic:
rw [Nat.cast_sub h]
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; rfl
  change Fin (n + 1) at a b
  change ((((a + b) : Fin (n + 1)) : ℕ) : ℤ) = if ((n + 1 : ℕ) : ℤ) ≤ (a : ℕ) + b then _ else _
  simp only [Fin.val_add_eq_ite, Int.ofNat_succ, Int.ofNat_le]
  norm_cast
  split_ifs with h
  · rw [Nat.cast_sub h]
    

Proof state:
case pos
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : Fin (n + 1)
h : n + 1 ≤ ↑a + ↑b
⊢ ↑(↑a + ↑b) - ↑(n + 1) = ↑a + ↑b - ↑(n + 1)

Next tactic:
congr
theorem coe_add_eq_ite {n : ℕ} (a b : ZMod n) :
    (↑(a + b) : ℤ) = if (n : ℤ) ≤ a + b then (a : ℤ) + b - n else a + b := by
  cases' n with n
  · simp; rfl
  change Fin (n + 1) at a b
  change ((((a + b) : Fin (n + 1)) : ℕ) : ℤ) = if ((n + 1 : ℕ) : ℤ) ≤ (a : ℕ) + b then _ else _
  simp only [Fin.val_add_eq_ite, Int.ofNat_succ, Int.ofNat_le]
  norm_cast
  split_ifs with h
  · rw [Nat.cast_sub h]
    congr
  · 

Proof state:
case neg
n✝ : ℕ
R : Type u_1
inst✝ : Ring R
n : ℕ
a b : Fin (n + 1)
h : ¬n + 1 ≤ ↑a + ↑b
⊢ ↑(↑a + ↑b) = ↑a + ↑b

Next tactic:
rfl
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  

Proof state:
n : ℕ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
h : m ∣ n
⊢ ↑1 = 1

Next tactic:
cases' n with n
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · 

Proof state:
case zero
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
h : m ∣ Nat.zero
⊢ ↑1 = 1

Next tactic:
exact Int.cast_one
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · exact Int.cast_one
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n : ℕ
h : m ∣ Nat.succ n
⊢ ↑1 = 1

Next tactic:
show ((1 % (n + 1) : ℕ) : R) = 1
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · exact Int.cast_one
  show ((1 % (n + 1) : ℕ) : R) = 1
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n : ℕ
h : m ∣ Nat.succ n
⊢ ↑(1 % (n + 1)) = 1

Next tactic:
cases n
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · exact Int.cast_one
  show ((1 % (n + 1) : ℕ) : R) = 1
  cases n;
  · 

Proof state:
case succ.zero
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
h : m ∣ Nat.succ Nat.zero
⊢ ↑(1 % (Nat.zero + 1)) = 1

Next tactic:
rw [Nat.dvd_one] at h
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · exact Int.cast_one
  show ((1 % (n + 1) : ℕ) : R) = 1
  cases n;
  · rw [Nat.dvd_one] at h
    

Proof state:
case succ.zero
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
h : m = 1
⊢ ↑(1 % (Nat.zero + 1)) = 1

Next tactic:
subst m
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · exact Int.cast_one
  show ((1 % (n + 1) : ℕ) : R) = 1
  cases n;
  · rw [Nat.dvd_one] at h
    subst m
    

Proof state:
case succ.zero
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R 1
⊢ ↑(1 % (Nat.zero + 1)) = 1

Next tactic:
apply Subsingleton.elim
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · exact Int.cast_one
  show ((1 % (n + 1) : ℕ) : R) = 1
  cases n;
  · rw [Nat.dvd_one] at h
    subst m
    apply Subsingleton.elim
  

Proof state:
case succ.succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ (Nat.succ n✝)
⊢ ↑(1 % (Nat.succ n✝ + 1)) = 1

Next tactic:
rw [Nat.mod_eq_of_lt]
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · exact Int.cast_one
  show ((1 % (n + 1) : ℕ) : R) = 1
  cases n;
  · rw [Nat.dvd_one] at h
    subst m
    apply Subsingleton.elim
  rw [Nat.mod_eq_of_lt]
  · 

Proof state:
case succ.succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ (Nat.succ n✝)
⊢ ↑1 = 1

Next tactic:
exact Nat.cast_one
@[simp]
theorem cast_one (h : m ∣ n) : ((1 : ZMod n) : R) = 1 := by
  cases' n with n
  · exact Int.cast_one
  show ((1 % (n + 1) : ℕ) : R) = 1
  cases n;
  · rw [Nat.dvd_one] at h
    subst m
    apply Subsingleton.elim
  rw [Nat.mod_eq_of_lt]
  · exact Nat.cast_one
  

Proof state:
case succ.succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ (Nat.succ n✝)
⊢ 1 < Nat.succ n✝ + 1

Next tactic:
exact Nat.lt_of_sub_eq_succ rfl
theorem cast_add (h : m ∣ n) (a b : ZMod n) : ((a + b : ZMod n) : R) = a + b := by
  

Proof state:
n : ℕ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
h : m ∣ n
a b : ZMod n
⊢ ↑(a + b) = ↑a + ↑b

Next tactic:
cases n
theorem cast_add (h : m ∣ n) (a b : ZMod n) : ((a + b : ZMod n) : R) = a + b := by
  cases n
  · 

Proof state:
case zero
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
h : m ∣ Nat.zero
a b : ZMod Nat.zero
⊢ ↑(a + b) = ↑a + ↑b

Next tactic:
apply Int.cast_add
theorem cast_add (h : m ∣ n) (a b : ZMod n) : ((a + b : ZMod n) : R) = a + b := by
  cases n
  · apply Int.cast_add
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ n✝
a b : ZMod (Nat.succ n✝)
⊢ ↑(a + b) = ↑a + ↑b

Next tactic:
symm
theorem cast_add (h : m ∣ n) (a b : ZMod n) : ((a + b : ZMod n) : R) = a + b := by
  cases n
  · apply Int.cast_add
  symm
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ n✝
a b : ZMod (Nat.succ n✝)
⊢ ↑a + ↑b = ↑(a + b)

Next tactic:
dsimp [ZMod, ZMod.cast]
theorem cast_add (h : m ∣ n) (a b : ZMod n) : ((a + b : ZMod n) : R) = a + b := by
  cases n
  · apply Int.cast_add
  symm
  dsimp [ZMod, ZMod.cast]
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ n✝
a b : ZMod (Nat.succ n✝)
⊢ ↑(val a) + ↑(val b) = ↑(val (a + b))

Next tactic:
erw [← Nat.cast_add, ← sub_eq_zero, ← Nat.cast_sub (Nat.mod_le _ _),
    @CharP.cast_eq_zero_iff R _ m]
theorem cast_add (h : m ∣ n) (a b : ZMod n) : ((a + b : ZMod n) : R) = a + b := by
  cases n
  · apply Int.cast_add
  symm
  dsimp [ZMod, ZMod.cast]
  erw [← Nat.cast_add, ← sub_eq_zero, ← Nat.cast_sub (Nat.mod_le _ _),
    @CharP.cast_eq_zero_iff R _ m]
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ n✝
a b : ZMod (Nat.succ n✝)
⊢ m ∣ val a + val b - (val a + val b) % Nat.succ n✝

Next tactic:
exact h.trans (Nat.dvd_sub_mod _)
theorem cast_mul (h : m ∣ n) (a b : ZMod n) : ((a * b : ZMod n) : R) = a * b := by
  

Proof state:
n : ℕ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
h : m ∣ n
a b : ZMod n
⊢ ↑(a * b) = ↑a * ↑b

Next tactic:
cases n
theorem cast_mul (h : m ∣ n) (a b : ZMod n) : ((a * b : ZMod n) : R) = a * b := by
  cases n
  · 

Proof state:
case zero
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
h : m ∣ Nat.zero
a b : ZMod Nat.zero
⊢ ↑(a * b) = ↑a * ↑b

Next tactic:
apply Int.cast_mul
theorem cast_mul (h : m ∣ n) (a b : ZMod n) : ((a * b : ZMod n) : R) = a * b := by
  cases n
  · apply Int.cast_mul
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ n✝
a b : ZMod (Nat.succ n✝)
⊢ ↑(a * b) = ↑a * ↑b

Next tactic:
symm
theorem cast_mul (h : m ∣ n) (a b : ZMod n) : ((a * b : ZMod n) : R) = a * b := by
  cases n
  · apply Int.cast_mul
  symm
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ n✝
a b : ZMod (Nat.succ n✝)
⊢ ↑a * ↑b = ↑(a * b)

Next tactic:
dsimp [ZMod, ZMod.cast]
theorem cast_mul (h : m ∣ n) (a b : ZMod n) : ((a * b : ZMod n) : R) = a * b := by
  cases n
  · apply Int.cast_mul
  symm
  dsimp [ZMod, ZMod.cast]
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ n✝
a b : ZMod (Nat.succ n✝)
⊢ ↑(val a) * ↑(val b) = ↑(val (a * b))

Next tactic:
erw [← Nat.cast_mul, ← sub_eq_zero, ← Nat.cast_sub (Nat.mod_le _ _),
    @CharP.cast_eq_zero_iff R _ m]
theorem cast_mul (h : m ∣ n) (a b : ZMod n) : ((a * b : ZMod n) : R) = a * b := by
  cases n
  · apply Int.cast_mul
  symm
  dsimp [ZMod, ZMod.cast]
  erw [← Nat.cast_mul, ← sub_eq_zero, ← Nat.cast_sub (Nat.mod_le _ _),
    @CharP.cast_eq_zero_iff R _ m]
  

Proof state:
case succ
R : Type u_1
inst✝¹ : Ring R
m : ℕ
inst✝ : CharP R m
n✝ : ℕ
h : m ∣ Nat.succ n✝
a b : ZMod (Nat.succ n✝)
⊢ m ∣ val a * val b - val a * val b % Nat.succ n✝

Next tactic:
exact h.trans (Nat.dvd_sub_mod _)
theorem castHom_injective : Function.Injective (ZMod.castHom (dvd_refl n) R) := by
  

Proof state:
n : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n
⊢ Injective ⇑(castHom (_ : n ∣ n) R)

Next tactic:
rw [injective_iff_map_eq_zero]
theorem castHom_injective : Function.Injective (ZMod.castHom (dvd_refl n) R) := by
  rw [injective_iff_map_eq_zero]
  

Proof state:
n : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n
⊢ ∀ (a : ZMod n), (castHom (_ : n ∣ n) R) a = 0 → a = 0

Next tactic:
intro x
theorem castHom_injective : Function.Injective (ZMod.castHom (dvd_refl n) R) := by
  rw [injective_iff_map_eq_zero]
  intro x
  

Proof state:
n : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n
x : ZMod n
⊢ (castHom (_ : n ∣ n) R) x = 0 → x = 0

Next tactic:
obtain ⟨k, rfl⟩ := ZMod.int_cast_surjective x
theorem castHom_injective : Function.Injective (ZMod.castHom (dvd_refl n) R) := by
  rw [injective_iff_map_eq_zero]
  intro x
  obtain ⟨k, rfl⟩ := ZMod.int_cast_surjective x
  

Proof state:
case intro
n : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n
k : ℤ
⊢ (castHom (_ : n ∣ n) R) ↑k = 0 → ↑k = 0

Next tactic:
rw [map_intCast, CharP.int_cast_eq_zero_iff R n, CharP.int_cast_eq_zero_iff (ZMod n) n]
theorem castHom_injective : Function.Injective (ZMod.castHom (dvd_refl n) R) := by
  rw [injective_iff_map_eq_zero]
  intro x
  obtain ⟨k, rfl⟩ := ZMod.int_cast_surjective x
  rw [map_intCast, CharP.int_cast_eq_zero_iff R n, CharP.int_cast_eq_zero_iff (ZMod n) n]
  

Proof state:
case intro
n : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n
k : ℤ
⊢ ↑n ∣ k → ↑n ∣ k

Next tactic:
exact id
theorem castHom_bijective [Fintype R] (h : Fintype.card R = n) :
    Function.Bijective (ZMod.castHom (dvd_refl n) R) := by
  

Proof state:
n : ℕ
R : Type u_1
inst✝² : Ring R
inst✝¹ : CharP R n
inst✝ : Fintype R
h : Fintype.card R = n
⊢ Bijective ⇑(castHom (_ : n ∣ n) R)

Next tactic:
haveI : NeZero n :=
    ⟨by
      intro hn
      rw [hn] at h
      exact (Fintype.card_eq_zero_iff.mp h).elim' 0⟩
theorem castHom_bijective [Fintype R] (h : Fintype.card R = n) :
    Function.Bijective (ZMod.castHom (dvd_refl n) R) := by
  haveI : NeZero n :=
    ⟨by
      

Proof state:
n : ℕ
R : Type u_1
inst✝² : Ring R
inst✝¹ : CharP R n
inst✝ : Fintype R
h : Fintype.card R = n
⊢ n ≠ 0

Next tactic:
intro hn
theorem castHom_bijective [Fintype R] (h : Fintype.card R = n) :
    Function.Bijective (ZMod.castHom (dvd_refl n) R) := by
  haveI : NeZero n :=
    ⟨by
      intro hn
      

Proof state:
n : ℕ
R : Type u_1
inst✝² : Ring R
inst✝¹ : CharP R n
inst✝ : Fintype R
h : Fintype.card R = n
hn : n = 0
⊢ False

Next tactic:
rw [hn] at h
theorem castHom_bijective [Fintype R] (h : Fintype.card R = n) :
    Function.Bijective (ZMod.castHom (dvd_refl n) R) := by
  haveI : NeZero n :=
    ⟨by
      intro hn
      rw [hn] at h
      

Proof state:
n : ℕ
R : Type u_1
inst✝² : Ring R
inst✝¹ : CharP R n
inst✝ : Fintype R
h : Fintype.card R = 0
hn : n = 0
⊢ False

Next tactic:
exact (Fintype.card_eq_zero_iff.mp h).elim' 0
theorem castHom_bijective [Fintype R] (h : Fintype.card R = n) :
    Function.Bijective (ZMod.castHom (dvd_refl n) R) := by
  haveI : NeZero n :=
    ⟨by
      intro hn
      rw [hn] at h
      exact (Fintype.card_eq_zero_iff.mp h).elim' 0⟩
  

Proof state:
n : ℕ
R : Type u_1
inst✝² : Ring R
inst✝¹ : CharP R n
inst✝ : Fintype R
h : Fintype.card R = n
this : NeZero n
⊢ Bijective ⇑(castHom (_ : n ∣ n) R)

Next tactic:
rw [Fintype.bijective_iff_injective_and_card, ZMod.card, h, eq_self_iff_true, and_true_iff]
theorem castHom_bijective [Fintype R] (h : Fintype.card R = n) :
    Function.Bijective (ZMod.castHom (dvd_refl n) R) := by
  haveI : NeZero n :=
    ⟨by
      intro hn
      rw [hn] at h
      exact (Fintype.card_eq_zero_iff.mp h).elim' 0⟩
  rw [Fintype.bijective_iff_injective_and_card, ZMod.card, h, eq_self_iff_true, and_true_iff]
  

Proof state:
n : ℕ
R : Type u_1
inst✝² : Ring R
inst✝¹ : CharP R n
inst✝ : Fintype R
h : Fintype.card R = n
this : NeZero n
⊢ Injective ⇑(castHom (_ : n ∣ n) R)

Next tactic:
apply ZMod.castHom_injective
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  

Proof state:
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
m n : ℕ
h : m = n
⊢ ZMod m ≃+* ZMod n

Next tactic:
cases' m with m
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> 

Proof state:
case zero
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
n : ℕ
h : Nat.zero = n
⊢ ZMod Nat.zero ≃+* ZMod n

Next tactic:
cases' n with n
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> 

Proof state:
case succ
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
n m : ℕ
h : Nat.succ m = n
⊢ ZMod (Nat.succ m) ≃+* ZMod n

Next tactic:
cases' n with n
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · 

Proof state:
case zero.zero
n : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n
h : Nat.zero = Nat.zero
⊢ ZMod Nat.zero ≃+* ZMod Nat.zero

Next tactic:
exact RingEquiv.refl _
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · exact RingEquiv.refl _
  · 

Proof state:
case zero.succ
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
n : ℕ
h : Nat.zero = Nat.succ n
⊢ ZMod Nat.zero ≃+* ZMod (Nat.succ n)

Next tactic:
exfalso
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · exact RingEquiv.refl _
  · exfalso
    

Proof state:
case zero.succ.h
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
n : ℕ
h : Nat.zero = Nat.succ n
⊢ False

Next tactic:
exact n.succ_ne_zero h.symm
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · exact RingEquiv.refl _
  · exfalso
    exact n.succ_ne_zero h.symm
  · 

Proof state:
case succ.zero
n : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n
m : ℕ
h : Nat.succ m = Nat.zero
⊢ ZMod (Nat.succ m) ≃+* ZMod Nat.zero

Next tactic:
exfalso
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · exact RingEquiv.refl _
  · exfalso
    exact n.succ_ne_zero h.symm
  · exfalso
    

Proof state:
case succ.zero.h
n : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n
m : ℕ
h : Nat.succ m = Nat.zero
⊢ False

Next tactic:
exact m.succ_ne_zero h
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · exact RingEquiv.refl _
  · exfalso
    exact n.succ_ne_zero h.symm
  · exfalso
    exact m.succ_ne_zero h
  · 

Proof state:
case succ.succ
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
m n : ℕ
h : Nat.succ m = Nat.succ n
⊢ ZMod (Nat.succ m) ≃+* ZMod (Nat.succ n)

Next tactic:
exact
      { Fin.castIso h with
        map_mul' := fun a b => by
          dsimp [ZMod]
          ext
          rw [Fin.coe_cast, Fin.coe_mul, Fin.coe_mul, Fin.coe_cast, Fin.coe_cast, ← h]
        map_add' := fun a b => by
          dsimp [ZMod]
          ext
          rw [Fin.coe_cast, Fin.val_add, Fin.val_add, Fin.coe_cast, Fin.coe_cast, ← h] }
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · exact RingEquiv.refl _
  · exfalso
    exact n.succ_ne_zero h.symm
  · exfalso
    exact m.succ_ne_zero h
  · exact
      { Fin.castIso h with
        map_mul' := fun a b => by
          

Proof state:
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
m n : ℕ
h : Nat.succ m = Nat.succ n
src✝ : Fin (Nat.succ m) ≃o Fin (Nat.succ n) := Fin.castIso h
a b : ZMod (Nat.succ m)
⊢ Equiv.toFun src✝.toEquiv (a * b) = Equiv.toFun src✝.toEquiv a * Equiv.toFun src✝.toEquiv b

Next tactic:
dsimp [ZMod]
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · exact RingEquiv.refl _
  · exfalso
    exact n.succ_ne_zero h.symm
  · exfalso
    exact m.succ_ne_zero h
  · exact
      { Fin.castIso h with
        map_mul' := fun a b => by
          dsimp [ZMod]
          

Proof state:
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
m n : ℕ
h : Nat.succ m = Nat.succ n
src✝ : Fin (Nat.succ m) ≃o Fin (Nat.succ n) := Fin.castIso h
a b : ZMod (Nat.succ m)
⊢ Fin.cast h (a * b) = Fin.cast h a * Fin.cast h b

Next tactic:
ext
/-- The identity between `ZMod m` and `ZMod n` when `m = n`, as a ring isomorphism. -/
def ringEquivCongr {m n : ℕ} (h : m = n) : ZMod m ≃+* ZMod n := by
  cases' m with m <;> cases' n with n
  · exact RingEquiv.refl _
  · exfalso
    exact n.succ_ne_zero h.symm
  · exfalso
    exact m.succ_ne_zero h
  · exact
      { Fin.castIso h with
        map_mul' := fun a b => by
          dsimp [ZMod]
          ext
          

Proof state:
case h
n✝ : ℕ
R : Type u_1
inst✝¹ : Ring R
inst✝ : CharP R n✝
m n : ℕ
h : Nat.succ m = Nat.succ n
src✝ : Fin (Nat.succ m) ≃o Fin (Nat.succ n) := Fin.castIso h
a b : ZMod (Nat.succ m)
⊢ ↑(Fin.cast h (a * b)) = ↑(Fin.cast h a * Fin.cast h b)

Next tactic:
rw [Fin.coe_cast, Fin.coe_mul, Fin.coe_mul, Fin.coe_cast, Fin.coe_cast, ← h]