l3lab/ntp-mathlib huggingface dataset:
theorem hyperoperation_ge_three_one (n : ℕ) : ∀ k : ℕ, hyperoperation (n + 3) 1 k = 1 := by
  induction' n with nn nih
  · intro k
    rw [hyperoperation_three]
    dsimp
    

Proof state:
case zero
k : ℕ
⊢ 1 ^ k = 1

Next tactic:
rw [one_pow]
theorem hyperoperation_ge_three_one (n : ℕ) : ∀ k : ℕ, hyperoperation (n + 3) 1 k = 1 := by
  induction' n with nn nih
  · intro k
    rw [hyperoperation_three]
    dsimp
    rw [one_pow]
  · 

Proof state:
case succ
nn : ℕ
nih : ∀ (k : ℕ), hyperoperation (nn + 3) 1 k = 1
⊢ ∀ (k : ℕ), hyperoperation (Nat.succ nn + 3) 1 k = 1

Next tactic:
intro k
theorem hyperoperation_ge_three_one (n : ℕ) : ∀ k : ℕ, hyperoperation (n + 3) 1 k = 1 := by
  induction' n with nn nih
  · intro k
    rw [hyperoperation_three]
    dsimp
    rw [one_pow]
  · intro k
    

Proof state:
case succ
nn : ℕ
nih : ∀ (k : ℕ), hyperoperation (nn + 3) 1 k = 1
k : ℕ
⊢ hyperoperation (Nat.succ nn + 3) 1 k = 1

Next tactic:
cases k
theorem hyperoperation_ge_three_one (n : ℕ) : ∀ k : ℕ, hyperoperation (n + 3) 1 k = 1 := by
  induction' n with nn nih
  · intro k
    rw [hyperoperation_three]
    dsimp
    rw [one_pow]
  · intro k
    cases k
    · 

Proof state:
case succ.zero
nn : ℕ
nih : ∀ (k : ℕ), hyperoperation (nn + 3) 1 k = 1
⊢ hyperoperation (Nat.succ nn + 3) 1 Nat.zero = 1

Next tactic:
rw [hyperoperation_ge_three_eq_one]
theorem hyperoperation_ge_three_one (n : ℕ) : ∀ k : ℕ, hyperoperation (n + 3) 1 k = 1 := by
  induction' n with nn nih
  · intro k
    rw [hyperoperation_three]
    dsimp
    rw [one_pow]
  · intro k
    cases k
    · rw [hyperoperation_ge_three_eq_one]
    · 

Proof state:
case succ.succ
nn : ℕ
nih : ∀ (k : ℕ), hyperoperation (nn + 3) 1 k = 1
n✝ : ℕ
⊢ hyperoperation (Nat.succ nn + 3) 1 (Nat.succ n✝) = 1

Next tactic:
rw [hyperoperation_recursion, nih]
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  

Proof state:
n k : ℕ
⊢ hyperoperation (n + 4) 0 k = if Even k then 1 else 0

Next tactic:
induction' k with kk kih
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  induction' k with kk kih
  · 

Proof state:
case zero
n : ℕ
⊢ hyperoperation (n + 4) 0 Nat.zero = if Even Nat.zero then 1 else 0

Next tactic:
rw [hyperoperation_ge_three_eq_one]
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  induction' k with kk kih
  · rw [hyperoperation_ge_three_eq_one]
    

Proof state:
case zero
n : ℕ
⊢ 1 = if Even Nat.zero then 1 else 0

Next tactic:
simp only [Nat.zero_eq, even_zero, if_true]
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  induction' k with kk kih
  · rw [hyperoperation_ge_three_eq_one]
    simp only [Nat.zero_eq, even_zero, if_true]
  · 

Proof state:
case succ
n kk : ℕ
kih : hyperoperation (n + 4) 0 kk = if Even kk then 1 else 0
⊢ hyperoperation (n + 4) 0 (Nat.succ kk) = if Even (Nat.succ kk) then 1 else 0

Next tactic:
rw [hyperoperation_recursion]
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  induction' k with kk kih
  · rw [hyperoperation_ge_three_eq_one]
    simp only [Nat.zero_eq, even_zero, if_true]
  · rw [hyperoperation_recursion]
    

Proof state:
case succ
n kk : ℕ
kih : hyperoperation (n + 4) 0 kk = if Even kk then 1 else 0
⊢ hyperoperation (n + 3) 0 (hyperoperation (n + 3 + 1) 0 kk) = if Even (Nat.succ kk) then 1 else 0

Next tactic:
rw [kih]
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  induction' k with kk kih
  · rw [hyperoperation_ge_three_eq_one]
    simp only [Nat.zero_eq, even_zero, if_true]
  · rw [hyperoperation_recursion]
    rw [kih]
    

Proof state:
case succ
n kk : ℕ
kih : hyperoperation (n + 4) 0 kk = if Even kk then 1 else 0
⊢ hyperoperation (n + 3) 0 (if Even kk then 1 else 0) = if Even (Nat.succ kk) then 1 else 0

Next tactic:
simp_rw [Nat.even_add_one]
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  induction' k with kk kih
  · rw [hyperoperation_ge_three_eq_one]
    simp only [Nat.zero_eq, even_zero, if_true]
  · rw [hyperoperation_recursion]
    rw [kih]
    simp_rw [Nat.even_add_one]
    

Proof state:
case succ
n kk : ℕ
kih : hyperoperation (n + 4) 0 kk = if Even kk then 1 else 0
⊢ hyperoperation (n + 3) 0 (if Even kk then 1 else 0) = if ¬Even kk then 1 else 0

Next tactic:
split_ifs
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  induction' k with kk kih
  · rw [hyperoperation_ge_three_eq_one]
    simp only [Nat.zero_eq, even_zero, if_true]
  · rw [hyperoperation_recursion]
    rw [kih]
    simp_rw [Nat.even_add_one]
    split_ifs
    · 

Proof state:
case pos
n kk : ℕ
kih : hyperoperation (n + 4) 0 kk = if Even kk then 1 else 0
h✝ : Even kk
⊢ hyperoperation (n + 3) 0 1 = 0

Next tactic:
exact hyperoperation_ge_two_eq_self (n + 1) 0
theorem hyperoperation_ge_four_zero (n k : ℕ) :
    hyperoperation (n + 4) 0 k = if Even k then 1 else 0 := by
  induction' k with kk kih
  · rw [hyperoperation_ge_three_eq_one]
    simp only [Nat.zero_eq, even_zero, if_true]
  · rw [hyperoperation_recursion]
    rw [kih]
    simp_rw [Nat.even_add_one]
    split_ifs
    · exact hyperoperation_ge_two_eq_self (n + 1) 0
    · 

Proof state:
case neg
n kk : ℕ
kih : hyperoperation (n + 4) 0 kk = if Even kk then 1 else 0
h✝ : ¬Even kk
⊢ hyperoperation (n + 3) 0 0 = 1

Next tactic:
exact hyperoperation_ge_three_eq_one n 0
theorem mod_add_div' (m k : R) : m % k + m / k * k = m := by
  

Proof state:
R : Type u
inst✝ : EuclideanDomain R
m k : R
⊢ m % k + m / k * k = m

Next tactic:
rw [mul_comm]
theorem mod_add_div' (m k : R) : m % k + m / k * k = m := by
  rw [mul_comm]
  

Proof state:
R : Type u
inst✝ : EuclideanDomain R
m k : R
⊢ m % k + k * (m / k) = m

Next tactic:
exact mod_add_div _ _
theorem div_add_mod' (m k : R) : m / k * k + m % k = m := by
  

Proof state:
R : Type u
inst✝ : EuclideanDomain R
m k : R
⊢ m / k * k + m % k = m

Next tactic:
rw [mul_comm]
theorem div_add_mod' (m k : R) : m / k * k + m % k = m := by
  rw [mul_comm]
  

Proof state:
R : Type u
inst✝ : EuclideanDomain R
m k : R
⊢ k * (m / k) + m % k = m

Next tactic:
exact div_add_mod _ _
theorem mod_eq_sub_mul_div {R : Type*} [EuclideanDomain R] (a b : R) : a % b = a - b * (a / b) :=
  calc
    a % b = b * (a / b) + a % b - b * (a / b) := (add_sub_cancel' _ _).symm
    _ = a - b * (a / b) := by 

Proof state:
R✝ : Type u
inst✝¹ : EuclideanDomain R✝
R : Type u_1
inst✝ : EuclideanDomain R
a b : R
⊢ b * (a / b) + a % b - b * (a / b) = a - b * (a / b)

Next tactic:
rw [div_add_mod]
theorem mul_right_not_lt {a : R} (b) (h : a ≠ 0) : ¬a * b ≺ b := by
  

Proof state:
R : Type u
inst✝ : EuclideanDomain R
a b : R
h : a ≠ 0
⊢ ¬a * b ≺ b

Next tactic:
rw [mul_comm]
theorem mul_right_not_lt {a : R} (b) (h : a ≠ 0) : ¬a * b ≺ b := by
  rw [mul_comm]
  

Proof state:
R : Type u
inst✝ : EuclideanDomain R
a b : R
h : a ≠ 0
⊢ ¬b * a ≺ b

Next tactic:
exact mul_left_not_lt b h
@[simp]
theorem mod_zero (a : R) : a % 0 = a := by 

Proof state:
R : Type u
inst✝ : EuclideanDomain R
a : R
⊢ a % 0 = a

Next tactic:
simpa only [zero_mul, zero_add] using div_add_mod a 0
theorem lt_one (a : R) : a ≺ (1 : R) → a = 0 :=
  haveI := Classical.dec
  not_imp_not.1 fun h => by 

Proof state:
R : Type u
inst✝ : EuclideanDomain R
a : R
this : (p : Prop) → Decidable p
h : ¬a = 0
⊢ ¬a ≺ 1

Next tactic:
simpa only [one_mul] using mul_left_not_lt 1 h
theorem val_dvd_le : ∀ a b : R, b ∣ a → a ≠ 0 → ¬a ≺ b
  | _, b, ⟨d, rfl⟩, ha => mul_left_not_lt b (mt (by 

Proof state:
R : Type u
inst✝ : EuclideanDomain R
b d : R
ha : b * d ≠ 0
⊢ d = 0 → b * d = 0

Next tactic:
rintro rfl
theorem val_dvd_le : ∀ a b : R, b ∣ a → a ≠ 0 → ¬a ≺ b
  | _, b, ⟨d, rfl⟩, ha => mul_left_not_lt b (mt (by rintro rfl; 

Proof state:
R : Type u
inst✝ : EuclideanDomain R
b : R
ha : b * 0 ≠ 0
⊢ b * 0 = 0

Next tactic:
exact mul_zero _
@[elab_as_elim]
theorem GCD.induction {P : R → R → Prop} (a b : R) (H0 : ∀ x, P 0 x)
    (H1 : ∀ a b, a ≠ 0 → P (b % a) a → P a b) : P a b :=
  if a0 : a = 0 then by
    -- Porting note: required for hygiene, the equation compiler introduces a dummy variable `x`
    -- See https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/unnecessarily.20tombstoned.20argument/near/314573315
    

Proof state:
R : Type u
inst✝ : EuclideanDomain R
P : R → R → Prop
a b : R
H0 : ∀ (x : R), P 0 x
H1 : ∀ (a b : R), a ≠ 0 → P (b % a) a → P a b
a0 : a = 0
⊢ P a b

Next tactic:
change P a b
@[elab_as_elim]
theorem GCD.induction {P : R → R → Prop} (a b : R) (H0 : ∀ x, P 0 x)
    (H1 : ∀ a b, a ≠ 0 → P (b % a) a → P a b) : P a b :=
  if a0 : a = 0 then by
    -- Porting note: required for hygiene, the equation compiler introduces a dummy variable `x`
    -- See https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/unnecessarily.20tombstoned.20argument/near/314573315
    change P a b
    

Proof state:
R : Type u
inst✝ : EuclideanDomain R
P : R → R → Prop
a b : R
H0 : ∀ (x : R), P 0 x
H1 : ∀ (a b : R), a ≠ 0 → P (b % a) a → P a b
a0 : a = 0
⊢ P a b

Next tactic:
exact a0.symm ▸ H0 b
@[simp]
theorem gcd_zero_left (a : R) : gcd 0 a = a := by
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
a : R
⊢ gcd 0 a = a

Next tactic:
rw [gcd]
@[simp]
theorem gcd_zero_left (a : R) : gcd 0 a = a := by
  rw [gcd]
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
a : R
⊢ (if a0 : 0 = 0 then a
    else
      let_fun x := (_ : a % 0 ≺ 0);
      gcd (a % 0) 0) =
    a

Next tactic:
exact if_pos rfl
@[simp]
theorem xgcd_zero_left {s t r' s' t' : R} : xgcdAux 0 s t r' s' t' = (r', s', t') := by
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
s t r' s' t' : R
⊢ xgcdAux 0 s t r' s' t' = (r', s', t')

Next tactic:
unfold xgcdAux
@[simp]
theorem xgcd_zero_left {s t r' s' t' : R} : xgcdAux 0 s t r' s' t' = (r', s', t') := by
  unfold xgcdAux
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
s t r' s' t' : R
⊢ (if _hr : 0 = 0 then (r', s', t')
    else
      let q := r' / 0;
      let_fun x := (_ : r' % 0 ≺ 0);
      xgcdAux (r' % 0) (s' - q * s) (t' - q * t) 0 s t) =
    (r', s', t')

Next tactic:
exact if_pos rfl
theorem xgcdAux_rec {r s t r' s' t' : R} (h : r ≠ 0) :
    xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t := by
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
r s t r' s' t' : R
h : r ≠ 0
⊢ xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t

Next tactic:
conv =>
    lhs
    rw [xgcdAux]
theorem xgcdAux_rec {r s t r' s' t' : R} (h : r ≠ 0) :
    xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t := by
  conv =>
    

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
r s t r' s' t' : R
h : r ≠ 0
| xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t

Next tactic:
lhs
    rw [xgcdAux]
theorem xgcdAux_rec {r s t r' s' t' : R} (h : r ≠ 0) :
    xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t := by
  conv =>
    

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
r s t r' s' t' : R
h : r ≠ 0
| xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t

Next tactic:
lhs
theorem xgcdAux_rec {r s t r' s' t' : R} (h : r ≠ 0) :
    xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t := by
  conv =>
    lhs
    

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
r s t r' s' t' : R
h : r ≠ 0
| xgcdAux r s t r' s' t'

Next tactic:
rw [xgcdAux]
theorem xgcdAux_rec {r s t r' s' t' : R} (h : r ≠ 0) :
    xgcdAux r s t r' s' t' = xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t := by
  conv =>
    lhs
    rw [xgcdAux]
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
r s t r' s' t' : R
h : r ≠ 0
⊢ (if _hr : r = 0 then (r', s', t')
    else
      let q := r' / r;
      let_fun x := (_ : r' % r ≺ r);
      xgcdAux (r' % r) (s' - q * s) (t' - q * t) r s t) =
    xgcdAux (r' % r) (s' - r' / r * s) (t' - r' / r * t) r s t

Next tactic:
exact if_neg h
@[simp]
theorem gcdA_zero_left {s : R} : gcdA 0 s = 0 := by
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
s : R
⊢ gcdA 0 s = 0

Next tactic:
unfold gcdA
@[simp]
theorem gcdA_zero_left {s : R} : gcdA 0 s = 0 := by
  unfold gcdA
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
s : R
⊢ (xgcd 0 s).fst = 0

Next tactic:
rw [xgcd, xgcd_zero_left]
@[simp]
theorem gcdB_zero_left {s : R} : gcdB 0 s = 1 := by
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
s : R
⊢ gcdB 0 s = 1

Next tactic:
unfold gcdB
@[simp]
theorem gcdB_zero_left {s : R} : gcdB 0 s = 1 := by
  unfold gcdB
  

Proof state:
R : Type u
inst✝¹ : EuclideanDomain R
inst✝ : DecidableEq R
s : R
⊢ (xgcd 0 s).snd = 1

Next tactic:
rw [xgcd, xgcd_zero_left]
@[simp]
theorem nsmul_one [AddMonoidWithOne A] : ∀ n : ℕ, n • (1 : A) = n := by
  

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : AddMonoidWithOne A
⊢ ∀ (n : ℕ), n • 1 = ↑n

Next tactic:
let f : ℕ →+ A :=
  { toFun := fun n ↦ n • (1 : A),
    map_zero' := by simp [zero_nsmul],
    map_add' := by simp [add_nsmul] }
@[simp]
theorem nsmul_one [AddMonoidWithOne A] : ∀ n : ℕ, n • (1 : A) = n := by
  let f : ℕ →+ A :=
  { toFun := fun n ↦ n • (1 : A),
    map_zero' := by 

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : AddMonoidWithOne A
⊢ (fun n => n • 1) 0 = 0

Next tactic:
simp [zero_nsmul]
@[simp]
theorem nsmul_one [AddMonoidWithOne A] : ∀ n : ℕ, n • (1 : A) = n := by
  let f : ℕ →+ A :=
  { toFun := fun n ↦ n • (1 : A),
    map_zero' := by simp [zero_nsmul],
    map_add' := by 

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : AddMonoidWithOne A
⊢ ∀ (x y : ℕ),
    ZeroHom.toFun { toFun := fun n => n • 1, map_zero' := (_ : 0 • 1 = 0) } (x + y) =
      ZeroHom.toFun { toFun := fun n => n • 1, map_zero' := (_ : 0 • 1 = 0) } x +
        ZeroHom.toFun { toFun := fun n => n • 1, map_zero' := (_ : 0 • 1 = 0) } y

Next tactic:
simp [add_nsmul]
@[simp]
theorem nsmul_one [AddMonoidWithOne A] : ∀ n : ℕ, n • (1 : A) = n := by
  let f : ℕ →+ A :=
  { toFun := fun n ↦ n • (1 : A),
    map_zero' := by simp [zero_nsmul],
    map_add' := by simp [add_nsmul] }
  

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : AddMonoidWithOne A
f : ℕ →+ A :=
  { toZeroHom := { toFun := fun n => n • 1, map_zero' := (_ : 0 • 1 = 0) },
    map_add' := (_ : ∀ (a a_1 : ℕ), (a + a_1) • 1 = a • 1 + a_1 • 1) }
⊢ ∀ (n : ℕ), n • 1 = ↑n

Next tactic:
refine' eq_natCast' f _
@[simp]
theorem nsmul_one [AddMonoidWithOne A] : ∀ n : ℕ, n • (1 : A) = n := by
  let f : ℕ →+ A :=
  { toFun := fun n ↦ n • (1 : A),
    map_zero' := by simp [zero_nsmul],
    map_add' := by simp [add_nsmul] }
  refine' eq_natCast' f _
  

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : AddMonoidWithOne A
f : ℕ →+ A :=
  { toZeroHom := { toFun := fun n => n • 1, map_zero' := (_ : 0 • 1 = 0) },
    map_add' := (_ : ∀ (a a_1 : ℕ), (a + a_1) • 1 = a • 1 + a_1 • 1) }
⊢ f 1 = 1

Next tactic:
simp
instance invertiblePow (m : M) [Invertible m] (n : ℕ) :
    Invertible (m ^ n) where
  invOf := ⅟ m ^ n
  invOf_mul_self := by 

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : AddMonoid A
inst✝¹ : AddMonoid B
m : M
inst✝ : Invertible m
n : ℕ
⊢ ⅟m ^ n * m ^ n = 1

Next tactic:
rw [← (commute_invOf m).symm.mul_pow, invOf_mul_self, one_pow]
instance invertiblePow (m : M) [Invertible m] (n : ℕ) :
    Invertible (m ^ n) where
  invOf := ⅟ m ^ n
  invOf_mul_self := by rw [← (commute_invOf m).symm.mul_pow, invOf_mul_self, one_pow]
  mul_invOf_self := by 

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : AddMonoid A
inst✝¹ : AddMonoid B
m : M
inst✝ : Invertible m
n : ℕ
⊢ m ^ n * ⅟m ^ n = 1

Next tactic:
rw [← (commute_invOf m).mul_pow, mul_invOf_self, one_pow]
/-- If a natural power of `x` is a unit, then `x` is a unit. -/
@[to_additive "If a natural multiple of `x` is an additive unit, then `x` is an additive unit."]
def Units.ofPow (u : Mˣ) (x : M) {n : ℕ} (hn : n ≠ 0) (hu : x ^ n = u) : Mˣ :=
  u.leftOfMul x (x ^ (n - 1))
    (by 

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : AddMonoid A
inst✝ : AddMonoid B
u : Mˣ
x : M
n : ℕ
hn : n ≠ 0
hu : x ^ n = ↑u
⊢ x * x ^ (n - 1) = ↑u

Next tactic:
rwa [← _root_.pow_succ, Nat.sub_add_cancel (Nat.succ_le_of_lt <| Nat.pos_of_ne_zero hn)]
@[to_additive (attr := simp)]
theorem Units.pow_ofPowEqOne {x : M} {n : ℕ} (hx : x ^ n = 1) (hn : n ≠ 0) :
    Units.ofPowEqOne x n hx hn ^ n = 1 :=
  Units.ext <| by 

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : AddMonoid A
inst✝ : AddMonoid B
x : M
n : ℕ
hx : x ^ n = 1
hn : n ≠ 0
⊢ ↑(ofPowEqOne x n hx hn ^ n) = ↑1

Next tactic:
simp [hx]
theorem smul_pow [MulAction M N] [IsScalarTower M N N] [SMulCommClass M N N] (k : M) (x : N)
    (p : ℕ) : (k • x) ^ p = k ^ p • x ^ p := by
  

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁶ : Monoid M
inst✝⁵ : Monoid N
inst✝⁴ : AddMonoid A
inst✝³ : AddMonoid B
inst✝² : MulAction M N
inst✝¹ : IsScalarTower M N N
inst✝ : SMulCommClass M N N
k : M
x : N
p : ℕ
⊢ (k • x) ^ p = k ^ p • x ^ p

Next tactic:
induction' p with p IH
theorem smul_pow [MulAction M N] [IsScalarTower M N N] [SMulCommClass M N N] (k : M) (x : N)
    (p : ℕ) : (k • x) ^ p = k ^ p • x ^ p := by
  induction' p with p IH
  · 

Proof state:
case zero
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁶ : Monoid M
inst✝⁵ : Monoid N
inst✝⁴ : AddMonoid A
inst✝³ : AddMonoid B
inst✝² : MulAction M N
inst✝¹ : IsScalarTower M N N
inst✝ : SMulCommClass M N N
k : M
x : N
⊢ (k • x) ^ Nat.zero = k ^ Nat.zero • x ^ Nat.zero

Next tactic:
simp
theorem smul_pow [MulAction M N] [IsScalarTower M N N] [SMulCommClass M N N] (k : M) (x : N)
    (p : ℕ) : (k • x) ^ p = k ^ p • x ^ p := by
  induction' p with p IH
  · simp
  · 

Proof state:
case succ
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁶ : Monoid M
inst✝⁵ : Monoid N
inst✝⁴ : AddMonoid A
inst✝³ : AddMonoid B
inst✝² : MulAction M N
inst✝¹ : IsScalarTower M N N
inst✝ : SMulCommClass M N N
k : M
x : N
p : ℕ
IH : (k • x) ^ p = k ^ p • x ^ p
⊢ (k • x) ^ Nat.succ p = k ^ Nat.succ p • x ^ Nat.succ p

Next tactic:
rw [pow_succ', IH, smul_mul_smul, ← pow_succ', ← pow_succ']
@[simp]
theorem smul_pow' [MulDistribMulAction M N] (x : M) (m : N) (n : ℕ) : x • m ^ n = (x • m) ^ n := by
  

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : AddMonoid A
inst✝¹ : AddMonoid B
inst✝ : MulDistribMulAction M N
x : M
m : N
n : ℕ
⊢ x • m ^ n = (x • m) ^ n

Next tactic:
induction' n with n ih
@[simp]
theorem smul_pow' [MulDistribMulAction M N] (x : M) (m : N) (n : ℕ) : x • m ^ n = (x • m) ^ n := by
  induction' n with n ih
  · 

Proof state:
case zero
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : AddMonoid A
inst✝¹ : AddMonoid B
inst✝ : MulDistribMulAction M N
x : M
m : N
⊢ x • m ^ Nat.zero = (x • m) ^ Nat.zero

Next tactic:
rw [pow_zero, pow_zero]
@[simp]
theorem smul_pow' [MulDistribMulAction M N] (x : M) (m : N) (n : ℕ) : x • m ^ n = (x • m) ^ n := by
  induction' n with n ih
  · rw [pow_zero, pow_zero]
    

Proof state:
case zero
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : AddMonoid A
inst✝¹ : AddMonoid B
inst✝ : MulDistribMulAction M N
x : M
m : N
⊢ x • 1 = 1

Next tactic:
exact smul_one x
@[simp]
theorem smul_pow' [MulDistribMulAction M N] (x : M) (m : N) (n : ℕ) : x • m ^ n = (x • m) ^ n := by
  induction' n with n ih
  · rw [pow_zero, pow_zero]
    exact smul_one x
  · 

Proof state:
case succ
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : AddMonoid A
inst✝¹ : AddMonoid B
inst✝ : MulDistribMulAction M N
x : M
m : N
n : ℕ
ih : x • m ^ n = (x • m) ^ n
⊢ x • m ^ Nat.succ n = (x • m) ^ Nat.succ n

Next tactic:
rw [pow_succ, pow_succ]
@[simp]
theorem smul_pow' [MulDistribMulAction M N] (x : M) (m : N) (n : ℕ) : x • m ^ n = (x • m) ^ n := by
  induction' n with n ih
  · rw [pow_zero, pow_zero]
    exact smul_one x
  · rw [pow_succ, pow_succ]
    

Proof state:
case succ
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : AddMonoid A
inst✝¹ : AddMonoid B
inst✝ : MulDistribMulAction M N
x : M
m : N
n : ℕ
ih : x • m ^ n = (x • m) ^ n
⊢ x • (m * m ^ n) = x • m * (x • m) ^ n

Next tactic:
exact (smul_mul' x m (m ^ n)).trans (congr_arg _ ih)
@[simp]
theorem zsmul_one [AddGroupWithOne A] (n : ℤ) : n • (1 : A) = n := by 

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : AddGroupWithOne A
n : ℤ
⊢ n • 1 = ↑n

Next tactic:
cases n
@[simp]
theorem zsmul_one [AddGroupWithOne A] (n : ℤ) : n • (1 : A) = n := by cases n <;> 

Proof state:
case ofNat
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : AddGroupWithOne A
a✝ : ℕ
⊢ ofNat a✝ • 1 = ↑(ofNat a✝)

Next tactic:
simp
@[simp]
theorem zsmul_one [AddGroupWithOne A] (n : ℤ) : n • (1 : A) = n := by cases n <;> 

Proof state:
case negSucc
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : AddGroupWithOne A
a✝ : ℕ
⊢ -[a✝+1] • 1 = ↑-[a✝+1]

Next tactic:
simp
@[to_additive mul_zsmul']
theorem zpow_mul (a : α) : ∀ m n : ℤ, a ^ (m * n) = (a ^ m) ^ n
  | (m : ℕ), (n : ℕ) => by
    

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : DivisionMonoid α
a : α
m n : ℕ
⊢ a ^ (↑m * ↑n) = (a ^ ↑m) ^ ↑n

Next tactic:
rw [zpow_ofNat, zpow_ofNat, ← pow_mul, ← zpow_ofNat]
@[to_additive mul_zsmul']
theorem zpow_mul (a : α) : ∀ m n : ℤ, a ^ (m * n) = (a ^ m) ^ n
  | (m : ℕ), (n : ℕ) => by
    rw [zpow_ofNat, zpow_ofNat, ← pow_mul, ← zpow_ofNat]
    

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : DivisionMonoid α
a : α
m n : ℕ
⊢ a ^ (↑m * ↑n) = a ^ ↑(m * n)

Next tactic:
rfl
@[to_additive mul_zsmul']
theorem zpow_mul (a : α) : ∀ m n : ℤ, a ^ (m * n) = (a ^ m) ^ n
  | (m : ℕ), (n : ℕ) => by
    rw [zpow_ofNat, zpow_ofNat, ← pow_mul, ← zpow_ofNat]
    rfl
  | (m : ℕ), -[n+1] => by
    

Proof state:
α : Type u_1
M : Type u
N : Type v
G : Type w
H : Type x
A : Type y
B : Type z
R : Type u₁
S : Type u₂
inst✝ : DivisionMonoid α
a : α
m n : ℕ
⊢ a ^ (↑m * -[n+1]) = (a ^ ↑m) ^ -[n+1]

Next tactic:
rw [zpow_ofNat, zpow_negSucc, ← pow_mul, ofNat_mul_negSucc, zpow_neg, inv_inj, ← zpow_ofNat]