l3lab/ntp-mathlib huggingface dataset:
/-- A perfect field of characteristic `p` (prime) is a perfect ring. -/
instance toPerfectRing (p : ℕ) [hp : Fact p.Prime] [CharP K p] : PerfectRing K p := by
  refine' PerfectRing.ofSurjective _ _ $ fun y ↦ _
  let f : K[X] := X ^ p - C y
  let L := f.SplittingField
  let ι := algebraMap K L
  have hf_deg : f.degree ≠ 0 := by
    rw [degree_X_pow_sub_C hp.out.pos y, p.cast_ne_zero]; exact hp.out.ne_zero
  let a : L := f.rootOfSplits ι (SplittingField.splits f) hf_deg
  have hfa : aeval a f = 0 := by rw [aeval_def, map_rootOfSplits _ (SplittingField.splits f) hf_deg]
  have ha_pow : a ^ p = ι y := by rwa [AlgHom.map_sub, aeval_X_pow, aeval_C, sub_eq_zero] at hfa
  let g : K[X] := minpoly K a
  suffices : (g.map ι).natDegree = 1
  · rw [g.natDegree_map, ← degree_eq_iff_natDegree_eq_of_pos Nat.one_pos] at this
    obtain ⟨a' : K, ha' : ι a' = a⟩ := minpoly.mem_range_of_degree_eq_one K a this
    refine' ⟨a', NoZeroSMulDivisors.algebraMap_injective K L _⟩
    rw [RingHom.map_frobenius, ha', frobenius_def, ha_pow]
  have hg_dvd : g.map ι ∣ (X - C a) ^ p := by
    convert Polynomial.map_dvd ι (minpoly.dvd K a hfa)
    rw [sub_pow_char, Polynomial.map_sub, Polynomial.map_pow, map_X, map_C, ← ha_pow, map_pow]
  have ha : IsIntegral K a := .of_finite K a
  have hg_pow : g.map ι = (X - C a) ^ (g.map ι).natDegree := by
    

Proof state:
K : Type u_1
inst✝² : Field K
inst✝¹ : PerfectField K
p : ℕ
hp : Fact (Nat.Prime p)
inst✝ : CharP K p
y : K
f : K[X] := X ^ p - C y
L : Type u_1 := SplittingField f
ι : K →+* L := algebraMap K L
hf_deg : degree f ≠ 0
a : L := rootOfSplits ι (_ : Splits (algebraMap K (SplittingField f)) f) hf_deg
hfa : (aeval a) f = 0
ha_pow : a ^ p = ι y
g : K[X] := minpoly K a
hg_dvd : map ι g ∣ (X - C a) ^ p
ha : IsIntegral K a
⊢ map ι g = (X - C a) ^ natDegree (map ι g)

Next tactic:
obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd
/-- A perfect field of characteristic `p` (prime) is a perfect ring. -/
instance toPerfectRing (p : ℕ) [hp : Fact p.Prime] [CharP K p] : PerfectRing K p := by
  refine' PerfectRing.ofSurjective _ _ $ fun y ↦ _
  let f : K[X] := X ^ p - C y
  let L := f.SplittingField
  let ι := algebraMap K L
  have hf_deg : f.degree ≠ 0 := by
    rw [degree_X_pow_sub_C hp.out.pos y, p.cast_ne_zero]; exact hp.out.ne_zero
  let a : L := f.rootOfSplits ι (SplittingField.splits f) hf_deg
  have hfa : aeval a f = 0 := by rw [aeval_def, map_rootOfSplits _ (SplittingField.splits f) hf_deg]
  have ha_pow : a ^ p = ι y := by rwa [AlgHom.map_sub, aeval_X_pow, aeval_C, sub_eq_zero] at hfa
  let g : K[X] := minpoly K a
  suffices : (g.map ι).natDegree = 1
  · rw [g.natDegree_map, ← degree_eq_iff_natDegree_eq_of_pos Nat.one_pos] at this
    obtain ⟨a' : K, ha' : ι a' = a⟩ := minpoly.mem_range_of_degree_eq_one K a this
    refine' ⟨a', NoZeroSMulDivisors.algebraMap_injective K L _⟩
    rw [RingHom.map_frobenius, ha', frobenius_def, ha_pow]
  have hg_dvd : g.map ι ∣ (X - C a) ^ p := by
    convert Polynomial.map_dvd ι (minpoly.dvd K a hfa)
    rw [sub_pow_char, Polynomial.map_sub, Polynomial.map_pow, map_X, map_C, ← ha_pow, map_pow]
  have ha : IsIntegral K a := .of_finite K a
  have hg_pow : g.map ι = (X - C a) ^ (g.map ι).natDegree := by
    obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd
    

Proof state:
case intro.intro
K : Type u_1
inst✝² : Field K
inst✝¹ : PerfectField K
p : ℕ
hp : Fact (Nat.Prime p)
inst✝ : CharP K p
y : K
f : K[X] := X ^ p - C y
L : Type u_1 := SplittingField f
ι : K →+* L := algebraMap K L
hf_deg : degree f ≠ 0
a : L := rootOfSplits ι (_ : Splits (algebraMap K (SplittingField f)) f) hf_deg
hfa : (aeval a) f = 0
ha_pow : a ^ p = ι y
g : K[X] := minpoly K a
hg_dvd : map ι g ∣ (X - C a) ^ p
ha : IsIntegral K a
q : ℕ
hq : Associated (map ι g) ((X - C a) ^ q)
⊢ map ι g = (X - C a) ^ natDegree (map ι g)

Next tactic:
rw [eq_of_monic_of_associated ((minpoly.monic ha).map ι) ((monic_X_sub_C a).pow q) hq,
      natDegree_pow, natDegree_X_sub_C, mul_one]
/-- A perfect field of characteristic `p` (prime) is a perfect ring. -/
instance toPerfectRing (p : ℕ) [hp : Fact p.Prime] [CharP K p] : PerfectRing K p := by
  refine' PerfectRing.ofSurjective _ _ $ fun y ↦ _
  let f : K[X] := X ^ p - C y
  let L := f.SplittingField
  let ι := algebraMap K L
  have hf_deg : f.degree ≠ 0 := by
    rw [degree_X_pow_sub_C hp.out.pos y, p.cast_ne_zero]; exact hp.out.ne_zero
  let a : L := f.rootOfSplits ι (SplittingField.splits f) hf_deg
  have hfa : aeval a f = 0 := by rw [aeval_def, map_rootOfSplits _ (SplittingField.splits f) hf_deg]
  have ha_pow : a ^ p = ι y := by rwa [AlgHom.map_sub, aeval_X_pow, aeval_C, sub_eq_zero] at hfa
  let g : K[X] := minpoly K a
  suffices : (g.map ι).natDegree = 1
  · rw [g.natDegree_map, ← degree_eq_iff_natDegree_eq_of_pos Nat.one_pos] at this
    obtain ⟨a' : K, ha' : ι a' = a⟩ := minpoly.mem_range_of_degree_eq_one K a this
    refine' ⟨a', NoZeroSMulDivisors.algebraMap_injective K L _⟩
    rw [RingHom.map_frobenius, ha', frobenius_def, ha_pow]
  have hg_dvd : g.map ι ∣ (X - C a) ^ p := by
    convert Polynomial.map_dvd ι (minpoly.dvd K a hfa)
    rw [sub_pow_char, Polynomial.map_sub, Polynomial.map_pow, map_X, map_C, ← ha_pow, map_pow]
  have ha : IsIntegral K a := .of_finite K a
  have hg_pow : g.map ι = (X - C a) ^ (g.map ι).natDegree := by
    obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd
    rw [eq_of_monic_of_associated ((minpoly.monic ha).map ι) ((monic_X_sub_C a).pow q) hq,
      natDegree_pow, natDegree_X_sub_C, mul_one]
  

Proof state:
case this
K : Type u_1
inst✝² : Field K
inst✝¹ : PerfectField K
p : ℕ
hp : Fact (Nat.Prime p)
inst✝ : CharP K p
y : K
f : K[X] := X ^ p - C y
L : Type u_1 := SplittingField f
ι : K →+* L := algebraMap K L
hf_deg : degree f ≠ 0
a : L := rootOfSplits ι (_ : Splits (algebraMap K (SplittingField f)) f) hf_deg
hfa : (aeval a) f = 0
ha_pow : a ^ p = ι y
g : K[X] := minpoly K a
hg_dvd : map ι g ∣ (X - C a) ^ p
ha : IsIntegral K a
hg_pow : map ι g = (X - C a) ^ natDegree (map ι g)
⊢ natDegree (map ι g) = 1

Next tactic:
have hg_sep : (g.map ι).Separable := (separable_of_irreducible $ minpoly.irreducible ha).map
/-- A perfect field of characteristic `p` (prime) is a perfect ring. -/
instance toPerfectRing (p : ℕ) [hp : Fact p.Prime] [CharP K p] : PerfectRing K p := by
  refine' PerfectRing.ofSurjective _ _ $ fun y ↦ _
  let f : K[X] := X ^ p - C y
  let L := f.SplittingField
  let ι := algebraMap K L
  have hf_deg : f.degree ≠ 0 := by
    rw [degree_X_pow_sub_C hp.out.pos y, p.cast_ne_zero]; exact hp.out.ne_zero
  let a : L := f.rootOfSplits ι (SplittingField.splits f) hf_deg
  have hfa : aeval a f = 0 := by rw [aeval_def, map_rootOfSplits _ (SplittingField.splits f) hf_deg]
  have ha_pow : a ^ p = ι y := by rwa [AlgHom.map_sub, aeval_X_pow, aeval_C, sub_eq_zero] at hfa
  let g : K[X] := minpoly K a
  suffices : (g.map ι).natDegree = 1
  · rw [g.natDegree_map, ← degree_eq_iff_natDegree_eq_of_pos Nat.one_pos] at this
    obtain ⟨a' : K, ha' : ι a' = a⟩ := minpoly.mem_range_of_degree_eq_one K a this
    refine' ⟨a', NoZeroSMulDivisors.algebraMap_injective K L _⟩
    rw [RingHom.map_frobenius, ha', frobenius_def, ha_pow]
  have hg_dvd : g.map ι ∣ (X - C a) ^ p := by
    convert Polynomial.map_dvd ι (minpoly.dvd K a hfa)
    rw [sub_pow_char, Polynomial.map_sub, Polynomial.map_pow, map_X, map_C, ← ha_pow, map_pow]
  have ha : IsIntegral K a := .of_finite K a
  have hg_pow : g.map ι = (X - C a) ^ (g.map ι).natDegree := by
    obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd
    rw [eq_of_monic_of_associated ((minpoly.monic ha).map ι) ((monic_X_sub_C a).pow q) hq,
      natDegree_pow, natDegree_X_sub_C, mul_one]
  have hg_sep : (g.map ι).Separable := (separable_of_irreducible $ minpoly.irreducible ha).map
  

Proof state:
case this
K : Type u_1
inst✝² : Field K
inst✝¹ : PerfectField K
p : ℕ
hp : Fact (Nat.Prime p)
inst✝ : CharP K p
y : K
f : K[X] := X ^ p - C y
L : Type u_1 := SplittingField f
ι : K →+* L := algebraMap K L
hf_deg : degree f ≠ 0
a : L := rootOfSplits ι (_ : Splits (algebraMap K (SplittingField f)) f) hf_deg
hfa : (aeval a) f = 0
ha_pow : a ^ p = ι y
g : K[X] := minpoly K a
hg_dvd : map ι g ∣ (X - C a) ^ p
ha : IsIntegral K a
hg_pow : map ι g = (X - C a) ^ natDegree (map ι g)
hg_sep : Separable (map ι g)
⊢ natDegree (map ι g) = 1

Next tactic:
rw [hg_pow] at hg_sep
/-- A perfect field of characteristic `p` (prime) is a perfect ring. -/
instance toPerfectRing (p : ℕ) [hp : Fact p.Prime] [CharP K p] : PerfectRing K p := by
  refine' PerfectRing.ofSurjective _ _ $ fun y ↦ _
  let f : K[X] := X ^ p - C y
  let L := f.SplittingField
  let ι := algebraMap K L
  have hf_deg : f.degree ≠ 0 := by
    rw [degree_X_pow_sub_C hp.out.pos y, p.cast_ne_zero]; exact hp.out.ne_zero
  let a : L := f.rootOfSplits ι (SplittingField.splits f) hf_deg
  have hfa : aeval a f = 0 := by rw [aeval_def, map_rootOfSplits _ (SplittingField.splits f) hf_deg]
  have ha_pow : a ^ p = ι y := by rwa [AlgHom.map_sub, aeval_X_pow, aeval_C, sub_eq_zero] at hfa
  let g : K[X] := minpoly K a
  suffices : (g.map ι).natDegree = 1
  · rw [g.natDegree_map, ← degree_eq_iff_natDegree_eq_of_pos Nat.one_pos] at this
    obtain ⟨a' : K, ha' : ι a' = a⟩ := minpoly.mem_range_of_degree_eq_one K a this
    refine' ⟨a', NoZeroSMulDivisors.algebraMap_injective K L _⟩
    rw [RingHom.map_frobenius, ha', frobenius_def, ha_pow]
  have hg_dvd : g.map ι ∣ (X - C a) ^ p := by
    convert Polynomial.map_dvd ι (minpoly.dvd K a hfa)
    rw [sub_pow_char, Polynomial.map_sub, Polynomial.map_pow, map_X, map_C, ← ha_pow, map_pow]
  have ha : IsIntegral K a := .of_finite K a
  have hg_pow : g.map ι = (X - C a) ^ (g.map ι).natDegree := by
    obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd
    rw [eq_of_monic_of_associated ((minpoly.monic ha).map ι) ((monic_X_sub_C a).pow q) hq,
      natDegree_pow, natDegree_X_sub_C, mul_one]
  have hg_sep : (g.map ι).Separable := (separable_of_irreducible $ minpoly.irreducible ha).map
  rw [hg_pow] at hg_sep
  

Proof state:
case this
K : Type u_1
inst✝² : Field K
inst✝¹ : PerfectField K
p : ℕ
hp : Fact (Nat.Prime p)
inst✝ : CharP K p
y : K
f : K[X] := X ^ p - C y
L : Type u_1 := SplittingField f
ι : K →+* L := algebraMap K L
hf_deg : degree f ≠ 0
a : L := rootOfSplits ι (_ : Splits (algebraMap K (SplittingField f)) f) hf_deg
hfa : (aeval a) f = 0
ha_pow : a ^ p = ι y
g : K[X] := minpoly K a
hg_dvd : map ι g ∣ (X - C a) ^ p
ha : IsIntegral K a
hg_pow : map ι g = (X - C a) ^ natDegree (map ι g)
hg_sep : Separable ((X - C a) ^ natDegree (map ι g))
⊢ natDegree (map ι g) = 1

Next tactic:
refine' (Separable.of_pow (not_isUnit_X_sub_C a) _ hg_sep).2
/-- A perfect field of characteristic `p` (prime) is a perfect ring. -/
instance toPerfectRing (p : ℕ) [hp : Fact p.Prime] [CharP K p] : PerfectRing K p := by
  refine' PerfectRing.ofSurjective _ _ $ fun y ↦ _
  let f : K[X] := X ^ p - C y
  let L := f.SplittingField
  let ι := algebraMap K L
  have hf_deg : f.degree ≠ 0 := by
    rw [degree_X_pow_sub_C hp.out.pos y, p.cast_ne_zero]; exact hp.out.ne_zero
  let a : L := f.rootOfSplits ι (SplittingField.splits f) hf_deg
  have hfa : aeval a f = 0 := by rw [aeval_def, map_rootOfSplits _ (SplittingField.splits f) hf_deg]
  have ha_pow : a ^ p = ι y := by rwa [AlgHom.map_sub, aeval_X_pow, aeval_C, sub_eq_zero] at hfa
  let g : K[X] := minpoly K a
  suffices : (g.map ι).natDegree = 1
  · rw [g.natDegree_map, ← degree_eq_iff_natDegree_eq_of_pos Nat.one_pos] at this
    obtain ⟨a' : K, ha' : ι a' = a⟩ := minpoly.mem_range_of_degree_eq_one K a this
    refine' ⟨a', NoZeroSMulDivisors.algebraMap_injective K L _⟩
    rw [RingHom.map_frobenius, ha', frobenius_def, ha_pow]
  have hg_dvd : g.map ι ∣ (X - C a) ^ p := by
    convert Polynomial.map_dvd ι (minpoly.dvd K a hfa)
    rw [sub_pow_char, Polynomial.map_sub, Polynomial.map_pow, map_X, map_C, ← ha_pow, map_pow]
  have ha : IsIntegral K a := .of_finite K a
  have hg_pow : g.map ι = (X - C a) ^ (g.map ι).natDegree := by
    obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd
    rw [eq_of_monic_of_associated ((minpoly.monic ha).map ι) ((monic_X_sub_C a).pow q) hq,
      natDegree_pow, natDegree_X_sub_C, mul_one]
  have hg_sep : (g.map ι).Separable := (separable_of_irreducible $ minpoly.irreducible ha).map
  rw [hg_pow] at hg_sep
  refine' (Separable.of_pow (not_isUnit_X_sub_C a) _ hg_sep).2
  

Proof state:
case this
K : Type u_1
inst✝² : Field K
inst✝¹ : PerfectField K
p : ℕ
hp : Fact (Nat.Prime p)
inst✝ : CharP K p
y : K
f : K[X] := X ^ p - C y
L : Type u_1 := SplittingField f
ι : K →+* L := algebraMap K L
hf_deg : degree f ≠ 0
a : L := rootOfSplits ι (_ : Splits (algebraMap K (SplittingField f)) f) hf_deg
hfa : (aeval a) f = 0
ha_pow : a ^ p = ι y
g : K[X] := minpoly K a
hg_dvd : map ι g ∣ (X - C a) ^ p
ha : IsIntegral K a
hg_pow : map ι g = (X - C a) ^ natDegree (map ι g)
hg_sep : Separable ((X - C a) ^ natDegree (map ι g))
⊢ natDegree (map ι g) ≠ 0

Next tactic:
rw [g.natDegree_map ι, ← Nat.pos_iff_ne_zero, natDegree_pos_iff_degree_pos]
/-- A perfect field of characteristic `p` (prime) is a perfect ring. -/
instance toPerfectRing (p : ℕ) [hp : Fact p.Prime] [CharP K p] : PerfectRing K p := by
  refine' PerfectRing.ofSurjective _ _ $ fun y ↦ _
  let f : K[X] := X ^ p - C y
  let L := f.SplittingField
  let ι := algebraMap K L
  have hf_deg : f.degree ≠ 0 := by
    rw [degree_X_pow_sub_C hp.out.pos y, p.cast_ne_zero]; exact hp.out.ne_zero
  let a : L := f.rootOfSplits ι (SplittingField.splits f) hf_deg
  have hfa : aeval a f = 0 := by rw [aeval_def, map_rootOfSplits _ (SplittingField.splits f) hf_deg]
  have ha_pow : a ^ p = ι y := by rwa [AlgHom.map_sub, aeval_X_pow, aeval_C, sub_eq_zero] at hfa
  let g : K[X] := minpoly K a
  suffices : (g.map ι).natDegree = 1
  · rw [g.natDegree_map, ← degree_eq_iff_natDegree_eq_of_pos Nat.one_pos] at this
    obtain ⟨a' : K, ha' : ι a' = a⟩ := minpoly.mem_range_of_degree_eq_one K a this
    refine' ⟨a', NoZeroSMulDivisors.algebraMap_injective K L _⟩
    rw [RingHom.map_frobenius, ha', frobenius_def, ha_pow]
  have hg_dvd : g.map ι ∣ (X - C a) ^ p := by
    convert Polynomial.map_dvd ι (minpoly.dvd K a hfa)
    rw [sub_pow_char, Polynomial.map_sub, Polynomial.map_pow, map_X, map_C, ← ha_pow, map_pow]
  have ha : IsIntegral K a := .of_finite K a
  have hg_pow : g.map ι = (X - C a) ^ (g.map ι).natDegree := by
    obtain ⟨q, -, hq⟩ := (dvd_prime_pow (prime_X_sub_C a) p).mp hg_dvd
    rw [eq_of_monic_of_associated ((minpoly.monic ha).map ι) ((monic_X_sub_C a).pow q) hq,
      natDegree_pow, natDegree_X_sub_C, mul_one]
  have hg_sep : (g.map ι).Separable := (separable_of_irreducible $ minpoly.irreducible ha).map
  rw [hg_pow] at hg_sep
  refine' (Separable.of_pow (not_isUnit_X_sub_C a) _ hg_sep).2
  rw [g.natDegree_map ι, ← Nat.pos_iff_ne_zero, natDegree_pos_iff_degree_pos]
  

Proof state:
case this
K : Type u_1
inst✝² : Field K
inst✝¹ : PerfectField K
p : ℕ
hp : Fact (Nat.Prime p)
inst✝ : CharP K p
y : K
f : K[X] := X ^ p - C y
L : Type u_1 := SplittingField f
ι : K →+* L := algebraMap K L
hf_deg : degree f ≠ 0
a : L := rootOfSplits ι (_ : Splits (algebraMap K (SplittingField f)) f) hf_deg
hfa : (aeval a) f = 0
ha_pow : a ^ p = ι y
g : K[X] := minpoly K a
hg_dvd : map ι g ∣ (X - C a) ^ p
ha : IsIntegral K a
hg_pow : map ι g = (X - C a) ^ natDegree (map ι g)
hg_sep : Separable ((X - C a) ^ natDegree (map ι g))
⊢ 0 < degree g

Next tactic:
exact minpoly.degree_pos ha
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  

Proof state:
m n : ℕ
⊢ bodd (subNatNat m n) = xor (Nat.bodd m) (Nat.bodd n)

Next tactic:
apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  

Proof state:
case hp
m n : ℕ
⊢ ∀ (i n : ℕ), bodd ↑i = xor (Nat.bodd (n + i)) (Nat.bodd n)

Next tactic:
intros i j
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  

Proof state:
case hn
m n : ℕ
⊢ ∀ (i m : ℕ), bodd -[i+1] = xor (Nat.bodd m) (Nat.bodd (m + i + 1))

Next tactic:
intros i j
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  intros i j <;>
  

Proof state:
case hp
m n i j : ℕ
⊢ bodd ↑i = xor (Nat.bodd (j + i)) (Nat.bodd j)

Next tactic:
simp only [Int.bodd, Int.bodd_coe, Nat.bodd_add]
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  intros i j <;>
  

Proof state:
case hn
m n i j : ℕ
⊢ bodd -[i+1] = xor (Nat.bodd j) (Nat.bodd (j + i + 1))

Next tactic:
simp only [Int.bodd, Int.bodd_coe, Nat.bodd_add]
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  intros i j <;>
  simp only [Int.bodd, Int.bodd_coe, Nat.bodd_add] <;>
  

Proof state:
case hp
m n i j : ℕ
⊢ Nat.bodd i = xor (xor (Nat.bodd j) (Nat.bodd i)) (Nat.bodd j)

Next tactic:
cases Nat.bodd i
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  intros i j <;>
  simp only [Int.bodd, Int.bodd_coe, Nat.bodd_add] <;>
  

Proof state:
case hn
m n i j : ℕ
⊢ (!Nat.bodd i) = xor (Nat.bodd j) (xor (xor (Nat.bodd j) (Nat.bodd i)) (Nat.bodd 1))

Next tactic:
cases Nat.bodd i
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  intros i j <;>
  simp only [Int.bodd, Int.bodd_coe, Nat.bodd_add] <;>
  cases Nat.bodd i <;> 

Proof state:
case hp.false
m n i j : ℕ
⊢ false = xor (xor (Nat.bodd j) false) (Nat.bodd j)

Next tactic:
simp
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  intros i j <;>
  simp only [Int.bodd, Int.bodd_coe, Nat.bodd_add] <;>
  cases Nat.bodd i <;> 

Proof state:
case hp.true
m n i j : ℕ
⊢ true = xor (xor (Nat.bodd j) true) (Nat.bodd j)

Next tactic:
simp
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  intros i j <;>
  simp only [Int.bodd, Int.bodd_coe, Nat.bodd_add] <;>
  cases Nat.bodd i <;> 

Proof state:
case hn.false
m n i j : ℕ
⊢ (!false) = xor (Nat.bodd j) (xor (xor (Nat.bodd j) false) (Nat.bodd 1))

Next tactic:
simp
@[simp]
theorem bodd_subNatNat (m n : ℕ) : bodd (subNatNat m n) = xor m.bodd n.bodd := by
  apply subNatNat_elim m n fun m n i => bodd i = xor m.bodd n.bodd <;>
  intros i j <;>
  simp only [Int.bodd, Int.bodd_coe, Nat.bodd_add] <;>
  cases Nat.bodd i <;> 

Proof state:
case hn.true
m n i j : ℕ
⊢ (!true) = xor (Nat.bodd j) (xor (xor (Nat.bodd j) true) (Nat.bodd 1))

Next tactic:
simp
@[simp]
theorem bodd_negOfNat (n : ℕ) : bodd (negOfNat n) = n.bodd := by
  

Proof state:
n : ℕ
⊢ bodd (negOfNat n) = Nat.bodd n

Next tactic:
cases n
@[simp]
theorem bodd_negOfNat (n : ℕ) : bodd (negOfNat n) = n.bodd := by
  cases n <;> 

Proof state:
case zero
⊢ bodd (negOfNat Nat.zero) = Nat.bodd Nat.zero

Next tactic:
simp (config := {decide := true})
@[simp]
theorem bodd_negOfNat (n : ℕ) : bodd (negOfNat n) = n.bodd := by
  cases n <;> 

Proof state:
case succ
n✝ : ℕ
⊢ bodd (negOfNat (Nat.succ n✝)) = Nat.bodd (Nat.succ n✝)

Next tactic:
simp (config := {decide := true})
@[simp]
theorem bodd_negOfNat (n : ℕ) : bodd (negOfNat n) = n.bodd := by
  cases n <;> simp (config := {decide := true})
  

Proof state:
case succ
n✝ : ℕ
⊢ bodd (negOfNat (Nat.succ n✝)) = !Nat.bodd n✝

Next tactic:
rfl
@[simp]
theorem bodd_neg (n : ℤ) : bodd (-n) = bodd n := by
  

Proof state:
n : ℤ
⊢ bodd (-n) = bodd n

Next tactic:
cases n with
  | ofNat =>
    rw [← negOfNat_eq, bodd_negOfNat]
    simp
  | negSucc n =>
    rw [neg_negSucc, bodd_coe, Nat.bodd_succ]
    change (!Nat.bodd n) = !(bodd n)
    rw [bodd_coe]
@[simp]
theorem bodd_neg (n : ℤ) : bodd (-n) = bodd n := by
  cases n with
  

Proof state:
case ofNat
a✝ : ℕ
⊢ bodd (-ofNat a✝) = bodd (ofNat a✝)

Next tactic:
| ofNat =>
    rw [← negOfNat_eq, bodd_negOfNat]
    simp
@[simp]
theorem bodd_neg (n : ℤ) : bodd (-n) = bodd n := by
  cases n with
  | ofNat =>
    

Proof state:
case ofNat
a✝ : ℕ
⊢ bodd (-ofNat a✝) = bodd (ofNat a✝)

Next tactic:
rw [← negOfNat_eq, bodd_negOfNat]
@[simp]
theorem bodd_neg (n : ℤ) : bodd (-n) = bodd n := by
  cases n with
  | ofNat =>
    rw [← negOfNat_eq, bodd_negOfNat]
    

Proof state:
case ofNat
a✝ : ℕ
⊢ Nat.bodd a✝ = bodd (ofNat a✝)

Next tactic:
simp
@[simp]
theorem bodd_neg (n : ℤ) : bodd (-n) = bodd n := by
  cases n with
  | ofNat =>
    rw [← negOfNat_eq, bodd_negOfNat]
    simp
  

Proof state:
case negSucc
n : ℕ
⊢ bodd (- -[n+1]) = bodd -[n+1]

Next tactic:
| negSucc n =>
    rw [neg_negSucc, bodd_coe, Nat.bodd_succ]
    change (!Nat.bodd n) = !(bodd n)
    rw [bodd_coe]
@[simp]
theorem bodd_neg (n : ℤ) : bodd (-n) = bodd n := by
  cases n with
  | ofNat =>
    rw [← negOfNat_eq, bodd_negOfNat]
    simp
  | negSucc n =>
    

Proof state:
case negSucc
n : ℕ
⊢ bodd (- -[n+1]) = bodd -[n+1]

Next tactic:
rw [neg_negSucc, bodd_coe, Nat.bodd_succ]
@[simp]
theorem bodd_neg (n : ℤ) : bodd (-n) = bodd n := by
  cases n with
  | ofNat =>
    rw [← negOfNat_eq, bodd_negOfNat]
    simp
  | negSucc n =>
    rw [neg_negSucc, bodd_coe, Nat.bodd_succ]
    

Proof state:
case negSucc
n : ℕ
⊢ (!Nat.bodd n) = bodd -[n+1]

Next tactic:
change (!Nat.bodd n) = !(bodd n)
@[simp]
theorem bodd_neg (n : ℤ) : bodd (-n) = bodd n := by
  cases n with
  | ofNat =>
    rw [← negOfNat_eq, bodd_negOfNat]
    simp
  | negSucc n =>
    rw [neg_negSucc, bodd_coe, Nat.bodd_succ]
    change (!Nat.bodd n) = !(bodd n)
    

Proof state:
case negSucc
n : ℕ
⊢ (!Nat.bodd n) = !bodd ↑n

Next tactic:
rw [bodd_coe]
@[simp]
theorem bodd_add (m n : ℤ) : bodd (m + n) = xor (bodd m) (bodd n) := by
  

Proof state:
m n : ℤ
⊢ bodd (m + n) = xor (bodd m) (bodd n)

Next tactic:
cases' m with m m
@[simp]
theorem bodd_add (m n : ℤ) : bodd (m + n) = xor (bodd m) (bodd n) := by
  cases' m with m m <;>
  

Proof state:
case ofNat
n : ℤ
m : ℕ
⊢ bodd (ofNat m + n) = xor (bodd (ofNat m)) (bodd n)

Next tactic:
cases' n with n n
@[simp]
theorem bodd_add (m n : ℤ) : bodd (m + n) = xor (bodd m) (bodd n) := by
  cases' m with m m <;>
  

Proof state:
case negSucc
n : ℤ
m : ℕ
⊢ bodd (-[m+1] + n) = xor (bodd -[m+1]) (bodd n)

Next tactic:
cases' n with n n
@[simp]
theorem bodd_add (m n : ℤ) : bodd (m + n) = xor (bodd m) (bodd n) := by
  cases' m with m m <;>
  cases' n with n n <;>
  

Proof state:
case ofNat.ofNat
m n : ℕ
⊢ bodd (ofNat m + ofNat n) = xor (bodd (ofNat m)) (bodd (ofNat n))

Next tactic:
simp only [ofNat_eq_coe, ofNat_add_negSucc, negSucc_add_ofNat,
             negSucc_add_negSucc, bodd_subNatNat]
@[simp]
theorem bodd_add (m n : ℤ) : bodd (m + n) = xor (bodd m) (bodd n) := by
  cases' m with m m <;>
  cases' n with n n <;>
  

Proof state:
case ofNat.negSucc
m n : ℕ
⊢ bodd (ofNat m + -[n+1]) = xor (bodd (ofNat m)) (bodd -[n+1])

Next tactic:
simp only [ofNat_eq_coe, ofNat_add_negSucc, negSucc_add_ofNat,
             negSucc_add_negSucc, bodd_subNatNat]
@[simp]
theorem bodd_add (m n : ℤ) : bodd (m + n) = xor (bodd m) (bodd n) := by
  cases' m with m m <;>
  cases' n with n n <;>
  

Proof state:
case negSucc.ofNat
m n : ℕ
⊢ bodd (-[m+1] + ofNat n) = xor (bodd -[m+1]) (bodd (ofNat n))

Next tactic:
simp only [ofNat_eq_coe, ofNat_add_negSucc, negSucc_add_ofNat,
             negSucc_add_negSucc, bodd_subNatNat]
@[simp]
theorem bodd_add (m n : ℤ) : bodd (m + n) = xor (bodd m) (bodd n) := by
  cases' m with m m <;>
  cases' n with n n <;>
  

Proof state:
case negSucc.negSucc
m n : ℕ
⊢ bodd (-[m+1] + -[n+1]) = xor (bodd -[m+1]) (bodd -[n+1])

Next tactic:
simp only [ofNat_eq_coe, ofNat_add_negSucc, negSucc_add_ofNat,
             negSucc_add_negSucc, bodd_subNatNat]