l3lab/ntp-mathlib huggingface dataset:
/-- The special case that more or less by definition `QuaternionGroup 0` is isomorphic to the
infinite dihedral group. -/
def quaternionGroupZeroEquivDihedralGroupZero : QuaternionGroup 0 ≃* DihedralGroup 0 where
  toFun i :=
    -- Porting note: Originally `QuaternionGroup.recOn i DihedralGroup.r DihedralGroup.sr`
    match i with
    | a j => DihedralGroup.r j
    | xa j => DihedralGroup.sr j
  invFun i :=
    match i with
    | DihedralGroup.r j => a j
    | DihedralGroup.sr j => xa j
  left_inv := by rintro (k | k) <;> rfl
  right_inv := by rintro (k | k) <;> 

Proof state:
case r
n : ℕ
k : ZMod 0
⊢ (fun i =>
        match i with
        | a j => DihedralGroup.r j
        | xa j => DihedralGroup.sr j)
      ((fun i =>
          match i with
          | DihedralGroup.r j => a j
          | DihedralGroup.sr j => xa j)
        (DihedralGroup.r k)) =
    DihedralGroup.r k

Next tactic:
rfl
/-- The special case that more or less by definition `QuaternionGroup 0` is isomorphic to the
infinite dihedral group. -/
def quaternionGroupZeroEquivDihedralGroupZero : QuaternionGroup 0 ≃* DihedralGroup 0 where
  toFun i :=
    -- Porting note: Originally `QuaternionGroup.recOn i DihedralGroup.r DihedralGroup.sr`
    match i with
    | a j => DihedralGroup.r j
    | xa j => DihedralGroup.sr j
  invFun i :=
    match i with
    | DihedralGroup.r j => a j
    | DihedralGroup.sr j => xa j
  left_inv := by rintro (k | k) <;> rfl
  right_inv := by rintro (k | k) <;> 

Proof state:
case sr
n : ℕ
k : ZMod 0
⊢ (fun i =>
        match i with
        | a j => DihedralGroup.r j
        | xa j => DihedralGroup.sr j)
      ((fun i =>
          match i with
          | DihedralGroup.r j => a j
          | DihedralGroup.sr j => xa j)
        (DihedralGroup.sr k)) =
    DihedralGroup.sr k

Next tactic:
rfl
instance : Nontrivial (QuaternionGroup n) :=
  ⟨⟨a 0, xa 0, by 

Proof state:
n : ℕ
⊢ a 0 ≠ xa 0

Next tactic:
revert n
instance : Nontrivial (QuaternionGroup n) :=
  ⟨⟨a 0, xa 0, by revert n; 

Proof state:
⊢ ∀ {n : ℕ}, a 0 ≠ xa 0

Next tactic:
simp
/-- If `0 < n`, then `QuaternionGroup n` has `4n` elements.
-/
theorem card [NeZero n] : Fintype.card (QuaternionGroup n) = 4 * n := by
  

Proof state:
n : ℕ
inst✝ : NeZero n
⊢ Fintype.card (QuaternionGroup n) = 4 * n

Next tactic:
rw [← Fintype.card_eq.mpr ⟨fintypeHelper⟩, Fintype.card_sum, ZMod.card, two_mul]
/-- If `0 < n`, then `QuaternionGroup n` has `4n` elements.
-/
theorem card [NeZero n] : Fintype.card (QuaternionGroup n) = 4 * n := by
  rw [← Fintype.card_eq.mpr ⟨fintypeHelper⟩, Fintype.card_sum, ZMod.card, two_mul]
  

Proof state:
n : ℕ
inst✝ : NeZero n
⊢ n + n + (n + n) = 4 * n

Next tactic:
ring
@[simp]
theorem a_one_pow (k : ℕ) : (a 1 : QuaternionGroup n) ^ k = a k := by
  

Proof state:
n k : ℕ
⊢ a 1 ^ k = a ↑k

Next tactic:
induction' k with k IH
@[simp]
theorem a_one_pow (k : ℕ) : (a 1 : QuaternionGroup n) ^ k = a k := by
  induction' k with k IH
  · 

Proof state:
case zero
n : ℕ
⊢ a 1 ^ Nat.zero = a ↑Nat.zero

Next tactic:
rw [Nat.cast_zero]
@[simp]
theorem a_one_pow (k : ℕ) : (a 1 : QuaternionGroup n) ^ k = a k := by
  induction' k with k IH
  · rw [Nat.cast_zero]; 

Proof state:
case zero
n : ℕ
⊢ a 1 ^ Nat.zero = a 0

Next tactic:
rfl
@[simp]
theorem a_one_pow (k : ℕ) : (a 1 : QuaternionGroup n) ^ k = a k := by
  induction' k with k IH
  · rw [Nat.cast_zero]; rfl
  · 

Proof state:
case succ
n k : ℕ
IH : a 1 ^ k = a ↑k
⊢ a 1 ^ Nat.succ k = a ↑(Nat.succ k)

Next tactic:
rw [pow_succ, IH, a_mul_a]
@[simp]
theorem a_one_pow (k : ℕ) : (a 1 : QuaternionGroup n) ^ k = a k := by
  induction' k with k IH
  · rw [Nat.cast_zero]; rfl
  · rw [pow_succ, IH, a_mul_a]
    

Proof state:
case succ
n k : ℕ
IH : a 1 ^ k = a ↑k
⊢ a (1 + ↑k) = a ↑(Nat.succ k)

Next tactic:
congr 1
@[simp]
theorem a_one_pow (k : ℕ) : (a 1 : QuaternionGroup n) ^ k = a k := by
  induction' k with k IH
  · rw [Nat.cast_zero]; rfl
  · rw [pow_succ, IH, a_mul_a]
    congr 1
    

Proof state:
case succ.e_a
n k : ℕ
IH : a 1 ^ k = a ↑k
⊢ 1 + ↑k = ↑(Nat.succ k)

Next tactic:
norm_cast
@[simp]
theorem a_one_pow (k : ℕ) : (a 1 : QuaternionGroup n) ^ k = a k := by
  induction' k with k IH
  · rw [Nat.cast_zero]; rfl
  · rw [pow_succ, IH, a_mul_a]
    congr 1
    norm_cast
    

Proof state:
case succ.e_a
n k : ℕ
IH : a 1 ^ k = a ↑k
⊢ ↑(1 + k) = ↑(Nat.succ k)

Next tactic:
rw [Nat.one_add]
theorem a_one_pow_n : (a 1 : QuaternionGroup n) ^ (2 * n) = 1 := by
  

Proof state:
n : ℕ
⊢ a 1 ^ (2 * n) = 1

Next tactic:
rw [a_one_pow, one_def]
theorem a_one_pow_n : (a 1 : QuaternionGroup n) ^ (2 * n) = 1 := by
  rw [a_one_pow, one_def]
  

Proof state:
n : ℕ
⊢ a ↑(2 * n) = a 0

Next tactic:
congr 1
theorem a_one_pow_n : (a 1 : QuaternionGroup n) ^ (2 * n) = 1 := by
  rw [a_one_pow, one_def]
  congr 1
  

Proof state:
case e_a
n : ℕ
⊢ ↑(2 * n) = 0

Next tactic:
exact ZMod.nat_cast_self _
@[simp]
theorem xa_sq (i : ZMod (2 * n)) : xa i ^ 2 = a n := by 

Proof state:
n : ℕ
i : ZMod (2 * n)
⊢ xa i ^ 2 = a ↑n

Next tactic:
simp [sq]
@[simp]
theorem xa_pow_four (i : ZMod (2 * n)) : xa i ^ 4 = 1 := by
  

Proof state:
n : ℕ
i : ZMod (2 * n)
⊢ xa i ^ 4 = 1

Next tactic:
rw [pow_succ, pow_succ, sq, xa_mul_xa, xa_mul_a, xa_mul_xa, add_sub_cancel, add_sub_assoc,
    add_sub_cancel']
@[simp]
theorem xa_pow_four (i : ZMod (2 * n)) : xa i ^ 4 = 1 := by
  rw [pow_succ, pow_succ, sq, xa_mul_xa, xa_mul_a, xa_mul_xa, add_sub_cancel, add_sub_assoc,
    add_sub_cancel']
  

Proof state:
n : ℕ
i : ZMod (2 * n)
⊢ a (↑n + ↑n) = 1

Next tactic:
norm_cast
@[simp]
theorem xa_pow_four (i : ZMod (2 * n)) : xa i ^ 4 = 1 := by
  rw [pow_succ, pow_succ, sq, xa_mul_xa, xa_mul_a, xa_mul_xa, add_sub_cancel, add_sub_assoc,
    add_sub_cancel']
  norm_cast
  

Proof state:
n : ℕ
i : ZMod (2 * n)
⊢ a ↑(n + n) = 1

Next tactic:
rw [← two_mul]
@[simp]
theorem xa_pow_four (i : ZMod (2 * n)) : xa i ^ 4 = 1 := by
  rw [pow_succ, pow_succ, sq, xa_mul_xa, xa_mul_a, xa_mul_xa, add_sub_cancel, add_sub_assoc,
    add_sub_cancel']
  norm_cast
  rw [← two_mul]
  

Proof state:
n : ℕ
i : ZMod (2 * n)
⊢ a ↑(2 * n) = 1

Next tactic:
simp [one_def]
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  

Proof state:
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
⊢ orderOf (xa i) = 4

Next tactic:
change _ = 2 ^ 2
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  

Proof state:
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
⊢ orderOf (xa i) = 2 ^ 2

Next tactic:
haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
  

Proof state:
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
this : Fact (Nat.Prime 2)
⊢ orderOf (xa i) = 2 ^ 2

Next tactic:
apply orderOf_eq_prime_pow
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
  apply orderOf_eq_prime_pow
  · 

Proof state:
case hnot
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
this : Fact (Nat.Prime 2)
⊢ ¬xa i ^ 2 ^ 1 = 1

Next tactic:
intro h
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
  apply orderOf_eq_prime_pow
  · intro h
    

Proof state:
case hnot
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
this : Fact (Nat.Prime 2)
h : xa i ^ 2 ^ 1 = 1
⊢ False

Next tactic:
simp only [pow_one, xa_sq] at h
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
  apply orderOf_eq_prime_pow
  · intro h
    simp only [pow_one, xa_sq] at h
    

Proof state:
case hnot
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
this : Fact (Nat.Prime 2)
h : a ↑n = 1
⊢ False

Next tactic:
injection h with h'
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
  apply orderOf_eq_prime_pow
  · intro h
    simp only [pow_one, xa_sq] at h
    injection h with h'
    

Proof state:
case hnot
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
this : Fact (Nat.Prime 2)
h' : ↑n = 0
⊢ False

Next tactic:
apply_fun ZMod.val at h'
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
  apply orderOf_eq_prime_pow
  · intro h
    simp only [pow_one, xa_sq] at h
    injection h with h'
    apply_fun ZMod.val at h'
    

Proof state:
case hnot
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
this : Fact (Nat.Prime 2)
h' : ZMod.val ↑n = ZMod.val 0
⊢ False

Next tactic:
apply_fun (· / n) at h'
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
  apply orderOf_eq_prime_pow
  · intro h
    simp only [pow_one, xa_sq] at h
    injection h with h'
    apply_fun ZMod.val at h'
    apply_fun (· / n) at h'
    

Proof state:
case hnot
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
this : Fact (Nat.Prime 2)
h' : ZMod.val ↑n / n = ZMod.val 0 / n
⊢ False

Next tactic:
simp only [ZMod.val_nat_cast, ZMod.val_zero, Nat.zero_div, Nat.mod_mul_left_div_self,
      Nat.div_self (NeZero.pos n)] at h'
/-- If `0 < n`, then `xa i` has order 4.
-/
@[simp]
theorem orderOf_xa [NeZero n] (i : ZMod (2 * n)) : orderOf (xa i) = 4 := by
  change _ = 2 ^ 2
  haveI : Fact (Nat.Prime 2) := Fact.mk Nat.prime_two
  apply orderOf_eq_prime_pow
  · intro h
    simp only [pow_one, xa_sq] at h
    injection h with h'
    apply_fun ZMod.val at h'
    apply_fun (· / n) at h'
    simp only [ZMod.val_nat_cast, ZMod.val_zero, Nat.zero_div, Nat.mod_mul_left_div_self,
      Nat.div_self (NeZero.pos n)] at h'
  · 

Proof state:
case hfin
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
this : Fact (Nat.Prime 2)
⊢ xa i ^ 2 ^ (1 + 1) = 1

Next tactic:
norm_num
/-- In the special case `n = 1`, `Quaternion 1` is a cyclic group (of order `4`). -/
theorem quaternionGroup_one_isCyclic : IsCyclic (QuaternionGroup 1) := by
  

Proof state:
n : ℕ
⊢ IsCyclic (QuaternionGroup 1)

Next tactic:
apply isCyclic_of_orderOf_eq_card
/-- In the special case `n = 1`, `Quaternion 1` is a cyclic group (of order `4`). -/
theorem quaternionGroup_one_isCyclic : IsCyclic (QuaternionGroup 1) := by
  apply isCyclic_of_orderOf_eq_card
  

Proof state:
case hx
n : ℕ
⊢ orderOf ?x = Fintype.card (QuaternionGroup 1)
case x n : ℕ ⊢ QuaternionGroup 1

Next tactic:
rw [card, mul_one]
/-- In the special case `n = 1`, `Quaternion 1` is a cyclic group (of order `4`). -/
theorem quaternionGroup_one_isCyclic : IsCyclic (QuaternionGroup 1) := by
  apply isCyclic_of_orderOf_eq_card
  rw [card, mul_one]
  

Proof state:
case hx
n : ℕ
⊢ orderOf ?x = 4
case x
n : ℕ
⊢ QuaternionGroup 1
case x
n : ℕ
⊢ QuaternionGroup 1
case x n : ℕ ⊢ QuaternionGroup 1

Next tactic:
exact orderOf_xa 0
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  

Proof state:
n : ℕ
⊢ orderOf (a 1) = 2 * n

Next tactic:
cases' eq_zero_or_neZero n with hn hn
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · 

Proof state:
case inl
n : ℕ
hn : n = 0
⊢ orderOf (a 1) = 2 * n

Next tactic:
subst hn
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    

Proof state:
case inl
⊢ orderOf (a 1) = 2 * 0

Next tactic:
simp_rw [mul_zero, orderOf_eq_zero_iff']
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    

Proof state:
case inl
⊢ ∀ (n : ℕ), 0 < n → QuaternionGroup.a 1 ^ n ≠ 1

Next tactic:
intro n h
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    

Proof state:
case inl
n : ℕ
h : 0 < n
⊢ a 1 ^ n ≠ 1

Next tactic:
rw [one_def, a_one_pow]
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    

Proof state:
case inl
n : ℕ
h : 0 < n
⊢ a ↑n ≠ a 0

Next tactic:
apply mt a.inj
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    

Proof state:
case inl
n : ℕ
h : 0 < n
⊢ ¬↑n = 0

Next tactic:
haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
    

Proof state:
case inl
n : ℕ
h : 0 < n
this : CharZero (ZMod (2 * 0))
⊢ ¬↑n = 0

Next tactic:
simpa using h.ne'
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
    simpa using h.ne'
  

Proof state:
case inr
n : ℕ
hn : NeZero n
⊢ orderOf (a 1) = 2 * n

Next tactic:
apply (Nat.le_of_dvd
    (NeZero.pos _) (orderOf_dvd_of_pow_eq_one (@a_one_pow_n n))).lt_or_eq.resolve_left
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
    simpa using h.ne'
  apply (Nat.le_of_dvd
    (NeZero.pos _) (orderOf_dvd_of_pow_eq_one (@a_one_pow_n n))).lt_or_eq.resolve_left
  

Proof state:
case inr
n : ℕ
hn : NeZero n
⊢ ¬orderOf (a 1) < 2 * n

Next tactic:
intro h
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
    simpa using h.ne'
  apply (Nat.le_of_dvd
    (NeZero.pos _) (orderOf_dvd_of_pow_eq_one (@a_one_pow_n n))).lt_or_eq.resolve_left
  intro h
  

Proof state:
case inr
n : ℕ
hn : NeZero n
h : orderOf (a 1) < 2 * n
⊢ False

Next tactic:
have h1 : (a 1 : QuaternionGroup n) ^ orderOf (a 1) = 1 := pow_orderOf_eq_one _
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
    simpa using h.ne'
  apply (Nat.le_of_dvd
    (NeZero.pos _) (orderOf_dvd_of_pow_eq_one (@a_one_pow_n n))).lt_or_eq.resolve_left
  intro h
  have h1 : (a 1 : QuaternionGroup n) ^ orderOf (a 1) = 1 := pow_orderOf_eq_one _
  

Proof state:
case inr
n : ℕ
hn : NeZero n
h : orderOf (a 1) < 2 * n
h1 : a 1 ^ orderOf (a 1) = 1
⊢ False

Next tactic:
rw [a_one_pow] at h1
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
    simpa using h.ne'
  apply (Nat.le_of_dvd
    (NeZero.pos _) (orderOf_dvd_of_pow_eq_one (@a_one_pow_n n))).lt_or_eq.resolve_left
  intro h
  have h1 : (a 1 : QuaternionGroup n) ^ orderOf (a 1) = 1 := pow_orderOf_eq_one _
  rw [a_one_pow] at h1
  

Proof state:
case inr
n : ℕ
hn : NeZero n
h : orderOf (a 1) < 2 * n
h1 : a ↑(orderOf (a 1)) = 1
⊢ False

Next tactic:
injection h1 with h2
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
    simpa using h.ne'
  apply (Nat.le_of_dvd
    (NeZero.pos _) (orderOf_dvd_of_pow_eq_one (@a_one_pow_n n))).lt_or_eq.resolve_left
  intro h
  have h1 : (a 1 : QuaternionGroup n) ^ orderOf (a 1) = 1 := pow_orderOf_eq_one _
  rw [a_one_pow] at h1
  injection h1 with h2
  

Proof state:
case inr
n : ℕ
hn : NeZero n
h : orderOf (a 1) < 2 * n
h2 : ↑(orderOf (a 1)) = 0
⊢ False

Next tactic:
rw [← ZMod.val_eq_zero, ZMod.val_nat_cast, Nat.mod_eq_of_lt h] at h2
/-- If `0 < n`, then `a 1` has order `2 * n`.
-/
@[simp]
theorem orderOf_a_one : orderOf (a 1 : QuaternionGroup n) = 2 * n := by
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp_rw [mul_zero, orderOf_eq_zero_iff']
    intro n h
    rw [one_def, a_one_pow]
    apply mt a.inj
    haveI : CharZero (ZMod (2 * 0)) := ZMod.charZero
    simpa using h.ne'
  apply (Nat.le_of_dvd
    (NeZero.pos _) (orderOf_dvd_of_pow_eq_one (@a_one_pow_n n))).lt_or_eq.resolve_left
  intro h
  have h1 : (a 1 : QuaternionGroup n) ^ orderOf (a 1) = 1 := pow_orderOf_eq_one _
  rw [a_one_pow] at h1
  injection h1 with h2
  rw [← ZMod.val_eq_zero, ZMod.val_nat_cast, Nat.mod_eq_of_lt h] at h2
  

Proof state:
case inr
n : ℕ
hn : NeZero n
h : orderOf (a 1) < 2 * n
h2 : orderOf (a 1) = 0
⊢ False

Next tactic:
exact absurd h2.symm (orderOf_pos _).ne
/-- If `0 < n`, then `a i` has order `(2 * n) / gcd (2 * n) i`.
-/
theorem orderOf_a [NeZero n] (i : ZMod (2 * n)) :
    orderOf (a i) = 2 * n / Nat.gcd (2 * n) i.val := by
  

Proof state:
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
⊢ orderOf (a i) = 2 * n / Nat.gcd (2 * n) (ZMod.val i)

Next tactic:
conv_lhs => rw [← ZMod.nat_cast_zmod_val i]
/-- If `0 < n`, then `a i` has order `(2 * n) / gcd (2 * n) i`.
-/
theorem orderOf_a [NeZero n] (i : ZMod (2 * n)) :
    orderOf (a i) = 2 * n / Nat.gcd (2 * n) i.val := by
  conv_lhs => 

Proof state:
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
| orderOf (a i)

Next tactic:
rw [← ZMod.nat_cast_zmod_val i]
/-- If `0 < n`, then `a i` has order `(2 * n) / gcd (2 * n) i`.
-/
theorem orderOf_a [NeZero n] (i : ZMod (2 * n)) :
    orderOf (a i) = 2 * n / Nat.gcd (2 * n) i.val := by
  conv_lhs => rw [← ZMod.nat_cast_zmod_val i]
  

Proof state:
n : ℕ
inst✝ : NeZero n
i : ZMod (2 * n)
⊢ orderOf (a ↑(ZMod.val i)) = 2 * n / Nat.gcd (2 * n) (ZMod.val i)

Next tactic:
rw [← a_one_pow, orderOf_pow, orderOf_a_one]
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  

Proof state:
n : ℕ
⊢ Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2

Next tactic:
rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  

Proof state:
n : ℕ
⊢ Monoid.exponent (QuaternionGroup n) = lcm (2 * n) (2 * 2)

Next tactic:
norm_num
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  

Proof state:
n : ℕ
⊢ Monoid.exponent (QuaternionGroup n) = lcm (2 * n) 4

Next tactic:
cases' eq_zero_or_neZero n with hn hn
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  cases' eq_zero_or_neZero n with hn hn
  · 

Proof state:
case inl
n : ℕ
hn : n = 0
⊢ Monoid.exponent (QuaternionGroup n) = lcm (2 * n) 4

Next tactic:
subst hn
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    

Proof state:
case inl
⊢ Monoid.exponent (QuaternionGroup 0) = lcm (2 * 0) 4

Next tactic:
simp only [lcm_zero_left, mul_zero]
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp only [lcm_zero_left, mul_zero]
    

Proof state:
case inl
⊢ Monoid.exponent (QuaternionGroup 0) = 0

Next tactic:
exact Monoid.exponent_eq_zero_of_order_zero orderOf_a_one
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp only [lcm_zero_left, mul_zero]
    exact Monoid.exponent_eq_zero_of_order_zero orderOf_a_one
  

Proof state:
case inr
n : ℕ
hn : NeZero n
⊢ Monoid.exponent (QuaternionGroup n) = lcm (2 * n) 4

Next tactic:
apply Nat.dvd_antisymm
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp only [lcm_zero_left, mul_zero]
    exact Monoid.exponent_eq_zero_of_order_zero orderOf_a_one
  apply Nat.dvd_antisymm
  · 

Proof state:
case inr.a
n : ℕ
hn : NeZero n
⊢ Monoid.exponent (QuaternionGroup n) ∣ lcm (2 * n) 4

Next tactic:
apply Monoid.exponent_dvd_of_forall_pow_eq_one
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp only [lcm_zero_left, mul_zero]
    exact Monoid.exponent_eq_zero_of_order_zero orderOf_a_one
  apply Nat.dvd_antisymm
  · apply Monoid.exponent_dvd_of_forall_pow_eq_one
    

Proof state:
case inr.a.hG
n : ℕ
hn : NeZero n
⊢ ∀ (g : QuaternionGroup n), g ^ lcm (2 * n) 4 = 1

Next tactic:
rintro (m | m)
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp only [lcm_zero_left, mul_zero]
    exact Monoid.exponent_eq_zero_of_order_zero orderOf_a_one
  apply Nat.dvd_antisymm
  · apply Monoid.exponent_dvd_of_forall_pow_eq_one
    rintro (m | m)
    · 

Proof state:
case inr.a.hG.a
n : ℕ
hn : NeZero n
m : ZMod (2 * n)
⊢ a m ^ lcm (2 * n) 4 = 1

Next tactic:
rw [← orderOf_dvd_iff_pow_eq_one, orderOf_a]
theorem exponent : Monoid.exponent (QuaternionGroup n) = 2 * lcm n 2 := by
  rw [← normalize_eq 2, ← lcm_mul_left, normalize_eq]
  norm_num
  cases' eq_zero_or_neZero n with hn hn
  · subst hn
    simp only [lcm_zero_left, mul_zero]
    exact Monoid.exponent_eq_zero_of_order_zero orderOf_a_one
  apply Nat.dvd_antisymm
  · apply Monoid.exponent_dvd_of_forall_pow_eq_one
    rintro (m | m)
    · rw [← orderOf_dvd_iff_pow_eq_one, orderOf_a]
      

Proof state:
case inr.a.hG.a
n : ℕ
hn : NeZero n
m : ZMod (2 * n)
⊢ 2 * n / Nat.gcd (2 * n) (ZMod.val m) ∣ lcm (2 * n) 4

Next tactic:
refine' Nat.dvd_trans ⟨gcd (2 * n) m.val, _⟩ (dvd_lcm_left (2 * n) 4)