l3lab/ntp-mathlib huggingface dataset:
/-- `toZModHom` is an auxiliary constructor for creating ring homs from `ℤ_[p]` to `ZMod v`.
-/
def toZModHom (v : ℕ) (f : ℤ_[p] → ℕ) (f_spec : ∀ x, x - f x ∈ (Ideal.span {↑v} : Ideal ℤ_[p]))
    (f_congr :
      ∀ (x : ℤ_[p]) (a b : ℕ),
        x - a ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) →
          x - b ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) → (a : ZMod v) = b) :
    ℤ_[p] →+* ZMod v where
  toFun x := f x
  map_zero' := by
    dsimp only
    rw [f_congr (0 : ℤ_[p]) _ 0, cast_zero]
    · exact f_spec _
    · simp only [sub_zero, cast_zero, Submodule.zero_mem]
  map_one' := by
    dsimp only
    rw [f_congr (1 : ℤ_[p]) _ 1, cast_one]
    · exact f_spec _
    · simp only [sub_self, cast_one, Submodule.zero_mem]
  map_add' := by
    

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
v : ℕ
f : ℤ_[p] → ℕ
f_spec : ∀ (x : ℤ_[p]), x - ↑(f x) ∈ Ideal.span {↑v}
f_congr : ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ Ideal.span {↑v} → x - ↑b ∈ Ideal.span {↑v} → ↑a = ↑b
⊢ ∀ (x y : ℤ_[p]),
    OneHom.toFun
        (↑{ toOneHom := { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) },
            map_mul' :=
              (_ :
                ∀ (x y : ℤ_[p]),
                  OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } (x * y) =
                    OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } x *
                      OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } y) })
        (x + y) =
      OneHom.toFun
          (↑{ toOneHom := { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) },
              map_mul' :=
                (_ :
                  ∀ (x y : ℤ_[p]),
                    OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } (x * y) =
                      OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } x *
                        OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } y) })
          x +
        OneHom.toFun
          (↑{ toOneHom := { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) },
              map_mul' :=
                (_ :
                  ∀ (x y : ℤ_[p]),
                    OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } (x * y) =
                      OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } x *
                        OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } y) })
          y

Next tactic:
intro x y
/-- `toZModHom` is an auxiliary constructor for creating ring homs from `ℤ_[p]` to `ZMod v`.
-/
def toZModHom (v : ℕ) (f : ℤ_[p] → ℕ) (f_spec : ∀ x, x - f x ∈ (Ideal.span {↑v} : Ideal ℤ_[p]))
    (f_congr :
      ∀ (x : ℤ_[p]) (a b : ℕ),
        x - a ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) →
          x - b ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) → (a : ZMod v) = b) :
    ℤ_[p] →+* ZMod v where
  toFun x := f x
  map_zero' := by
    dsimp only
    rw [f_congr (0 : ℤ_[p]) _ 0, cast_zero]
    · exact f_spec _
    · simp only [sub_zero, cast_zero, Submodule.zero_mem]
  map_one' := by
    dsimp only
    rw [f_congr (1 : ℤ_[p]) _ 1, cast_one]
    · exact f_spec _
    · simp only [sub_self, cast_one, Submodule.zero_mem]
  map_add' := by
    intro x y
    

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ : ℤ_[p]
v : ℕ
f : ℤ_[p] → ℕ
f_spec : ∀ (x : ℤ_[p]), x - ↑(f x) ∈ Ideal.span {↑v}
f_congr : ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ Ideal.span {↑v} → x - ↑b ∈ Ideal.span {↑v} → ↑a = ↑b
x y : ℤ_[p]
⊢ OneHom.toFun
      (↑{ toOneHom := { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) },
          map_mul' :=
            (_ :
              ∀ (x y : ℤ_[p]),
                OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } (x * y) =
                  OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } x *
                    OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } y) })
      (x + y) =
    OneHom.toFun
        (↑{ toOneHom := { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) },
            map_mul' :=
              (_ :
                ∀ (x y : ℤ_[p]),
                  OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } (x * y) =
                    OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } x *
                      OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } y) })
        x +
      OneHom.toFun
        (↑{ toOneHom := { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) },
            map_mul' :=
              (_ :
                ∀ (x y : ℤ_[p]),
                  OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } (x * y) =
                    OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } x *
                      OneHom.toFun { toFun := fun x => ↑(f x), map_one' := (_ : (fun x => ↑(f x)) 1 = 1) } y) })
        y

Next tactic:
dsimp only
/-- `toZModHom` is an auxiliary constructor for creating ring homs from `ℤ_[p]` to `ZMod v`.
-/
def toZModHom (v : ℕ) (f : ℤ_[p] → ℕ) (f_spec : ∀ x, x - f x ∈ (Ideal.span {↑v} : Ideal ℤ_[p]))
    (f_congr :
      ∀ (x : ℤ_[p]) (a b : ℕ),
        x - a ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) →
          x - b ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) → (a : ZMod v) = b) :
    ℤ_[p] →+* ZMod v where
  toFun x := f x
  map_zero' := by
    dsimp only
    rw [f_congr (0 : ℤ_[p]) _ 0, cast_zero]
    · exact f_spec _
    · simp only [sub_zero, cast_zero, Submodule.zero_mem]
  map_one' := by
    dsimp only
    rw [f_congr (1 : ℤ_[p]) _ 1, cast_one]
    · exact f_spec _
    · simp only [sub_self, cast_one, Submodule.zero_mem]
  map_add' := by
    intro x y
    dsimp only
    

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ : ℤ_[p]
v : ℕ
f : ℤ_[p] → ℕ
f_spec : ∀ (x : ℤ_[p]), x - ↑(f x) ∈ Ideal.span {↑v}
f_congr : ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ Ideal.span {↑v} → x - ↑b ∈ Ideal.span {↑v} → ↑a = ↑b
x y : ℤ_[p]
⊢ ↑(f (x + y)) = ↑(f x) + ↑(f y)

Next tactic:
rw [f_congr (x + y) _ (f x + f y), cast_add]
/-- `toZModHom` is an auxiliary constructor for creating ring homs from `ℤ_[p]` to `ZMod v`.
-/
def toZModHom (v : ℕ) (f : ℤ_[p] → ℕ) (f_spec : ∀ x, x - f x ∈ (Ideal.span {↑v} : Ideal ℤ_[p]))
    (f_congr :
      ∀ (x : ℤ_[p]) (a b : ℕ),
        x - a ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) →
          x - b ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) → (a : ZMod v) = b) :
    ℤ_[p] →+* ZMod v where
  toFun x := f x
  map_zero' := by
    dsimp only
    rw [f_congr (0 : ℤ_[p]) _ 0, cast_zero]
    · exact f_spec _
    · simp only [sub_zero, cast_zero, Submodule.zero_mem]
  map_one' := by
    dsimp only
    rw [f_congr (1 : ℤ_[p]) _ 1, cast_one]
    · exact f_spec _
    · simp only [sub_self, cast_one, Submodule.zero_mem]
  map_add' := by
    intro x y
    dsimp only
    rw [f_congr (x + y) _ (f x + f y), cast_add]
    · 

Proof state:
case a
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ : ℤ_[p]
v : ℕ
f : ℤ_[p] → ℕ
f_spec : ∀ (x : ℤ_[p]), x - ↑(f x) ∈ Ideal.span {↑v}
f_congr : ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ Ideal.span {↑v} → x - ↑b ∈ Ideal.span {↑v} → ↑a = ↑b
x y : ℤ_[p]
⊢ x + y - ↑(f (x + y)) ∈ Ideal.span {↑v}

Next tactic:
exact f_spec _
/-- `toZModHom` is an auxiliary constructor for creating ring homs from `ℤ_[p]` to `ZMod v`.
-/
def toZModHom (v : ℕ) (f : ℤ_[p] → ℕ) (f_spec : ∀ x, x - f x ∈ (Ideal.span {↑v} : Ideal ℤ_[p]))
    (f_congr :
      ∀ (x : ℤ_[p]) (a b : ℕ),
        x - a ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) →
          x - b ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) → (a : ZMod v) = b) :
    ℤ_[p] →+* ZMod v where
  toFun x := f x
  map_zero' := by
    dsimp only
    rw [f_congr (0 : ℤ_[p]) _ 0, cast_zero]
    · exact f_spec _
    · simp only [sub_zero, cast_zero, Submodule.zero_mem]
  map_one' := by
    dsimp only
    rw [f_congr (1 : ℤ_[p]) _ 1, cast_one]
    · exact f_spec _
    · simp only [sub_self, cast_one, Submodule.zero_mem]
  map_add' := by
    intro x y
    dsimp only
    rw [f_congr (x + y) _ (f x + f y), cast_add]
    · exact f_spec _
    · 

Proof state:
case a
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ : ℤ_[p]
v : ℕ
f : ℤ_[p] → ℕ
f_spec : ∀ (x : ℤ_[p]), x - ↑(f x) ∈ Ideal.span {↑v}
f_congr : ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ Ideal.span {↑v} → x - ↑b ∈ Ideal.span {↑v} → ↑a = ↑b
x y : ℤ_[p]
⊢ x + y - ↑(f x + f y) ∈ Ideal.span {↑v}

Next tactic:
convert Ideal.add_mem _ (f_spec x) (f_spec y) using 1
/-- `toZModHom` is an auxiliary constructor for creating ring homs from `ℤ_[p]` to `ZMod v`.
-/
def toZModHom (v : ℕ) (f : ℤ_[p] → ℕ) (f_spec : ∀ x, x - f x ∈ (Ideal.span {↑v} : Ideal ℤ_[p]))
    (f_congr :
      ∀ (x : ℤ_[p]) (a b : ℕ),
        x - a ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) →
          x - b ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) → (a : ZMod v) = b) :
    ℤ_[p] →+* ZMod v where
  toFun x := f x
  map_zero' := by
    dsimp only
    rw [f_congr (0 : ℤ_[p]) _ 0, cast_zero]
    · exact f_spec _
    · simp only [sub_zero, cast_zero, Submodule.zero_mem]
  map_one' := by
    dsimp only
    rw [f_congr (1 : ℤ_[p]) _ 1, cast_one]
    · exact f_spec _
    · simp only [sub_self, cast_one, Submodule.zero_mem]
  map_add' := by
    intro x y
    dsimp only
    rw [f_congr (x + y) _ (f x + f y), cast_add]
    · exact f_spec _
    · convert Ideal.add_mem _ (f_spec x) (f_spec y) using 1
      

Proof state:
case h.e'_4
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ : ℤ_[p]
v : ℕ
f : ℤ_[p] → ℕ
f_spec : ∀ (x : ℤ_[p]), x - ↑(f x) ∈ Ideal.span {↑v}
f_congr : ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ Ideal.span {↑v} → x - ↑b ∈ Ideal.span {↑v} → ↑a = ↑b
x y : ℤ_[p]
⊢ x + y - ↑(f x + f y) = x - ↑(f x) + (y - ↑(f y))

Next tactic:
rw [cast_add]
/-- `toZModHom` is an auxiliary constructor for creating ring homs from `ℤ_[p]` to `ZMod v`.
-/
def toZModHom (v : ℕ) (f : ℤ_[p] → ℕ) (f_spec : ∀ x, x - f x ∈ (Ideal.span {↑v} : Ideal ℤ_[p]))
    (f_congr :
      ∀ (x : ℤ_[p]) (a b : ℕ),
        x - a ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) →
          x - b ∈ (Ideal.span {↑v} : Ideal ℤ_[p]) → (a : ZMod v) = b) :
    ℤ_[p] →+* ZMod v where
  toFun x := f x
  map_zero' := by
    dsimp only
    rw [f_congr (0 : ℤ_[p]) _ 0, cast_zero]
    · exact f_spec _
    · simp only [sub_zero, cast_zero, Submodule.zero_mem]
  map_one' := by
    dsimp only
    rw [f_congr (1 : ℤ_[p]) _ 1, cast_one]
    · exact f_spec _
    · simp only [sub_self, cast_one, Submodule.zero_mem]
  map_add' := by
    intro x y
    dsimp only
    rw [f_congr (x + y) _ (f x + f y), cast_add]
    · exact f_spec _
    · convert Ideal.add_mem _ (f_spec x) (f_spec y) using 1
      rw [cast_add]
      

Proof state:
case h.e'_4
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ : ℤ_[p]
v : ℕ
f : ℤ_[p] → ℕ
f_spec : ∀ (x : ℤ_[p]), x - ↑(f x) ∈ Ideal.span {↑v}
f_congr : ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ Ideal.span {↑v} → x - ↑b ∈ Ideal.span {↑v} → ↑a = ↑b
x y : ℤ_[p]
⊢ x + y - (↑(f x) + ↑(f y)) = x - ↑(f x) + (y - ↑(f y))

Next tactic:
ring
/-- `toZMod` is a ring hom from `ℤ_[p]` to `ZMod p`,
with the equality `toZMod x = (zmodRepr x : ZMod p)`.
-/
def toZMod : ℤ_[p] →+* ZMod p :=
  toZModHom p zmodRepr
    (by
      

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
⊢ ∀ (x : ℤ_[p]), x - ↑(zmodRepr x) ∈ Ideal.span {↑p}

Next tactic:
rw [← maximalIdeal_eq_span_p]
/-- `toZMod` is a ring hom from `ℤ_[p]` to `ZMod p`,
with the equality `toZMod x = (zmodRepr x : ZMod p)`.
-/
def toZMod : ℤ_[p] →+* ZMod p :=
  toZModHom p zmodRepr
    (by
      rw [← maximalIdeal_eq_span_p]
      

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
⊢ ∀ (x : ℤ_[p]), x - ↑(zmodRepr x) ∈ maximalIdeal ℤ_[p]

Next tactic:
exact sub_zmodRepr_mem
/-- `toZMod` is a ring hom from `ℤ_[p]` to `ZMod p`,
with the equality `toZMod x = (zmodRepr x : ZMod p)`.
-/
def toZMod : ℤ_[p] →+* ZMod p :=
  toZModHom p zmodRepr
    (by
      rw [← maximalIdeal_eq_span_p]
      exact sub_zmodRepr_mem)
    (by
      

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
⊢ ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ Ideal.span {↑p} → x - ↑b ∈ Ideal.span {↑p} → ↑a = ↑b

Next tactic:
rw [← maximalIdeal_eq_span_p]
/-- `toZMod` is a ring hom from `ℤ_[p]` to `ZMod p`,
with the equality `toZMod x = (zmodRepr x : ZMod p)`.
-/
def toZMod : ℤ_[p] →+* ZMod p :=
  toZModHom p zmodRepr
    (by
      rw [← maximalIdeal_eq_span_p]
      exact sub_zmodRepr_mem)
    (by
      rw [← maximalIdeal_eq_span_p]
      

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
⊢ ∀ (x : ℤ_[p]) (a b : ℕ), x - ↑a ∈ maximalIdeal ℤ_[p] → x - ↑b ∈ maximalIdeal ℤ_[p] → ↑a = ↑b

Next tactic:
exact zmod_congr_of_sub_mem_max_ideal
/-- `z - (toZMod z : ℤ_[p])` is contained in the maximal ideal of `ℤ_[p]`, for every `z : ℤ_[p]`.

The coercion from `ZMod p` to `ℤ_[p]` is `ZMod.cast`,
which coerces `ZMod p` into arbitrary rings.
This is unfortunate, but a consequence of the fact that we allow `ZMod p`
to coerce to rings of arbitrary characteristic, instead of only rings of characteristic `p`.
This coercion is only a ring homomorphism if it coerces into a ring whose characteristic divides
`p`. While this is not the case here we can still make use of the coercion.
-/
theorem toZMod_spec : x - (toZMod x : ℤ_[p]) ∈ maximalIdeal ℤ_[p] := by
  

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
⊢ x - ↑(toZMod x) ∈ maximalIdeal ℤ_[p]

Next tactic:
convert sub_zmodRepr_mem x using 2
/-- `z - (toZMod z : ℤ_[p])` is contained in the maximal ideal of `ℤ_[p]`, for every `z : ℤ_[p]`.

The coercion from `ZMod p` to `ℤ_[p]` is `ZMod.cast`,
which coerces `ZMod p` into arbitrary rings.
This is unfortunate, but a consequence of the fact that we allow `ZMod p`
to coerce to rings of arbitrary characteristic, instead of only rings of characteristic `p`.
This coercion is only a ring homomorphism if it coerces into a ring whose characteristic divides
`p`. While this is not the case here we can still make use of the coercion.
-/
theorem toZMod_spec : x - (toZMod x : ℤ_[p]) ∈ maximalIdeal ℤ_[p] := by
  convert sub_zmodRepr_mem x using 2
  

Proof state:
case h.e'_4.h.e'_6
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
⊢ ↑(toZMod x) = ↑(zmodRepr x)

Next tactic:
dsimp [toZMod, toZModHom]
/-- `z - (toZMod z : ℤ_[p])` is contained in the maximal ideal of `ℤ_[p]`, for every `z : ℤ_[p]`.

The coercion from `ZMod p` to `ℤ_[p]` is `ZMod.cast`,
which coerces `ZMod p` into arbitrary rings.
This is unfortunate, but a consequence of the fact that we allow `ZMod p`
to coerce to rings of arbitrary characteristic, instead of only rings of characteristic `p`.
This coercion is only a ring homomorphism if it coerces into a ring whose characteristic divides
`p`. While this is not the case here we can still make use of the coercion.
-/
theorem toZMod_spec : x - (toZMod x : ℤ_[p]) ∈ maximalIdeal ℤ_[p] := by
  convert sub_zmodRepr_mem x using 2
  dsimp [toZMod, toZModHom]
  

Proof state:
case h.e'_4.h.e'_6
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
⊢ ↑↑(zmodRepr x) = ↑(zmodRepr x)

Next tactic:
rcases exists_eq_add_of_lt hp_prime.1.pos with ⟨p', rfl⟩
/-- `z - (toZMod z : ℤ_[p])` is contained in the maximal ideal of `ℤ_[p]`, for every `z : ℤ_[p]`.

The coercion from `ZMod p` to `ℤ_[p]` is `ZMod.cast`,
which coerces `ZMod p` into arbitrary rings.
This is unfortunate, but a consequence of the fact that we allow `ZMod p`
to coerce to rings of arbitrary characteristic, instead of only rings of characteristic `p`.
This coercion is only a ring homomorphism if it coerces into a ring whose characteristic divides
`p`. While this is not the case here we can still make use of the coercion.
-/
theorem toZMod_spec : x - (toZMod x : ℤ_[p]) ∈ maximalIdeal ℤ_[p] := by
  convert sub_zmodRepr_mem x using 2
  dsimp [toZMod, toZModHom]
  rcases exists_eq_add_of_lt hp_prime.1.pos with ⟨p', rfl⟩
  

Proof state:
case h.e'_4.h.e'_6.intro
r : ℚ
p' : ℕ
hp_prime : Fact (Nat.Prime (0 + p' + 1))
x : ℤ_[0 + p' + 1]
⊢ ↑↑(zmodRepr x) = ↑(zmodRepr x)

Next tactic:
change ↑((_ : ZMod (0 + p' + 1)).val) = (_ : ℤ_[0 + p' + 1])
/-- `z - (toZMod z : ℤ_[p])` is contained in the maximal ideal of `ℤ_[p]`, for every `z : ℤ_[p]`.

The coercion from `ZMod p` to `ℤ_[p]` is `ZMod.cast`,
which coerces `ZMod p` into arbitrary rings.
This is unfortunate, but a consequence of the fact that we allow `ZMod p`
to coerce to rings of arbitrary characteristic, instead of only rings of characteristic `p`.
This coercion is only a ring homomorphism if it coerces into a ring whose characteristic divides
`p`. While this is not the case here we can still make use of the coercion.
-/
theorem toZMod_spec : x - (toZMod x : ℤ_[p]) ∈ maximalIdeal ℤ_[p] := by
  convert sub_zmodRepr_mem x using 2
  dsimp [toZMod, toZModHom]
  rcases exists_eq_add_of_lt hp_prime.1.pos with ⟨p', rfl⟩
  change ↑((_ : ZMod (0 + p' + 1)).val) = (_ : ℤ_[0 + p' + 1])
  

Proof state:
case h.e'_4.h.e'_6.intro
r : ℚ
p' : ℕ
hp_prime : Fact (Nat.Prime (0 + p' + 1))
x : ℤ_[0 + p' + 1]
⊢ ↑(ZMod.val ↑(zmodRepr x)) = ↑(zmodRepr x)

Next tactic:
simp only [ZMod.val_nat_cast, add_zero, add_def, Nat.cast_inj, zero_add]
/-- `z - (toZMod z : ℤ_[p])` is contained in the maximal ideal of `ℤ_[p]`, for every `z : ℤ_[p]`.

The coercion from `ZMod p` to `ℤ_[p]` is `ZMod.cast`,
which coerces `ZMod p` into arbitrary rings.
This is unfortunate, but a consequence of the fact that we allow `ZMod p`
to coerce to rings of arbitrary characteristic, instead of only rings of characteristic `p`.
This coercion is only a ring homomorphism if it coerces into a ring whose characteristic divides
`p`. While this is not the case here we can still make use of the coercion.
-/
theorem toZMod_spec : x - (toZMod x : ℤ_[p]) ∈ maximalIdeal ℤ_[p] := by
  convert sub_zmodRepr_mem x using 2
  dsimp [toZMod, toZModHom]
  rcases exists_eq_add_of_lt hp_prime.1.pos with ⟨p', rfl⟩
  change ↑((_ : ZMod (0 + p' + 1)).val) = (_ : ℤ_[0 + p' + 1])
  simp only [ZMod.val_nat_cast, add_zero, add_def, Nat.cast_inj, zero_add]
  

Proof state:
case h.e'_4.h.e'_6.intro
r : ℚ
p' : ℕ
hp_prime : Fact (Nat.Prime (0 + p' + 1))
x : ℤ_[0 + p' + 1]
⊢ zmodRepr x % (p' + 1) = zmodRepr x

Next tactic:
apply mod_eq_of_lt
/-- `z - (toZMod z : ℤ_[p])` is contained in the maximal ideal of `ℤ_[p]`, for every `z : ℤ_[p]`.

The coercion from `ZMod p` to `ℤ_[p]` is `ZMod.cast`,
which coerces `ZMod p` into arbitrary rings.
This is unfortunate, but a consequence of the fact that we allow `ZMod p`
to coerce to rings of arbitrary characteristic, instead of only rings of characteristic `p`.
This coercion is only a ring homomorphism if it coerces into a ring whose characteristic divides
`p`. While this is not the case here we can still make use of the coercion.
-/
theorem toZMod_spec : x - (toZMod x : ℤ_[p]) ∈ maximalIdeal ℤ_[p] := by
  convert sub_zmodRepr_mem x using 2
  dsimp [toZMod, toZModHom]
  rcases exists_eq_add_of_lt hp_prime.1.pos with ⟨p', rfl⟩
  change ↑((_ : ZMod (0 + p' + 1)).val) = (_ : ℤ_[0 + p' + 1])
  simp only [ZMod.val_nat_cast, add_zero, add_def, Nat.cast_inj, zero_add]
  apply mod_eq_of_lt
  

Proof state:
case h.e'_4.h.e'_6.intro.h
r : ℚ
p' : ℕ
hp_prime : Fact (Nat.Prime (0 + p' + 1))
x : ℤ_[0 + p' + 1]
⊢ zmodRepr x < p' + 1

Next tactic:
simpa only [zero_add] using zmodRepr_lt_p x
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x : ℤ_[p]
⊢ RingHom.ker toZMod = maximalIdeal ℤ_[p]

Next tactic:
ext x
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  

Proof state:
case h
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
⊢ x ∈ RingHom.ker toZMod ↔ x ∈ maximalIdeal ℤ_[p]

Next tactic:
rw [RingHom.mem_ker]
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  

Proof state:
case h
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
⊢ toZMod x = 0 ↔ x ∈ maximalIdeal ℤ_[p]

Next tactic:
constructor
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  constructor
  · 

Proof state:
case h.mp
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
⊢ toZMod x = 0 → x ∈ maximalIdeal ℤ_[p]

Next tactic:
intro h
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  constructor
  · intro h
    

Proof state:
case h.mp
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
h : toZMod x = 0
⊢ x ∈ maximalIdeal ℤ_[p]

Next tactic:
simpa only [h, ZMod.cast_zero, sub_zero] using toZMod_spec x
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  constructor
  · intro h
    simpa only [h, ZMod.cast_zero, sub_zero] using toZMod_spec x
  · 

Proof state:
case h.mpr
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
⊢ x ∈ maximalIdeal ℤ_[p] → toZMod x = 0

Next tactic:
intro h
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  constructor
  · intro h
    simpa only [h, ZMod.cast_zero, sub_zero] using toZMod_spec x
  · intro h
    

Proof state:
case h.mpr
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
h : x ∈ maximalIdeal ℤ_[p]
⊢ toZMod x = 0

Next tactic:
rw [← sub_zero x] at h
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  constructor
  · intro h
    simpa only [h, ZMod.cast_zero, sub_zero] using toZMod_spec x
  · intro h
    rw [← sub_zero x] at h
    

Proof state:
case h.mpr
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
h : x - 0 ∈ maximalIdeal ℤ_[p]
⊢ toZMod x = 0

Next tactic:
dsimp [toZMod, toZModHom]
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  constructor
  · intro h
    simpa only [h, ZMod.cast_zero, sub_zero] using toZMod_spec x
  · intro h
    rw [← sub_zero x] at h
    dsimp [toZMod, toZModHom]
    

Proof state:
case h.mpr
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
h : x - 0 ∈ maximalIdeal ℤ_[p]
⊢ ↑(zmodRepr x) = 0

Next tactic:
convert zmod_congr_of_sub_mem_max_ideal x _ 0 _ h
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  constructor
  · intro h
    simpa only [h, ZMod.cast_zero, sub_zero] using toZMod_spec x
  · intro h
    rw [← sub_zero x] at h
    dsimp [toZMod, toZModHom]
    convert zmod_congr_of_sub_mem_max_ideal x _ 0 _ h
    

Proof state:
case h.e'_3
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
h : x - 0 ∈ maximalIdeal ℤ_[p]
⊢ 0 = ↑0
case h.mpr.convert_2
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
h : x - 0 ∈ maximalIdeal ℤ_[p]
⊢ x - ↑(zmodRepr x) ∈ maximalIdeal ℤ_[p]

Next tactic:
norm_cast
theorem ker_toZMod : RingHom.ker (toZMod : ℤ_[p] →+* ZMod p) = maximalIdeal ℤ_[p] := by
  ext x
  rw [RingHom.mem_ker]
  constructor
  · intro h
    simpa only [h, ZMod.cast_zero, sub_zero] using toZMod_spec x
  · intro h
    rw [← sub_zero x] at h
    dsimp [toZMod, toZModHom]
    convert zmod_congr_of_sub_mem_max_ideal x _ 0 _ h
    norm_cast
    

Proof state:
case h.mpr.convert_2
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
h : x - 0 ∈ maximalIdeal ℤ_[p]
⊢ x - ↑(zmodRepr x) ∈ maximalIdeal ℤ_[p]

Next tactic:
apply sub_zmodRepr_mem
theorem appr_lt (x : ℤ_[p]) (n : ℕ) : x.appr n < p ^ n := by
  

Proof state:
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
n : ℕ
⊢ appr x n < p ^ n

Next tactic:
induction' n with n ih generalizing x
theorem appr_lt (x : ℤ_[p]) (n : ℕ) : x.appr n < p ^ n := by
  induction' n with n ih generalizing x
  · 

Proof state:
case zero
p : ℕ
hp_prime : Fact (Nat.Prime p)
r : ℚ
x✝ x : ℤ_[p]
⊢ appr x zero < p ^ zero

Next tactic:
simp only [appr, zero_eq, _root_.pow_zero, zero_lt_one]