l3lab/ntp-mathlib huggingface dataset:
/-- The following diagram commutes:
```text
TruncatedWittVector p n (zmod p) ----> TruncatedWittVector p m (zmod p)
            |                                        |
            |                                        |
            v                                        v
          zmod (p^n) ----------------------------> zmod (p^m)
```
Here the vertical arrows are `(TruncatedWittVector.zmodEquivTrunc p _).symm`,
the horizontal arrow at the top is `ZMod.castHom`,
and the horizontal arrow at the bottom is `TruncatedWittVector.truncate`.
-/
theorem commutes_symm {m : ℕ} (hm : n ≤ m) :
    (zmodEquivTrunc p n).symm.toRingHom.comp (truncate hm) =
      (ZMod.castHom (pow_dvd_pow p hm) _).comp (zmodEquivTrunc p m).symm.toRingHom :=
  by 

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
⊢ RingHom.comp (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p n))) (truncate hm) =
    RingHom.comp (ZMod.castHom (_ : p ^ n ∣ p ^ m) (ZMod (p ^ n)))
      (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p m)))

Next tactic:
ext
/-- The following diagram commutes:
```text
TruncatedWittVector p n (zmod p) ----> TruncatedWittVector p m (zmod p)
            |                                        |
            |                                        |
            v                                        v
          zmod (p^n) ----------------------------> zmod (p^m)
```
Here the vertical arrows are `(TruncatedWittVector.zmodEquivTrunc p _).symm`,
the horizontal arrow at the top is `ZMod.castHom`,
and the horizontal arrow at the bottom is `TruncatedWittVector.truncate`.
-/
theorem commutes_symm {m : ℕ} (hm : n ≤ m) :
    (zmodEquivTrunc p n).symm.toRingHom.comp (truncate hm) =
      (ZMod.castHom (pow_dvd_pow p hm) _).comp (zmodEquivTrunc p m).symm.toRingHom :=
  by ext; 

Proof state:
case a
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
R : Type u_1
inst✝ : CommRing R
m : ℕ
hm : n ≤ m
x✝ : TruncatedWittVector p m (ZMod p)
⊢ (RingHom.comp (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p n))) (truncate hm)) x✝ =
    (RingHom.comp (ZMod.castHom (_ : p ^ n ∣ p ^ m) (ZMod (p ^ n)))
        (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p m))))
      x✝

Next tactic:
apply commutes_symm'
theorem toZModPow_compat (m n : ℕ) (h : m ≤ n) :
    (ZMod.castHom (pow_dvd_pow p h) (ZMod (p ^ m))).comp (toZModPow p n) = toZModPow p m :=
  calc
    (ZMod.castHom _ (ZMod (p ^ m))).comp ((zmodEquivTrunc p n).symm.toRingHom.comp (truncate n))
    _ = ((zmodEquivTrunc p m).symm.toRingHom.comp (TruncatedWittVector.truncate h)).comp
          (truncate n) := by
      

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
m n : ℕ
h : m ≤ n
⊢ RingHom.comp (ZMod.castHom (_ : p ^ m ∣ p ^ n) (ZMod (p ^ m)))
      (RingHom.comp (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p n))) (truncate n)) =
    RingHom.comp
      (RingHom.comp (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p m))) (TruncatedWittVector.truncate h))
      (truncate n)

Next tactic:
rw [commutes_symm, RingHom.comp_assoc]
theorem toZModPow_compat (m n : ℕ) (h : m ≤ n) :
    (ZMod.castHom (pow_dvd_pow p h) (ZMod (p ^ m))).comp (toZModPow p n) = toZModPow p m :=
  calc
    (ZMod.castHom _ (ZMod (p ^ m))).comp ((zmodEquivTrunc p n).symm.toRingHom.comp (truncate n))
    _ = ((zmodEquivTrunc p m).symm.toRingHom.comp (TruncatedWittVector.truncate h)).comp
          (truncate n) := by
      rw [commutes_symm, RingHom.comp_assoc]
    _ = (zmodEquivTrunc p m).symm.toRingHom.comp (truncate m) := by
      

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
m n : ℕ
h : m ≤ n
⊢ RingHom.comp
      (RingHom.comp (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p m))) (TruncatedWittVector.truncate h))
      (truncate n) =
    RingHom.comp (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p m))) (truncate m)

Next tactic:
rw [RingHom.comp_assoc, truncate_comp_wittVector_truncate]
theorem zmodEquivTrunc_compat (k₁ k₂ : ℕ) (hk : k₁ ≤ k₂) :
    (TruncatedWittVector.truncate hk).comp
        ((zmodEquivTrunc p k₂).toRingHom.comp (PadicInt.toZModPow k₂)) =
      (zmodEquivTrunc p k₁).toRingHom.comp (PadicInt.toZModPow k₁) :=
  by 

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k₁ k₂ : ℕ
hk : k₁ ≤ k₂
⊢ RingHom.comp (TruncatedWittVector.truncate hk)
      (RingHom.comp (RingEquiv.toRingHom (zmodEquivTrunc p k₂)) (PadicInt.toZModPow k₂)) =
    RingHom.comp (RingEquiv.toRingHom (zmodEquivTrunc p k₁)) (PadicInt.toZModPow k₁)

Next tactic:
rw [← RingHom.comp_assoc, commutes, RingHom.comp_assoc,
    PadicInt.zmod_cast_comp_toZModPow _ _ hk]
theorem toPadicInt_comp_fromPadicInt : (toPadicInt p).comp (fromPadicInt p) = RingHom.id ℤ_[p] := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
⊢ RingHom.comp (toPadicInt p) (fromPadicInt p) = RingHom.id ℤ_[p]

Next tactic:
rw [← PadicInt.toZModPow_eq_iff_ext]
theorem toPadicInt_comp_fromPadicInt : (toPadicInt p).comp (fromPadicInt p) = RingHom.id ℤ_[p] := by
  rw [← PadicInt.toZModPow_eq_iff_ext]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
⊢ ∀ (n : ℕ),
    RingHom.comp (PadicInt.toZModPow n) (RingHom.comp (toPadicInt p) (fromPadicInt p)) =
      RingHom.comp (PadicInt.toZModPow n) (RingHom.id ℤ_[p])

Next tactic:
intro n
theorem toPadicInt_comp_fromPadicInt : (toPadicInt p).comp (fromPadicInt p) = RingHom.id ℤ_[p] := by
  rw [← PadicInt.toZModPow_eq_iff_ext]
  intro n
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
⊢ RingHom.comp (PadicInt.toZModPow n) (RingHom.comp (toPadicInt p) (fromPadicInt p)) =
    RingHom.comp (PadicInt.toZModPow n) (RingHom.id ℤ_[p])

Next tactic:
rw [← RingHom.comp_assoc, toPadicInt, PadicInt.lift_spec]
theorem toPadicInt_comp_fromPadicInt : (toPadicInt p).comp (fromPadicInt p) = RingHom.id ℤ_[p] := by
  rw [← PadicInt.toZModPow_eq_iff_ext]
  intro n
  rw [← RingHom.comp_assoc, toPadicInt, PadicInt.lift_spec]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
⊢ RingHom.comp (toZModPow p n) (fromPadicInt p) = RingHom.comp (PadicInt.toZModPow n) (RingHom.id ℤ_[p])

Next tactic:
simp only [fromPadicInt, toZModPow, RingHom.comp_id]
theorem toPadicInt_comp_fromPadicInt : (toPadicInt p).comp (fromPadicInt p) = RingHom.id ℤ_[p] := by
  rw [← PadicInt.toZModPow_eq_iff_ext]
  intro n
  rw [← RingHom.comp_assoc, toPadicInt, PadicInt.lift_spec]
  simp only [fromPadicInt, toZModPow, RingHom.comp_id]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
⊢ RingHom.comp (RingHom.comp (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p n))) (truncate n))
      (lift (fun k => RingHom.comp (RingEquiv.toRingHom (zmodEquivTrunc p k)) (PadicInt.toZModPow k))
        (_ :
          ∀ (k₁ k₂ : ℕ) (hk : k₁ ≤ k₂),
            RingHom.comp (TruncatedWittVector.truncate hk)
                (RingHom.comp (RingEquiv.toRingHom (zmodEquivTrunc p k₂)) (PadicInt.toZModPow k₂)) =
              RingHom.comp (RingEquiv.toRingHom (zmodEquivTrunc p k₁)) (PadicInt.toZModPow k₁))) =
    PadicInt.toZModPow n

Next tactic:
rw [RingHom.comp_assoc, truncate_comp_lift, ← RingHom.comp_assoc]
theorem toPadicInt_comp_fromPadicInt : (toPadicInt p).comp (fromPadicInt p) = RingHom.id ℤ_[p] := by
  rw [← PadicInt.toZModPow_eq_iff_ext]
  intro n
  rw [← RingHom.comp_assoc, toPadicInt, PadicInt.lift_spec]
  simp only [fromPadicInt, toZModPow, RingHom.comp_id]
  rw [RingHom.comp_assoc, truncate_comp_lift, ← RingHom.comp_assoc]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
⊢ RingHom.comp
      (RingHom.comp (RingEquiv.toRingHom (RingEquiv.symm (zmodEquivTrunc p n)))
        (RingEquiv.toRingHom (zmodEquivTrunc p n)))
      (PadicInt.toZModPow n) =
    PadicInt.toZModPow n

Next tactic:
simp only [RingEquiv.symm_toRingHom_comp_toRingHom, RingHom.id_comp]
theorem toPadicInt_comp_fromPadicInt_ext (x) :
    (toPadicInt p).comp (fromPadicInt p) x = RingHom.id ℤ_[p] x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
x : ℤ_[p]
⊢ (RingHom.comp (toPadicInt p) (fromPadicInt p)) x = (RingHom.id ℤ_[p]) x

Next tactic:
rw [toPadicInt_comp_fromPadicInt]
theorem fromPadicInt_comp_toPadicInt :
    (fromPadicInt p).comp (toPadicInt p) = RingHom.id (𝕎 (ZMod p)) := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
⊢ RingHom.comp (fromPadicInt p) (toPadicInt p) = RingHom.id (𝕎 (ZMod p))

Next tactic:
apply WittVector.hom_ext
theorem fromPadicInt_comp_toPadicInt :
    (fromPadicInt p).comp (toPadicInt p) = RingHom.id (𝕎 (ZMod p)) := by
  apply WittVector.hom_ext
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
⊢ ∀ (k : ℕ),
    RingHom.comp (truncate k) (RingHom.comp (fromPadicInt p) (toPadicInt p)) =
      RingHom.comp (truncate k) (RingHom.id (𝕎 (ZMod p)))

Next tactic:
intro n
theorem fromPadicInt_comp_toPadicInt :
    (fromPadicInt p).comp (toPadicInt p) = RingHom.id (𝕎 (ZMod p)) := by
  apply WittVector.hom_ext
  intro n
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
⊢ RingHom.comp (truncate n) (RingHom.comp (fromPadicInt p) (toPadicInt p)) =
    RingHom.comp (truncate n) (RingHom.id (𝕎 (ZMod p)))

Next tactic:
rw [fromPadicInt, ← RingHom.comp_assoc, truncate_comp_lift, RingHom.comp_assoc]
theorem fromPadicInt_comp_toPadicInt :
    (fromPadicInt p).comp (toPadicInt p) = RingHom.id (𝕎 (ZMod p)) := by
  apply WittVector.hom_ext
  intro n
  rw [fromPadicInt, ← RingHom.comp_assoc, truncate_comp_lift, RingHom.comp_assoc]
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
n : ℕ
⊢ RingHom.comp (RingEquiv.toRingHom (zmodEquivTrunc p n)) (RingHom.comp (PadicInt.toZModPow n) (toPadicInt p)) =
    RingHom.comp (truncate n) (RingHom.id (𝕎 (ZMod p)))

Next tactic:
simp only [toPadicInt, toZModPow, RingHom.comp_id, PadicInt.lift_spec, RingHom.id_comp, ←
    RingHom.comp_assoc, RingEquiv.toRingHom_comp_symm_toRingHom]
theorem fromPadicInt_comp_toPadicInt_ext (x) :
    (fromPadicInt p).comp (toPadicInt p) x = RingHom.id (𝕎 (ZMod p)) x := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
x : 𝕎 (ZMod p)
⊢ (RingHom.comp (fromPadicInt p) (toPadicInt p)) x = (RingHom.id (𝕎 (ZMod p))) x

Next tactic:
rw [fromPadicInt_comp_toPadicInt]
@[simp]
theorem divOf_zero (x : k[G]) : x /ᵒᶠ 0 = x := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
⊢ x /ᵒᶠ 0 = x

Next tactic:
refine Finsupp.ext fun _ => ?_
@[simp]
theorem divOf_zero (x : k[G]) : x /ᵒᶠ 0 = x := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
x✝ : G
⊢ (x /ᵒᶠ 0) x✝ = x x✝

Next tactic:
simp only [AddMonoidAlgebra.divOf_apply, zero_add]
theorem divOf_add (x : k[G]) (a b : G) : x /ᵒᶠ (a + b) = x /ᵒᶠ a /ᵒᶠ b := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
a b : G
⊢ x /ᵒᶠ (a + b) = x /ᵒᶠ a /ᵒᶠ b

Next tactic:
refine Finsupp.ext fun _ => ?_
theorem divOf_add (x : k[G]) (a b : G) : x /ᵒᶠ (a + b) = x /ᵒᶠ a /ᵒᶠ b := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
a b x✝ : G
⊢ (x /ᵒᶠ (a + b)) x✝ = (x /ᵒᶠ a /ᵒᶠ b) x✝

Next tactic:
simp only [AddMonoidAlgebra.divOf_apply, add_assoc]
theorem of'_mul_divOf (a : G) (x : k[G]) : of' k G a * x /ᵒᶠ a = x := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
a : G
x : k[G]
⊢ of' k G a * x /ᵒᶠ a = x

Next tactic:
refine Finsupp.ext fun _ => ?_
theorem of'_mul_divOf (a : G) (x : k[G]) : of' k G a * x /ᵒᶠ a = x := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
a : G
x : k[G]
x✝ : G
⊢ (of' k G a * x /ᵒᶠ a) x✝ = x x✝

Next tactic:
rw [AddMonoidAlgebra.divOf_apply, of'_apply, single_mul_apply_aux, one_mul]
theorem of'_mul_divOf (a : G) (x : k[G]) : of' k G a * x /ᵒᶠ a = x := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  rw [AddMonoidAlgebra.divOf_apply, of'_apply, single_mul_apply_aux, one_mul]
  

Proof state:
case H
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
a : G
x : k[G]
x✝ : G
⊢ ∀ (a_1 : G), a + a_1 = a + x✝ ↔ a_1 = x✝

Next tactic:
intro c
theorem of'_mul_divOf (a : G) (x : k[G]) : of' k G a * x /ᵒᶠ a = x := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  rw [AddMonoidAlgebra.divOf_apply, of'_apply, single_mul_apply_aux, one_mul]
  intro c
  

Proof state:
case H
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
a : G
x : k[G]
x✝ c : G
⊢ a + c = a + x✝ ↔ c = x✝

Next tactic:
exact add_right_inj _
theorem mul_of'_divOf (x : k[G]) (a : G) : x * of' k G a /ᵒᶠ a = x := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
a : G
⊢ x * of' k G a /ᵒᶠ a = x

Next tactic:
refine Finsupp.ext fun _ => ?_
theorem mul_of'_divOf (x : k[G]) (a : G) : x * of' k G a /ᵒᶠ a = x := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
a x✝ : G
⊢ (x * of' k G a /ᵒᶠ a) x✝ = x x✝

Next tactic:
rw [AddMonoidAlgebra.divOf_apply, of'_apply, mul_single_apply_aux, mul_one]
theorem mul_of'_divOf (x : k[G]) (a : G) : x * of' k G a /ᵒᶠ a = x := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  rw [AddMonoidAlgebra.divOf_apply, of'_apply, mul_single_apply_aux, mul_one]
  

Proof state:
case H
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
a x✝ : G
⊢ ∀ (a_1 : G), a_1 + a = a + x✝ ↔ a_1 = x✝

Next tactic:
intro c
theorem mul_of'_divOf (x : k[G]) (a : G) : x * of' k G a /ᵒᶠ a = x := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  rw [AddMonoidAlgebra.divOf_apply, of'_apply, mul_single_apply_aux, mul_one]
  intro c
  

Proof state:
case H
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
a x✝ c : G
⊢ c + a = a + x✝ ↔ c = x✝

Next tactic:
rw [add_comm]
theorem mul_of'_divOf (x : k[G]) (a : G) : x * of' k G a /ᵒᶠ a = x := by
  refine Finsupp.ext fun _ => ?_  -- porting note: `ext` doesn't work
  rw [AddMonoidAlgebra.divOf_apply, of'_apply, mul_single_apply_aux, mul_one]
  intro c
  rw [add_comm]
  

Proof state:
case H
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
a x✝ c : G
⊢ a + c = a + x✝ ↔ c = x✝

Next tactic:
exact add_right_inj _
theorem of'_divOf (a : G) : of' k G a /ᵒᶠ a = 1 := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
a : G
⊢ of' k G a /ᵒᶠ a = 1

Next tactic:
simpa only [one_mul] using mul_of'_divOf (1 : k[G]) a
@[simp]
theorem modOf_apply_of_exists_add (x : k[G]) (g : G) (g' : G)
    (h : ∃ d, g' = g + d) : (x %ᵒᶠ g) g' = 0 :=
  Finsupp.filter_apply_neg _ _ <| by 

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
h : ∃ d, g' = g + d
⊢ ¬¬∃ g₂, g' = g + g₂

Next tactic:
rwa [Classical.not_not]
theorem of'_mul_modOf (g : G) (x : k[G]) : of' k G g * x %ᵒᶠ g = 0 := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
g : G
x : k[G]
⊢ of' k G g * x %ᵒᶠ g = 0

Next tactic:
refine Finsupp.ext fun g' => ?_
theorem of'_mul_modOf (g : G) (x : k[G]) : of' k G g * x %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
g : G
x : k[G]
g' : G
⊢ (of' k G g * x %ᵒᶠ g) g' = 0 g'

Next tactic:
rw [Finsupp.zero_apply]
theorem of'_mul_modOf (g : G) (x : k[G]) : of' k G g * x %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  rw [Finsupp.zero_apply]
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
g : G
x : k[G]
g' : G
⊢ (of' k G g * x %ᵒᶠ g) g' = 0

Next tactic:
obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
theorem of'_mul_modOf (g : G) (x : k[G]) : of' k G g * x %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  rw [Finsupp.zero_apply]
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  · 

Proof state:
case inl.intro
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
g : G
x : k[G]
d : G
⊢ (of' k G g * x %ᵒᶠ g) (g + d) = 0

Next tactic:
rw [modOf_apply_self_add]
theorem of'_mul_modOf (g : G) (x : k[G]) : of' k G g * x %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  rw [Finsupp.zero_apply]
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  · rw [modOf_apply_self_add]
  · 

Proof state:
case inr
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
g : G
x : k[G]
g' : G
h : ¬∃ d, g' = g + d
⊢ (of' k G g * x %ᵒᶠ g) g' = 0

Next tactic:
rw [modOf_apply_of_not_exists_add _ _ _ h, of'_apply, single_mul_apply_of_not_exists_add _ _ h]
theorem mul_of'_modOf (x : k[G]) (g : G) : x * of' k G g %ᵒᶠ g = 0 := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g : G
⊢ x * of' k G g %ᵒᶠ g = 0

Next tactic:
refine Finsupp.ext fun g' => ?_
theorem mul_of'_modOf (x : k[G]) (g : G) : x * of' k G g %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
⊢ (x * of' k G g %ᵒᶠ g) g' = 0 g'

Next tactic:
rw [Finsupp.zero_apply]
theorem mul_of'_modOf (x : k[G]) (g : G) : x * of' k G g %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  rw [Finsupp.zero_apply]
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
⊢ (x * of' k G g %ᵒᶠ g) g' = 0

Next tactic:
obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
theorem mul_of'_modOf (x : k[G]) (g : G) : x * of' k G g %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  rw [Finsupp.zero_apply]
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  · 

Proof state:
case inl.intro
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g d : G
⊢ (x * of' k G g %ᵒᶠ g) (g + d) = 0

Next tactic:
rw [modOf_apply_self_add]
theorem mul_of'_modOf (x : k[G]) (g : G) : x * of' k G g %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  rw [Finsupp.zero_apply]
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  · rw [modOf_apply_self_add]
  · 

Proof state:
case inr
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
h : ¬∃ d, g' = g + d
⊢ (x * of' k G g %ᵒᶠ g) g' = 0

Next tactic:
rw [modOf_apply_of_not_exists_add _ _ _ h, of'_apply, mul_single_apply_of_not_exists_add]
theorem mul_of'_modOf (x : k[G]) (g : G) : x * of' k G g %ᵒᶠ g = 0 := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext g'` doesn't work
  rw [Finsupp.zero_apply]
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  · rw [modOf_apply_self_add]
  · rw [modOf_apply_of_not_exists_add _ _ _ h, of'_apply, mul_single_apply_of_not_exists_add]
    

Proof state:
case inr.h
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
h : ¬∃ d, g' = g + d
⊢ ¬∃ d, g' = d + g

Next tactic:
simpa only [add_comm] using h
theorem of'_modOf (g : G) : of' k G g %ᵒᶠ g = 0 := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
g : G
⊢ of' k G g %ᵒᶠ g = 0

Next tactic:
simpa only [one_mul] using mul_of'_modOf (1 : k[G]) g
theorem divOf_add_modOf (x : k[G]) (g : G) :
    of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x := by
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g : G
⊢ of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x

Next tactic:
refine Finsupp.ext fun g' => ?_
theorem divOf_add_modOf (x : k[G]) (g : G) :
    of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext` doesn't work
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
⊢ (of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g) g' = x g'

Next tactic:
rw [Finsupp.add_apply]
theorem divOf_add_modOf (x : k[G]) (g : G) :
    of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext` doesn't work
  rw [Finsupp.add_apply] -- porting note: changed from `simp_rw` which can't see through the type
  

Proof state:
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
⊢ (of' k G g * (x /ᵒᶠ g)) g' + (x %ᵒᶠ g) g' = x g'

Next tactic:
obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
theorem divOf_add_modOf (x : k[G]) (g : G) :
    of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext` doesn't work
  rw [Finsupp.add_apply] -- porting note: changed from `simp_rw` which can't see through the type
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  

Proof state:
case inl.intro
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g d : G
⊢ (of' k G g * (x /ᵒᶠ g)) (g + d) + (x %ᵒᶠ g) (g + d) = x (g + d)
case inr
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
h : ¬∃ d, g' = g + d
⊢ (of' k G g * (x /ᵒᶠ g)) g' + (x %ᵒᶠ g) g' = x g'

Next tactic:
swap
theorem divOf_add_modOf (x : k[G]) (g : G) :
    of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext` doesn't work
  rw [Finsupp.add_apply] -- porting note: changed from `simp_rw` which can't see through the type
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  swap
  · 

Proof state:
case inr
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g g' : G
h : ¬∃ d, g' = g + d
⊢ (of' k G g * (x /ᵒᶠ g)) g' + (x %ᵒᶠ g) g' = x g'

Next tactic:
rw [modOf_apply_of_not_exists_add x _ _ h, of'_apply, single_mul_apply_of_not_exists_add _ _ h,
      zero_add]
theorem divOf_add_modOf (x : k[G]) (g : G) :
    of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext` doesn't work
  rw [Finsupp.add_apply] -- porting note: changed from `simp_rw` which can't see through the type
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  swap
  · rw [modOf_apply_of_not_exists_add x _ _ h, of'_apply, single_mul_apply_of_not_exists_add _ _ h,
      zero_add]
  · 

Proof state:
case inl.intro
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g d : G
⊢ (of' k G g * (x /ᵒᶠ g)) (g + d) + (x %ᵒᶠ g) (g + d) = x (g + d)

Next tactic:
rw [modOf_apply_self_add, add_zero]
theorem divOf_add_modOf (x : k[G]) (g : G) :
    of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext` doesn't work
  rw [Finsupp.add_apply] -- porting note: changed from `simp_rw` which can't see through the type
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  swap
  · rw [modOf_apply_of_not_exists_add x _ _ h, of'_apply, single_mul_apply_of_not_exists_add _ _ h,
      zero_add]
  · rw [modOf_apply_self_add, add_zero]
    

Proof state:
case inl.intro
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g d : G
⊢ (of' k G g * (x /ᵒᶠ g)) (g + d) = x (g + d)

Next tactic:
rw [of'_apply, single_mul_apply_aux _ _ _, one_mul, divOf_apply]
theorem divOf_add_modOf (x : k[G]) (g : G) :
    of' k G g * (x /ᵒᶠ g) + x %ᵒᶠ g = x := by
  refine Finsupp.ext fun g' => ?_  -- porting note: `ext` doesn't work
  rw [Finsupp.add_apply] -- porting note: changed from `simp_rw` which can't see through the type
  obtain ⟨d, rfl⟩ | h := em (∃ d, g' = g + d)
  swap
  · rw [modOf_apply_of_not_exists_add x _ _ h, of'_apply, single_mul_apply_of_not_exists_add _ _ h,
      zero_add]
  · rw [modOf_apply_self_add, add_zero]
    rw [of'_apply, single_mul_apply_aux _ _ _, one_mul, divOf_apply]
    

Proof state:
case inl.intro.H
k : Type u_1
G : Type u_2
inst✝¹ : Semiring k
inst✝ : AddCancelCommMonoid G
x : k[G]
g d : G
⊢ ∀ (a : G), g + a = g + d ↔ a = d

Next tactic:
intro a