l3lab/ntp-mathlib huggingface dataset:
theorem natAbs_ediv (a b : ℤ) (H : b ∣ a) : natAbs (a / b) = natAbs a / natAbs b := by
  rcases Nat.eq_zero_or_pos (natAbs b) with (h | h)
  · rw [natAbs_eq_zero.1 h]
    simp [Int.ediv_zero]
  

Proof state:
case inr
a b : ℤ
H : b ∣ a
h : natAbs b > 0
⊢ natAbs (a / b) = natAbs a / natAbs b

Next tactic:
calc
    natAbs (a / b) = natAbs (a / b) * 1 := by rw [mul_one]
    _ = natAbs (a / b) * (natAbs b / natAbs b) := by rw [Nat.div_self h]
    _ = natAbs (a / b) * natAbs b / natAbs b := by rw [Nat.mul_div_assoc _ dvd_rfl]
    _ = natAbs (a / b * b) / natAbs b := by rw [natAbs_mul (a / b) b]
    _ = natAbs a / natAbs b := by rw [Int.ediv_mul_cancel H]
theorem natAbs_ediv (a b : ℤ) (H : b ∣ a) : natAbs (a / b) = natAbs a / natAbs b := by
  rcases Nat.eq_zero_or_pos (natAbs b) with (h | h)
  · rw [natAbs_eq_zero.1 h]
    simp [Int.ediv_zero]
  calc
    natAbs (a / b) = natAbs (a / b) * 1 := by 

Proof state:
a b : ℤ
H : b ∣ a
h : natAbs b > 0
⊢ natAbs (a / b) = natAbs (a / b) * 1

Next tactic:
rw [mul_one]
theorem natAbs_ediv (a b : ℤ) (H : b ∣ a) : natAbs (a / b) = natAbs a / natAbs b := by
  rcases Nat.eq_zero_or_pos (natAbs b) with (h | h)
  · rw [natAbs_eq_zero.1 h]
    simp [Int.ediv_zero]
  calc
    natAbs (a / b) = natAbs (a / b) * 1 := by rw [mul_one]
    _ = natAbs (a / b) * (natAbs b / natAbs b) := by 

Proof state:
a b : ℤ
H : b ∣ a
h : natAbs b > 0
⊢ natAbs (a / b) * 1 = natAbs (a / b) * (natAbs b / natAbs b)

Next tactic:
rw [Nat.div_self h]
theorem natAbs_ediv (a b : ℤ) (H : b ∣ a) : natAbs (a / b) = natAbs a / natAbs b := by
  rcases Nat.eq_zero_or_pos (natAbs b) with (h | h)
  · rw [natAbs_eq_zero.1 h]
    simp [Int.ediv_zero]
  calc
    natAbs (a / b) = natAbs (a / b) * 1 := by rw [mul_one]
    _ = natAbs (a / b) * (natAbs b / natAbs b) := by rw [Nat.div_self h]
    _ = natAbs (a / b) * natAbs b / natAbs b := by 

Proof state:
a b : ℤ
H : b ∣ a
h : natAbs b > 0
⊢ natAbs (a / b) * (natAbs b / natAbs b) = natAbs (a / b) * natAbs b / natAbs b

Next tactic:
rw [Nat.mul_div_assoc _ dvd_rfl]
theorem natAbs_ediv (a b : ℤ) (H : b ∣ a) : natAbs (a / b) = natAbs a / natAbs b := by
  rcases Nat.eq_zero_or_pos (natAbs b) with (h | h)
  · rw [natAbs_eq_zero.1 h]
    simp [Int.ediv_zero]
  calc
    natAbs (a / b) = natAbs (a / b) * 1 := by rw [mul_one]
    _ = natAbs (a / b) * (natAbs b / natAbs b) := by rw [Nat.div_self h]
    _ = natAbs (a / b) * natAbs b / natAbs b := by rw [Nat.mul_div_assoc _ dvd_rfl]
    _ = natAbs (a / b * b) / natAbs b := by 

Proof state:
a b : ℤ
H : b ∣ a
h : natAbs b > 0
⊢ natAbs (a / b) * natAbs b / natAbs b = natAbs (a / b * b) / natAbs b

Next tactic:
rw [natAbs_mul (a / b) b]
theorem natAbs_ediv (a b : ℤ) (H : b ∣ a) : natAbs (a / b) = natAbs a / natAbs b := by
  rcases Nat.eq_zero_or_pos (natAbs b) with (h | h)
  · rw [natAbs_eq_zero.1 h]
    simp [Int.ediv_zero]
  calc
    natAbs (a / b) = natAbs (a / b) * 1 := by rw [mul_one]
    _ = natAbs (a / b) * (natAbs b / natAbs b) := by rw [Nat.div_self h]
    _ = natAbs (a / b) * natAbs b / natAbs b := by rw [Nat.mul_div_assoc _ dvd_rfl]
    _ = natAbs (a / b * b) / natAbs b := by rw [natAbs_mul (a / b) b]
    _ = natAbs a / natAbs b := by 

Proof state:
a b : ℤ
H : b ∣ a
h : natAbs b > 0
⊢ natAbs (a / b * b) / natAbs b = natAbs a / natAbs b

Next tactic:
rw [Int.ediv_mul_cancel H]
theorem dvd_of_mul_dvd_mul_left {i j k : ℤ} (k_non_zero : k ≠ 0) (H : k * i ∣ k * j) : i ∣ j :=
  Dvd.elim H fun l H1 => by 

Proof state:
i j k : ℤ
k_non_zero : k ≠ 0
H : k * i ∣ k * j
l : ℤ
H1 : k * j = k * i * l
⊢ i ∣ j

Next tactic:
rw [mul_assoc] at H1
theorem dvd_of_mul_dvd_mul_left {i j k : ℤ} (k_non_zero : k ≠ 0) (H : k * i ∣ k * j) : i ∣ j :=
  Dvd.elim H fun l H1 => by rw [mul_assoc] at H1; 

Proof state:
i j k : ℤ
k_non_zero : k ≠ 0
H : k * i ∣ k * j
l : ℤ
H1 : k * j = k * (i * l)
⊢ i ∣ j

Next tactic:
exact ⟨_, mul_left_cancel₀ k_non_zero H1⟩
theorem dvd_of_mul_dvd_mul_right {i j k : ℤ} (k_non_zero : k ≠ 0) (H : i * k ∣ j * k) : i ∣ j := by
  

Proof state:
i j k : ℤ
k_non_zero : k ≠ 0
H : i * k ∣ j * k
⊢ i ∣ j

Next tactic:
rw [mul_comm i k, mul_comm j k] at H
theorem dvd_of_mul_dvd_mul_right {i j k : ℤ} (k_non_zero : k ≠ 0) (H : i * k ∣ j * k) : i ∣ j := by
  rw [mul_comm i k, mul_comm j k] at H; 

Proof state:
i j k : ℤ
k_non_zero : k ≠ 0
H : k * i ∣ k * j
⊢ i ∣ j

Next tactic:
exact dvd_of_mul_dvd_mul_left k_non_zero H
theorem gcd_mul_lcm (i j : ℤ) : gcd i j * lcm i j = natAbs (i * j) := by
  

Proof state:
i j : ℤ
⊢ gcd i j * lcm i j = natAbs (i * j)

Next tactic:
rw [Int.gcd, Int.lcm, Nat.gcd_mul_lcm, natAbs_mul]
@[simp]
theorem gcd_self (i : ℤ) : gcd i i = natAbs i := by 

Proof state:
i : ℤ
⊢ gcd i i = natAbs i

Next tactic:
simp [gcd]
@[simp]
theorem gcd_zero_left (i : ℤ) : gcd 0 i = natAbs i := by 

Proof state:
i : ℤ
⊢ gcd 0 i = natAbs i

Next tactic:
simp [gcd]
@[simp]
theorem gcd_zero_right (i : ℤ) : gcd i 0 = natAbs i := by 

Proof state:
i : ℤ
⊢ gcd i 0 = natAbs i

Next tactic:
simp [gcd]
@[simp]
theorem gcd_neg_right {x y : ℤ} : gcd x (-y) = gcd x y := by 

Proof state:
x y : ℤ
⊢ gcd x (-y) = gcd x y

Next tactic:
rw [Int.gcd, Int.gcd, natAbs_neg]
@[simp]
theorem gcd_neg_left {x y : ℤ} : gcd (-x) y = gcd x y := by 

Proof state:
x y : ℤ
⊢ gcd (-x) y = gcd x y

Next tactic:
rw [Int.gcd, Int.gcd, natAbs_neg]
theorem gcd_mul_left (i j k : ℤ) : gcd (i * j) (i * k) = natAbs i * gcd j k := by
  

Proof state:
i j k : ℤ
⊢ gcd (i * j) (i * k) = natAbs i * gcd j k

Next tactic:
rw [Int.gcd, Int.gcd, natAbs_mul, natAbs_mul]
theorem gcd_mul_left (i j k : ℤ) : gcd (i * j) (i * k) = natAbs i * gcd j k := by
  rw [Int.gcd, Int.gcd, natAbs_mul, natAbs_mul]
  

Proof state:
i j k : ℤ
⊢ Nat.gcd (natAbs i * natAbs j) (natAbs i * natAbs k) = natAbs i * Nat.gcd (natAbs j) (natAbs k)

Next tactic:
apply Nat.gcd_mul_left
theorem gcd_mul_right (i j k : ℤ) : gcd (i * j) (k * j) = gcd i k * natAbs j := by
  

Proof state:
i j k : ℤ
⊢ gcd (i * j) (k * j) = gcd i k * natAbs j

Next tactic:
rw [Int.gcd, Int.gcd, natAbs_mul, natAbs_mul]
theorem gcd_mul_right (i j k : ℤ) : gcd (i * j) (k * j) = gcd i k * natAbs j := by
  rw [Int.gcd, Int.gcd, natAbs_mul, natAbs_mul]
  

Proof state:
i j k : ℤ
⊢ Nat.gcd (natAbs i * natAbs j) (natAbs k * natAbs j) = Nat.gcd (natAbs i) (natAbs k) * natAbs j

Next tactic:
apply Nat.gcd_mul_right
theorem gcd_eq_zero_iff {i j : ℤ} : gcd i j = 0 ↔ i = 0 ∧ j = 0 := by
  

Proof state:
i j : ℤ
⊢ gcd i j = 0 ↔ i = 0 ∧ j = 0

Next tactic:
rw [gcd, Nat.gcd_eq_zero_iff, natAbs_eq_zero, natAbs_eq_zero]
theorem gcd_div {i j k : ℤ} (H1 : k ∣ i) (H2 : k ∣ j) :
    gcd (i / k) (j / k) = gcd i j / natAbs k := by
  

Proof state:
i j k : ℤ
H1 : k ∣ i
H2 : k ∣ j
⊢ gcd (i / k) (j / k) = gcd i j / natAbs k

Next tactic:
rw [gcd, natAbs_ediv i k H1, natAbs_ediv j k H2]
theorem gcd_div {i j k : ℤ} (H1 : k ∣ i) (H2 : k ∣ j) :
    gcd (i / k) (j / k) = gcd i j / natAbs k := by
  rw [gcd, natAbs_ediv i k H1, natAbs_ediv j k H2]
  

Proof state:
i j k : ℤ
H1 : k ∣ i
H2 : k ∣ j
⊢ Nat.gcd (natAbs i / natAbs k) (natAbs j / natAbs k) = gcd i j / natAbs k

Next tactic:
exact Nat.gcd_div (natAbs_dvd_natAbs.mpr H1) (natAbs_dvd_natAbs.mpr H2)
theorem gcd_div_gcd_div_gcd {i j : ℤ} (H : 0 < gcd i j) : gcd (i / gcd i j) (j / gcd i j) = 1 := by
  

Proof state:
i j : ℤ
H : 0 < gcd i j
⊢ gcd (i / ↑(gcd i j)) (j / ↑(gcd i j)) = 1

Next tactic:
rw [gcd_div (gcd_dvd_left i j) (gcd_dvd_right i j), natAbs_ofNat, Nat.div_self H]
theorem gcd_eq_right {i j : ℤ} (H : j ∣ i) : gcd i j = natAbs j := by 

Proof state:
i j : ℤ
H : j ∣ i
⊢ gcd i j = natAbs j

Next tactic:
rw [gcd_comm, gcd_eq_left H]
theorem ne_zero_of_gcd {x y : ℤ} (hc : gcd x y ≠ 0) : x ≠ 0 ∨ y ≠ 0 := by
  

Proof state:
x y : ℤ
hc : gcd x y ≠ 0
⊢ x ≠ 0 ∨ y ≠ 0

Next tactic:
contrapose! hc
theorem ne_zero_of_gcd {x y : ℤ} (hc : gcd x y ≠ 0) : x ≠ 0 ∨ y ≠ 0 := by
  contrapose! hc
  

Proof state:
x y : ℤ
hc : x = 0 ∧ y = 0
⊢ gcd x y = 0

Next tactic:
rw [hc.left, hc.right, gcd_zero_right, natAbs_zero]
theorem pow_dvd_pow_iff {m n : ℤ} {k : ℕ} (k0 : 0 < k) : m ^ k ∣ n ^ k ↔ m ∣ n := by
  

Proof state:
m n : ℤ
k : ℕ
k0 : 0 < k
⊢ m ^ k ∣ n ^ k ↔ m ∣ n

Next tactic:
refine' ⟨fun h => _, fun h => pow_dvd_pow_of_dvd h _⟩
theorem pow_dvd_pow_iff {m n : ℤ} {k : ℕ} (k0 : 0 < k) : m ^ k ∣ n ^ k ↔ m ∣ n := by
  refine' ⟨fun h => _, fun h => pow_dvd_pow_of_dvd h _⟩
  

Proof state:
m n : ℤ
k : ℕ
k0 : 0 < k
h : m ^ k ∣ n ^ k
⊢ m ∣ n

Next tactic:
rwa [← natAbs_dvd_natAbs, ← Nat.pow_dvd_pow_iff k0, ← Int.natAbs_pow, ← Int.natAbs_pow,
    natAbs_dvd_natAbs]
theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑n = a * x + b * y := by
  

Proof state:
a b : ℤ
n : ℕ
⊢ gcd a b ∣ n ↔ ∃ x y, ↑n = a * x + b * y

Next tactic:
constructor
theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑n = a * x + b * y := by
  constructor
  · 

Proof state:
case mp
a b : ℤ
n : ℕ
⊢ gcd a b ∣ n → ∃ x y, ↑n = a * x + b * y

Next tactic:
intro h
theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑n = a * x + b * y := by
  constructor
  · intro h
    

Proof state:
case mp
a b : ℤ
n : ℕ
h : gcd a b ∣ n
⊢ ∃ x y, ↑n = a * x + b * y

Next tactic:
rw [← Nat.mul_div_cancel' h, Int.ofNat_mul, gcd_eq_gcd_ab, add_mul, mul_assoc, mul_assoc]
theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑n = a * x + b * y := by
  constructor
  · intro h
    rw [← Nat.mul_div_cancel' h, Int.ofNat_mul, gcd_eq_gcd_ab, add_mul, mul_assoc, mul_assoc]
    

Proof state:
case mp
a b : ℤ
n : ℕ
h : gcd a b ∣ n
⊢ ∃ x y, a * (gcdA a b * ↑(n / gcd a b)) + b * (gcdB a b * ↑(n / gcd a b)) = a * x + b * y

Next tactic:
exact ⟨_, _, rfl⟩
theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑n = a * x + b * y := by
  constructor
  · intro h
    rw [← Nat.mul_div_cancel' h, Int.ofNat_mul, gcd_eq_gcd_ab, add_mul, mul_assoc, mul_assoc]
    exact ⟨_, _, rfl⟩
  · 

Proof state:
case mpr
a b : ℤ
n : ℕ
⊢ (∃ x y, ↑n = a * x + b * y) → gcd a b ∣ n

Next tactic:
rintro ⟨x, y, h⟩
theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑n = a * x + b * y := by
  constructor
  · intro h
    rw [← Nat.mul_div_cancel' h, Int.ofNat_mul, gcd_eq_gcd_ab, add_mul, mul_assoc, mul_assoc]
    exact ⟨_, _, rfl⟩
  · rintro ⟨x, y, h⟩
    

Proof state:
case mpr.intro.intro
a b : ℤ
n : ℕ
x y : ℤ
h : ↑n = a * x + b * y
⊢ gcd a b ∣ n

Next tactic:
rw [← Int.coe_nat_dvd, h]
theorem gcd_dvd_iff {a b : ℤ} {n : ℕ} : gcd a b ∣ n ↔ ∃ x y : ℤ, ↑n = a * x + b * y := by
  constructor
  · intro h
    rw [← Nat.mul_div_cancel' h, Int.ofNat_mul, gcd_eq_gcd_ab, add_mul, mul_assoc, mul_assoc]
    exact ⟨_, _, rfl⟩
  · rintro ⟨x, y, h⟩
    rw [← Int.coe_nat_dvd, h]
    

Proof state:
case mpr.intro.intro
a b : ℤ
n : ℕ
x y : ℤ
h : ↑n = a * x + b * y
⊢ ↑(gcd a b) ∣ a * x + b * y

Next tactic:
exact
      dvd_add (dvd_mul_of_dvd_left (gcd_dvd_left a b) _) (dvd_mul_of_dvd_left (gcd_dvd_right a b) y)
/-- Euclid's lemma: if `a ∣ b * c` and `gcd a c = 1` then `a ∣ b`.
Compare with `IsCoprime.dvd_of_dvd_mul_left` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_left_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_left_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a c = 1) :
    a ∣ b := by
  

Proof state:
a b c : ℤ
habc : a ∣ b * c
hab : gcd a c = 1
⊢ a ∣ b

Next tactic:
have := gcd_eq_gcd_ab a c
/-- Euclid's lemma: if `a ∣ b * c` and `gcd a c = 1` then `a ∣ b`.
Compare with `IsCoprime.dvd_of_dvd_mul_left` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_left_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_left_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a c = 1) :
    a ∣ b := by
  have := gcd_eq_gcd_ab a c
  

Proof state:
a b c : ℤ
habc : a ∣ b * c
hab : gcd a c = 1
this : ↑(gcd a c) = a * gcdA a c + c * gcdB a c
⊢ a ∣ b

Next tactic:
simp only [hab, Int.ofNat_zero, Int.ofNat_succ, zero_add] at this
/-- Euclid's lemma: if `a ∣ b * c` and `gcd a c = 1` then `a ∣ b`.
Compare with `IsCoprime.dvd_of_dvd_mul_left` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_left_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_left_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a c = 1) :
    a ∣ b := by
  have := gcd_eq_gcd_ab a c
  simp only [hab, Int.ofNat_zero, Int.ofNat_succ, zero_add] at this
  

Proof state:
a b c : ℤ
habc : a ∣ b * c
hab : gcd a c = 1
this : 1 = a * gcdA a c + c * gcdB a c
⊢ a ∣ b

Next tactic:
have : b * a * gcdA a c + b * c * gcdB a c = b := by simp [mul_assoc, ← mul_add, ← this]
/-- Euclid's lemma: if `a ∣ b * c` and `gcd a c = 1` then `a ∣ b`.
Compare with `IsCoprime.dvd_of_dvd_mul_left` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_left_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_left_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a c = 1) :
    a ∣ b := by
  have := gcd_eq_gcd_ab a c
  simp only [hab, Int.ofNat_zero, Int.ofNat_succ, zero_add] at this
  have : b * a * gcdA a c + b * c * gcdB a c = b := by 

Proof state:
a b c : ℤ
habc : a ∣ b * c
hab : gcd a c = 1
this : 1 = a * gcdA a c + c * gcdB a c
⊢ b * a * gcdA a c + b * c * gcdB a c = b

Next tactic:
simp [mul_assoc, ← mul_add, ← this]
/-- Euclid's lemma: if `a ∣ b * c` and `gcd a c = 1` then `a ∣ b`.
Compare with `IsCoprime.dvd_of_dvd_mul_left` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_left_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_left_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a c = 1) :
    a ∣ b := by
  have := gcd_eq_gcd_ab a c
  simp only [hab, Int.ofNat_zero, Int.ofNat_succ, zero_add] at this
  have : b * a * gcdA a c + b * c * gcdB a c = b := by simp [mul_assoc, ← mul_add, ← this]
  

Proof state:
a b c : ℤ
habc : a ∣ b * c
hab : gcd a c = 1
this✝ : 1 = a * gcdA a c + c * gcdB a c
this : b * a * gcdA a c + b * c * gcdB a c = b
⊢ a ∣ b

Next tactic:
rw [← this]
/-- Euclid's lemma: if `a ∣ b * c` and `gcd a c = 1` then `a ∣ b`.
Compare with `IsCoprime.dvd_of_dvd_mul_left` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_left_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_left_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a c = 1) :
    a ∣ b := by
  have := gcd_eq_gcd_ab a c
  simp only [hab, Int.ofNat_zero, Int.ofNat_succ, zero_add] at this
  have : b * a * gcdA a c + b * c * gcdB a c = b := by simp [mul_assoc, ← mul_add, ← this]
  rw [← this]
  

Proof state:
a b c : ℤ
habc : a ∣ b * c
hab : gcd a c = 1
this✝ : 1 = a * gcdA a c + c * gcdB a c
this : b * a * gcdA a c + b * c * gcdB a c = b
⊢ a ∣ b * a * gcdA a c + b * c * gcdB a c

Next tactic:
exact dvd_add (dvd_mul_of_dvd_left (dvd_mul_left a b) _) (dvd_mul_of_dvd_left habc _)
/-- Euclid's lemma: if `a ∣ b * c` and `gcd a b = 1` then `a ∣ c`.
Compare with `IsCoprime.dvd_of_dvd_mul_right` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_right_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_right_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a b = 1) :
    a ∣ c := by
  

Proof state:
a b c : ℤ
habc : a ∣ b * c
hab : gcd a b = 1
⊢ a ∣ c

Next tactic:
rw [mul_comm] at habc
/-- Euclid's lemma: if `a ∣ b * c` and `gcd a b = 1` then `a ∣ c`.
Compare with `IsCoprime.dvd_of_dvd_mul_right` and
`UniqueFactorizationMonoid.dvd_of_dvd_mul_right_of_no_prime_factors` -/
theorem dvd_of_dvd_mul_right_of_gcd_one {a b c : ℤ} (habc : a ∣ b * c) (hab : gcd a b = 1) :
    a ∣ c := by
  rw [mul_comm] at habc
  

Proof state:
a b c : ℤ
habc : a ∣ c * b
hab : gcd a b = 1
⊢ a ∣ c

Next tactic:
exact dvd_of_dvd_mul_left_of_gcd_one habc hab
/-- For nonzero integers `a` and `b`, `gcd a b` is the smallest positive natural number that can be
written in the form `a * x + b * y` for some pair of integers `x` and `y` -/
theorem gcd_least_linear {a b : ℤ} (ha : a ≠ 0) :
    IsLeast { n : ℕ | 0 < n ∧ ∃ x y : ℤ, ↑n = a * x + b * y } (a.gcd b) := by
  

Proof state:
a b : ℤ
ha : a ≠ 0
⊢ IsLeast {n | 0 < n ∧ ∃ x y, ↑n = a * x + b * y} (gcd a b)

Next tactic:
simp_rw [← gcd_dvd_iff]
/-- For nonzero integers `a` and `b`, `gcd a b` is the smallest positive natural number that can be
written in the form `a * x + b * y` for some pair of integers `x` and `y` -/
theorem gcd_least_linear {a b : ℤ} (ha : a ≠ 0) :
    IsLeast { n : ℕ | 0 < n ∧ ∃ x y : ℤ, ↑n = a * x + b * y } (a.gcd b) := by
  simp_rw [← gcd_dvd_iff]
  

Proof state:
a b : ℤ
ha : a ≠ 0
⊢ IsLeast {n | 0 < n ∧ gcd a b ∣ n} (gcd a b)

Next tactic:
constructor
/-- For nonzero integers `a` and `b`, `gcd a b` is the smallest positive natural number that can be
written in the form `a * x + b * y` for some pair of integers `x` and `y` -/
theorem gcd_least_linear {a b : ℤ} (ha : a ≠ 0) :
    IsLeast { n : ℕ | 0 < n ∧ ∃ x y : ℤ, ↑n = a * x + b * y } (a.gcd b) := by
  simp_rw [← gcd_dvd_iff]
  constructor
  · 

Proof state:
case left
a b : ℤ
ha : a ≠ 0
⊢ gcd a b ∈ {n | 0 < n ∧ gcd a b ∣ n}

Next tactic:
simpa [and_true_iff, dvd_refl, Set.mem_setOf_eq] using gcd_pos_of_ne_zero_left b ha
/-- For nonzero integers `a` and `b`, `gcd a b` is the smallest positive natural number that can be
written in the form `a * x + b * y` for some pair of integers `x` and `y` -/
theorem gcd_least_linear {a b : ℤ} (ha : a ≠ 0) :
    IsLeast { n : ℕ | 0 < n ∧ ∃ x y : ℤ, ↑n = a * x + b * y } (a.gcd b) := by
  simp_rw [← gcd_dvd_iff]
  constructor
  · simpa [and_true_iff, dvd_refl, Set.mem_setOf_eq] using gcd_pos_of_ne_zero_left b ha
  · 

Proof state:
case right
a b : ℤ
ha : a ≠ 0
⊢ gcd a b ∈ lowerBounds {n | 0 < n ∧ gcd a b ∣ n}

Next tactic:
simp only [lowerBounds, and_imp, Set.mem_setOf_eq]
/-- For nonzero integers `a` and `b`, `gcd a b` is the smallest positive natural number that can be
written in the form `a * x + b * y` for some pair of integers `x` and `y` -/
theorem gcd_least_linear {a b : ℤ} (ha : a ≠ 0) :
    IsLeast { n : ℕ | 0 < n ∧ ∃ x y : ℤ, ↑n = a * x + b * y } (a.gcd b) := by
  simp_rw [← gcd_dvd_iff]
  constructor
  · simpa [and_true_iff, dvd_refl, Set.mem_setOf_eq] using gcd_pos_of_ne_zero_left b ha
  · simp only [lowerBounds, and_imp, Set.mem_setOf_eq]
    

Proof state:
case right
a b : ℤ
ha : a ≠ 0
⊢ ∀ ⦃a_1 : ℕ⦄, 0 < a_1 → gcd a b ∣ a_1 → gcd a b ≤ a_1

Next tactic:
exact fun n hn_pos hn => Nat.le_of_dvd hn_pos hn
theorem lcm_comm (i j : ℤ) : lcm i j = lcm j i := by
  

Proof state:
i j : ℤ
⊢ lcm i j = lcm j i

Next tactic:
rw [Int.lcm, Int.lcm]
theorem lcm_comm (i j : ℤ) : lcm i j = lcm j i := by
  rw [Int.lcm, Int.lcm]
  

Proof state:
i j : ℤ
⊢ Nat.lcm (natAbs i) (natAbs j) = Nat.lcm (natAbs j) (natAbs i)

Next tactic:
exact Nat.lcm_comm _ _
theorem lcm_assoc (i j k : ℤ) : lcm (lcm i j) k = lcm i (lcm j k) := by
  

Proof state:
i j k : ℤ
⊢ lcm (↑(lcm i j)) k = lcm i ↑(lcm j k)

Next tactic:
rw [Int.lcm, Int.lcm, Int.lcm, Int.lcm, natAbs_ofNat, natAbs_ofNat]
theorem lcm_assoc (i j k : ℤ) : lcm (lcm i j) k = lcm i (lcm j k) := by
  rw [Int.lcm, Int.lcm, Int.lcm, Int.lcm, natAbs_ofNat, natAbs_ofNat]
  

Proof state:
i j k : ℤ
⊢ Nat.lcm (Nat.lcm (natAbs i) (natAbs j)) (natAbs k) = Nat.lcm (natAbs i) (Nat.lcm (natAbs j) (natAbs k))

Next tactic:
apply Nat.lcm_assoc
@[simp]
theorem lcm_zero_left (i : ℤ) : lcm 0 i = 0 := by
  

Proof state:
i : ℤ
⊢ lcm 0 i = 0

Next tactic:
rw [Int.lcm]
@[simp]
theorem lcm_zero_left (i : ℤ) : lcm 0 i = 0 := by
  rw [Int.lcm]
  

Proof state:
i : ℤ
⊢ Nat.lcm (natAbs 0) (natAbs i) = 0

Next tactic:
apply Nat.lcm_zero_left
@[simp]
theorem lcm_zero_right (i : ℤ) : lcm i 0 = 0 := by
  

Proof state:
i : ℤ
⊢ lcm i 0 = 0

Next tactic:
rw [Int.lcm]
@[simp]
theorem lcm_zero_right (i : ℤ) : lcm i 0 = 0 := by
  rw [Int.lcm]
  

Proof state:
i : ℤ
⊢ Nat.lcm (natAbs i) (natAbs 0) = 0

Next tactic:
apply Nat.lcm_zero_right
@[simp]
theorem lcm_one_left (i : ℤ) : lcm 1 i = natAbs i := by
  

Proof state:
i : ℤ
⊢ lcm 1 i = natAbs i

Next tactic:
rw [Int.lcm]
@[simp]
theorem lcm_one_left (i : ℤ) : lcm 1 i = natAbs i := by
  rw [Int.lcm]
  

Proof state:
i : ℤ
⊢ Nat.lcm (natAbs 1) (natAbs i) = natAbs i

Next tactic:
apply Nat.lcm_one_left
@[simp]
theorem lcm_one_right (i : ℤ) : lcm i 1 = natAbs i := by
  

Proof state:
i : ℤ
⊢ lcm i 1 = natAbs i

Next tactic:
rw [Int.lcm]
@[simp]
theorem lcm_one_right (i : ℤ) : lcm i 1 = natAbs i := by
  rw [Int.lcm]
  

Proof state:
i : ℤ
⊢ Nat.lcm (natAbs i) (natAbs 1) = natAbs i

Next tactic:
apply Nat.lcm_one_right
@[simp]
theorem lcm_self (i : ℤ) : lcm i i = natAbs i := by
  

Proof state:
i : ℤ
⊢ lcm i i = natAbs i

Next tactic:
rw [Int.lcm]
@[simp]
theorem lcm_self (i : ℤ) : lcm i i = natAbs i := by
  rw [Int.lcm]
  

Proof state:
i : ℤ
⊢ Nat.lcm (natAbs i) (natAbs i) = natAbs i

Next tactic:
apply Nat.lcm_self
theorem dvd_lcm_left (i j : ℤ) : i ∣ lcm i j := by
  

Proof state:
i j : ℤ
⊢ i ∣ ↑(lcm i j)

Next tactic:
rw [Int.lcm]
theorem dvd_lcm_left (i j : ℤ) : i ∣ lcm i j := by
  rw [Int.lcm]
  

Proof state:
i j : ℤ
⊢ i ∣ ↑(Nat.lcm (natAbs i) (natAbs j))

Next tactic:
apply coe_nat_dvd_right.mpr
theorem dvd_lcm_left (i j : ℤ) : i ∣ lcm i j := by
  rw [Int.lcm]
  apply coe_nat_dvd_right.mpr
  

Proof state:
i j : ℤ
⊢ natAbs i ∣ Nat.lcm (natAbs i) (natAbs j)

Next tactic:
apply Nat.dvd_lcm_left
theorem dvd_lcm_right (i j : ℤ) : j ∣ lcm i j := by
  

Proof state:
i j : ℤ
⊢ j ∣ ↑(lcm i j)

Next tactic:
rw [Int.lcm]
theorem dvd_lcm_right (i j : ℤ) : j ∣ lcm i j := by
  rw [Int.lcm]
  

Proof state:
i j : ℤ
⊢ j ∣ ↑(Nat.lcm (natAbs i) (natAbs j))

Next tactic:
apply coe_nat_dvd_right.mpr
theorem dvd_lcm_right (i j : ℤ) : j ∣ lcm i j := by
  rw [Int.lcm]
  apply coe_nat_dvd_right.mpr
  

Proof state:
i j : ℤ
⊢ natAbs j ∣ Nat.lcm (natAbs i) (natAbs j)

Next tactic:
apply Nat.dvd_lcm_right
theorem lcm_dvd {i j k : ℤ} : i ∣ k → j ∣ k → (lcm i j : ℤ) ∣ k := by
  

Proof state:
i j k : ℤ
⊢ i ∣ k → j ∣ k → ↑(lcm i j) ∣ k

Next tactic:
rw [Int.lcm]
theorem lcm_dvd {i j k : ℤ} : i ∣ k → j ∣ k → (lcm i j : ℤ) ∣ k := by
  rw [Int.lcm]
  

Proof state:
i j k : ℤ
⊢ i ∣ k → j ∣ k → ↑(Nat.lcm (natAbs i) (natAbs j)) ∣ k

Next tactic:
intro hi hj
theorem lcm_dvd {i j k : ℤ} : i ∣ k → j ∣ k → (lcm i j : ℤ) ∣ k := by
  rw [Int.lcm]
  intro hi hj
  

Proof state:
i j k : ℤ
hi : i ∣ k
hj : j ∣ k
⊢ ↑(Nat.lcm (natAbs i) (natAbs j)) ∣ k

Next tactic:
exact coe_nat_dvd_left.mpr (Nat.lcm_dvd (natAbs_dvd_natAbs.mpr hi) (natAbs_dvd_natAbs.mpr hj))
theorem lcm_mul_left {m n k : ℤ} : (m * n).lcm (m * k) = natAbs m * n.lcm k := by
  

Proof state:
m n k : ℤ
⊢ lcm (m * n) (m * k) = natAbs m * lcm n k

Next tactic:
simp_rw [Int.lcm, natAbs_mul, Nat.lcm_mul_left]
theorem lcm_mul_right {m n k : ℤ} : (m * n).lcm (k * n) = m.lcm k * natAbs n := by
  

Proof state:
m n k : ℤ
⊢ lcm (m * n) (k * n) = lcm m k * natAbs n

Next tactic:
simp_rw [Int.lcm, natAbs_mul, Nat.lcm_mul_right]
@[to_additive gcd_nsmul_eq_zero]
theorem pow_gcd_eq_one {M : Type*} [Monoid M] (x : M) {m n : ℕ} (hm : x ^ m = 1) (hn : x ^ n = 1) :
    x ^ m.gcd n = 1 := by
  

Proof state:
M : Type u_1
inst✝ : Monoid M
x : M
m n : ℕ
hm : x ^ m = 1
hn : x ^ n = 1
⊢ x ^ Nat.gcd m n = 1

Next tactic:
rcases m with (rfl | m)
@[to_additive gcd_nsmul_eq_zero]
theorem pow_gcd_eq_one {M : Type*} [Monoid M] (x : M) {m n : ℕ} (hm : x ^ m = 1) (hn : x ^ n = 1) :
    x ^ m.gcd n = 1 := by
  rcases m with (rfl | m); · 

Proof state:
case zero
M : Type u_1
inst✝ : Monoid M
x : M
n : ℕ
hn : x ^ n = 1
hm : x ^ Nat.zero = 1
⊢ x ^ Nat.gcd Nat.zero n = 1

Next tactic:
simp [hn]
@[to_additive gcd_nsmul_eq_zero]
theorem pow_gcd_eq_one {M : Type*} [Monoid M] (x : M) {m n : ℕ} (hm : x ^ m = 1) (hn : x ^ n = 1) :
    x ^ m.gcd n = 1 := by
  rcases m with (rfl | m); · simp [hn]
  

Proof state:
case succ
M : Type u_1
inst✝ : Monoid M
x : M
n : ℕ
hn : x ^ n = 1
m : ℕ
hm : x ^ Nat.succ m = 1
⊢ x ^ Nat.gcd (Nat.succ m) n = 1

Next tactic:
obtain ⟨y, rfl⟩ := isUnit_ofPowEqOne hm m.succ_ne_zero
@[to_additive gcd_nsmul_eq_zero]
theorem pow_gcd_eq_one {M : Type*} [Monoid M] (x : M) {m n : ℕ} (hm : x ^ m = 1) (hn : x ^ n = 1) :
    x ^ m.gcd n = 1 := by
  rcases m with (rfl | m); · simp [hn]
  obtain ⟨y, rfl⟩ := isUnit_ofPowEqOne hm m.succ_ne_zero
  

Proof state:
case succ.intro
M : Type u_1
inst✝ : Monoid M
n m : ℕ
y : Mˣ
hn : ↑y ^ n = 1
hm : ↑y ^ Nat.succ m = 1
⊢ ↑y ^ Nat.gcd (Nat.succ m) n = 1

Next tactic:
simp only [← Units.val_pow_eq_pow_val] at *