l3lab/ntp-mathlib huggingface dataset:
/-- Lift a semigroup homomorphism `f` to a bundled monoid homorphism. -/
@[to_additive "Lift an add semigroup homomorphism `f` to a bundled add monoid homorphism."]
def lift : (α →ₙ* β) ≃ (WithOne α →* β) where
  toFun f :=
    { toFun := fun x => Option.casesOn x 1 f, map_one' := rfl,
      map_mul' := fun x y => WithOne.cases_on x (by rw [one_mul]; exact (one_mul _).symm)
        (fun x => WithOne.cases_on y (by rw [mul_one]; 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝¹ : Mul α
inst✝ : MulOneClass β
f : α →ₙ* β
x✝ y : WithOne α
x : α
⊢ OneHom.toFun
      { toFun := fun x => Option.casesOn x 1 ⇑f,
        map_one' := (_ : (fun x => Option.casesOn x 1 ⇑f) 1 = (fun x => Option.casesOn x 1 ⇑f) 1) }
      ↑x =
    OneHom.toFun
        { toFun := fun x => Option.casesOn x 1 ⇑f,
          map_one' := (_ : (fun x => Option.casesOn x 1 ⇑f) 1 = (fun x => Option.casesOn x 1 ⇑f) 1) }
        ↑x *
      OneHom.toFun
        { toFun := fun x => Option.casesOn x 1 ⇑f,
          map_one' := (_ : (fun x => Option.casesOn x 1 ⇑f) 1 = (fun x => Option.casesOn x 1 ⇑f) 1) }
        1

Next tactic:
exact (mul_one _).symm
@[to_additive (attr := simp)]
theorem map_id : map (MulHom.id α) = MonoidHom.id (WithOne α) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : Mul α
inst✝¹ : Mul β
inst✝ : Mul γ
⊢ map (MulHom.id α) = MonoidHom.id (WithOne α)

Next tactic:
ext x
@[to_additive (attr := simp)]
theorem map_id : map (MulHom.id α) = MonoidHom.id (WithOne α) := by
  ext x
  

Proof state:
case h
α : Type u
β : Type v
γ : Type w
inst✝² : Mul α
inst✝¹ : Mul β
inst✝ : Mul γ
x : WithOne α
⊢ (map (MulHom.id α)) x = (MonoidHom.id (WithOne α)) x

Next tactic:
induction x using WithOne.cases_on
@[to_additive (attr := simp)]
theorem map_id : map (MulHom.id α) = MonoidHom.id (WithOne α) := by
  ext x
  induction x using WithOne.cases_on <;> 

Proof state:
case h.a
α : Type u
β : Type v
γ : Type w
inst✝² : Mul α
inst✝¹ : Mul β
inst✝ : Mul γ
⊢ (map (MulHom.id α)) 1 = (MonoidHom.id (WithOne α)) 1

Next tactic:
rfl
@[to_additive (attr := simp)]
theorem map_id : map (MulHom.id α) = MonoidHom.id (WithOne α) := by
  ext x
  induction x using WithOne.cases_on <;> 

Proof state:
case h.a
α : Type u
β : Type v
γ : Type w
inst✝² : Mul α
inst✝¹ : Mul β
inst✝ : Mul γ
a✝ : α
⊢ (map (MulHom.id α)) ↑a✝ = (MonoidHom.id (WithOne α)) ↑a✝

Next tactic:
rfl
@[to_additive]
theorem map_map (f : α →ₙ* β) (g : β →ₙ* γ) (x) : map g (map f x) = map (g.comp f) x := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : Mul α
inst✝¹ : Mul β
inst✝ : Mul γ
f : α →ₙ* β
g : β →ₙ* γ
x : WithOne α
⊢ (map g) ((map f) x) = (map (MulHom.comp g f)) x

Next tactic:
induction x using WithOne.cases_on
@[to_additive]
theorem map_map (f : α →ₙ* β) (g : β →ₙ* γ) (x) : map g (map f x) = map (g.comp f) x := by
  induction x using WithOne.cases_on <;> 

Proof state:
case a
α : Type u
β : Type v
γ : Type w
inst✝² : Mul α
inst✝¹ : Mul β
inst✝ : Mul γ
f : α →ₙ* β
g : β →ₙ* γ
⊢ (map g) ((map f) 1) = (map (MulHom.comp g f)) 1

Next tactic:
rfl
@[to_additive]
theorem map_map (f : α →ₙ* β) (g : β →ₙ* γ) (x) : map g (map f x) = map (g.comp f) x := by
  induction x using WithOne.cases_on <;> 

Proof state:
case a
α : Type u
β : Type v
γ : Type w
inst✝² : Mul α
inst✝¹ : Mul β
inst✝ : Mul γ
f : α →ₙ* β
g : β →ₙ* γ
a✝ : α
⊢ (map g) ((map f) ↑a✝) = (map (MulHom.comp g f)) ↑a✝

Next tactic:
rfl
instance involutiveInv [InvolutiveInv α] : InvolutiveInv (WithZero α) :=
  { WithZero.inv with
    inv_inv := fun a =>
      (Option.map_map _ _ _).trans <| by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : InvolutiveInv α
src✝ : Inv (WithZero α) := inv
a : WithZero α
⊢ Option.map (Inv.inv ∘ Inv.inv) a = a

Next tactic:
simp_rw [inv_comp_inv, Option.map_id, id]
instance divisionMonoid [DivisionMonoid α] : DivisionMonoid (WithZero α) :=
  { WithZero.divInvMonoid, WithZero.involutiveInv with
    mul_inv_rev := fun a b =>
      match a, b with
      | none, none => rfl
      | none, some b => rfl
      | some a, none => rfl
      | some a, some b => congr_arg some <| mul_inv_rev _ _,
    inv_eq_of_mul := fun a b ↦
      match a, b with
      | none, none => fun _ ↦ rfl
      | none, some b => fun _ ↦ by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : DivisionMonoid α
src✝¹ : DivInvMonoid (WithZero α) := divInvMonoid
src✝ : InvolutiveInv (WithZero α) := involutiveInv
a b✝ : WithZero α
b : α
x✝ : none * some b = 1
⊢ none⁻¹ = some b

Next tactic:
contradiction
instance divisionMonoid [DivisionMonoid α] : DivisionMonoid (WithZero α) :=
  { WithZero.divInvMonoid, WithZero.involutiveInv with
    mul_inv_rev := fun a b =>
      match a, b with
      | none, none => rfl
      | none, some b => rfl
      | some a, none => rfl
      | some a, some b => congr_arg some <| mul_inv_rev _ _,
    inv_eq_of_mul := fun a b ↦
      match a, b with
      | none, none => fun _ ↦ rfl
      | none, some b => fun _ ↦ by contradiction
      | some a, none => fun _ ↦ by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝ : DivisionMonoid α
src✝¹ : DivInvMonoid (WithZero α) := divInvMonoid
src✝ : InvolutiveInv (WithZero α) := involutiveInv
a✝ b : WithZero α
a : α
x✝ : some a * none = 1
⊢ (some a)⁻¹ = none

Next tactic:
contradiction
theorem Prime.eq_one_or_self_of_dvd {p : ℕ} (pp : p.Prime) (m : ℕ) (hm : m ∣ p) :
    m = 1 ∨ m = p := by
  

Proof state:
p : ℕ
pp : Prime p
m : ℕ
hm : m ∣ p
⊢ m = 1 ∨ m = p

Next tactic:
obtain ⟨n, hn⟩ := hm
theorem Prime.eq_one_or_self_of_dvd {p : ℕ} (pp : p.Prime) (m : ℕ) (hm : m ∣ p) :
    m = 1 ∨ m = p := by
  obtain ⟨n, hn⟩ := hm
  

Proof state:
case intro
p : ℕ
pp : Prime p
m n : ℕ
hn : p = m * n
⊢ m = 1 ∨ m = p

Next tactic:
have := pp.isUnit_or_isUnit hn
theorem Prime.eq_one_or_self_of_dvd {p : ℕ} (pp : p.Prime) (m : ℕ) (hm : m ∣ p) :
    m = 1 ∨ m = p := by
  obtain ⟨n, hn⟩ := hm
  have := pp.isUnit_or_isUnit hn
  

Proof state:
case intro
p : ℕ
pp : Prime p
m n : ℕ
hn : p = m * n
this : IsUnit m ∨ IsUnit n
⊢ m = 1 ∨ m = p

Next tactic:
rw [Nat.isUnit_iff, Nat.isUnit_iff] at this
theorem Prime.eq_one_or_self_of_dvd {p : ℕ} (pp : p.Prime) (m : ℕ) (hm : m ∣ p) :
    m = 1 ∨ m = p := by
  obtain ⟨n, hn⟩ := hm
  have := pp.isUnit_or_isUnit hn
  rw [Nat.isUnit_iff, Nat.isUnit_iff] at this
  

Proof state:
case intro
p : ℕ
pp : Prime p
m n : ℕ
hn : p = m * n
this : m = 1 ∨ n = 1
⊢ m = 1 ∨ m = p

Next tactic:
apply Or.imp_right _ this
theorem Prime.eq_one_or_self_of_dvd {p : ℕ} (pp : p.Prime) (m : ℕ) (hm : m ∣ p) :
    m = 1 ∨ m = p := by
  obtain ⟨n, hn⟩ := hm
  have := pp.isUnit_or_isUnit hn
  rw [Nat.isUnit_iff, Nat.isUnit_iff] at this
  apply Or.imp_right _ this
  

Proof state:
p : ℕ
pp : Prime p
m n : ℕ
hn : p = m * n
this : m = 1 ∨ n = 1
⊢ n = 1 → m = p

Next tactic:
rintro rfl
theorem Prime.eq_one_or_self_of_dvd {p : ℕ} (pp : p.Prime) (m : ℕ) (hm : m ∣ p) :
    m = 1 ∨ m = p := by
  obtain ⟨n, hn⟩ := hm
  have := pp.isUnit_or_isUnit hn
  rw [Nat.isUnit_iff, Nat.isUnit_iff] at this
  apply Or.imp_right _ this
  rintro rfl
  

Proof state:
p : ℕ
pp : Prime p
m : ℕ
hn : p = m * 1
this : m = 1 ∨ 1 = 1
⊢ m = p

Next tactic:
rw [hn, mul_one]
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  

Proof state:
p : ℕ
⊢ Prime p ↔ 2 ≤ p ∧ ∀ (m : ℕ), m ∣ p → m = 1 ∨ m = p

Next tactic:
refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
  -- Porting note: needed to make ℕ explicit
  

Proof state:
p : ℕ
h : 2 ≤ p ∧ ∀ (m : ℕ), m ∣ p → m = 1 ∨ m = p
⊢ Prime p

Next tactic:
have h1 := (@one_lt_two ℕ ..).trans_le h.1
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
  -- Porting note: needed to make ℕ explicit
  have h1 := (@one_lt_two ℕ ..).trans_le h.1
  

Proof state:
p : ℕ
h : 2 ≤ p ∧ ∀ (m : ℕ), m ∣ p → m = 1 ∨ m = p
h1 : 1 < p
⊢ Prime p

Next tactic:
refine' ⟨mt Nat.isUnit_iff.mp h1.ne', fun a b hab => _⟩
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
  -- Porting note: needed to make ℕ explicit
  have h1 := (@one_lt_two ℕ ..).trans_le h.1
  refine' ⟨mt Nat.isUnit_iff.mp h1.ne', fun a b hab => _⟩
  

Proof state:
p : ℕ
h : 2 ≤ p ∧ ∀ (m : ℕ), m ∣ p → m = 1 ∨ m = p
h1 : 1 < p
a b : ℕ
hab : p = a * b
⊢ IsUnit a ∨ IsUnit b

Next tactic:
simp only [Nat.isUnit_iff]
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
  -- Porting note: needed to make ℕ explicit
  have h1 := (@one_lt_two ℕ ..).trans_le h.1
  refine' ⟨mt Nat.isUnit_iff.mp h1.ne', fun a b hab => _⟩
  simp only [Nat.isUnit_iff]
  

Proof state:
p : ℕ
h : 2 ≤ p ∧ ∀ (m : ℕ), m ∣ p → m = 1 ∨ m = p
h1 : 1 < p
a b : ℕ
hab : p = a * b
⊢ a = 1 ∨ b = 1

Next tactic:
apply Or.imp_right _ (h.2 a _)
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
  -- Porting note: needed to make ℕ explicit
  have h1 := (@one_lt_two ℕ ..).trans_le h.1
  refine' ⟨mt Nat.isUnit_iff.mp h1.ne', fun a b hab => _⟩
  simp only [Nat.isUnit_iff]
  apply Or.imp_right _ (h.2 a _)
  · 

Proof state:
p : ℕ
h : 2 ≤ p ∧ ∀ (m : ℕ), m ∣ p → m = 1 ∨ m = p
h1 : 1 < p
a b : ℕ
hab : p = a * b
⊢ a = p → b = 1

Next tactic:
rintro rfl
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
  -- Porting note: needed to make ℕ explicit
  have h1 := (@one_lt_two ℕ ..).trans_le h.1
  refine' ⟨mt Nat.isUnit_iff.mp h1.ne', fun a b hab => _⟩
  simp only [Nat.isUnit_iff]
  apply Or.imp_right _ (h.2 a _)
  · rintro rfl
    

Proof state:
a b : ℕ
h : 2 ≤ a ∧ ∀ (m : ℕ), m ∣ a → m = 1 ∨ m = a
h1 : 1 < a
hab : a = a * b
⊢ b = 1

Next tactic:
rw [← mul_right_inj' (pos_of_gt h1).ne', ← hab, mul_one]
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
  -- Porting note: needed to make ℕ explicit
  have h1 := (@one_lt_two ℕ ..).trans_le h.1
  refine' ⟨mt Nat.isUnit_iff.mp h1.ne', fun a b hab => _⟩
  simp only [Nat.isUnit_iff]
  apply Or.imp_right _ (h.2 a _)
  · rintro rfl
    rw [← mul_right_inj' (pos_of_gt h1).ne', ← hab, mul_one]
  · 

Proof state:
p : ℕ
h : 2 ≤ p ∧ ∀ (m : ℕ), m ∣ p → m = 1 ∨ m = p
h1 : 1 < p
a b : ℕ
hab : p = a * b
⊢ a ∣ p

Next tactic:
rw [hab]
theorem prime_def_lt'' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ (m) (_ : m ∣ p), m = 1 ∨ m = p := by
  refine' ⟨fun h => ⟨h.two_le, h.eq_one_or_self_of_dvd⟩, fun h => _⟩
  -- Porting note: needed to make ℕ explicit
  have h1 := (@one_lt_two ℕ ..).trans_le h.1
  refine' ⟨mt Nat.isUnit_iff.mp h1.ne', fun a b hab => _⟩
  simp only [Nat.isUnit_iff]
  apply Or.imp_right _ (h.2 a _)
  · rintro rfl
    rw [← mul_right_inj' (pos_of_gt h1).ne', ← hab, mul_one]
  · rw [hab]
    

Proof state:
p : ℕ
h : 2 ≤ p ∧ ∀ (m : ℕ), m ∣ p → m = 1 ∨ m = p
h1 : 1 < p
a b : ℕ
hab : p = a * b
⊢ a ∣ a * b

Next tactic:
exact dvd_mul_right _ _
theorem prime_def_lt' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m < p → ¬m ∣ p :=
  prime_def_lt.trans <|
    and_congr_right fun p2 =>
      forall_congr' fun m =>
        ⟨fun h m2 l d => not_lt_of_ge m2 ((h l d).symm ▸ by 

Proof state:
p : ℕ
p2 : 2 ≤ p
m : ℕ
h : m < p → m ∣ p → m = 1
m2 : 2 ≤ m
l : m < p
d : m ∣ p
⊢ 1 < 2

Next tactic:
decide
theorem prime_def_lt' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m < p → ¬m ∣ p :=
  prime_def_lt.trans <|
    and_congr_right fun p2 =>
      forall_congr' fun m =>
        ⟨fun h m2 l d => not_lt_of_ge m2 ((h l d).symm ▸ by decide), fun h l d => by
          

Proof state:
p : ℕ
p2 : 2 ≤ p
m : ℕ
h : 2 ≤ m → m < p → ¬m ∣ p
l : m < p
d : m ∣ p
⊢ m = 1

Next tactic:
rcases m with (_ | _ | m)
theorem prime_def_lt' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m < p → ¬m ∣ p :=
  prime_def_lt.trans <|
    and_congr_right fun p2 =>
      forall_congr' fun m =>
        ⟨fun h m2 l d => not_lt_of_ge m2 ((h l d).symm ▸ by decide), fun h l d => by
          rcases m with (_ | _ | m)
          · 

Proof state:
case zero
p : ℕ
p2 : 2 ≤ p
h : 2 ≤ zero → zero < p → ¬zero ∣ p
l : zero < p
d : zero ∣ p
⊢ zero = 1

Next tactic:
rw [eq_zero_of_zero_dvd d] at p2
theorem prime_def_lt' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m < p → ¬m ∣ p :=
  prime_def_lt.trans <|
    and_congr_right fun p2 =>
      forall_congr' fun m =>
        ⟨fun h m2 l d => not_lt_of_ge m2 ((h l d).symm ▸ by decide), fun h l d => by
          rcases m with (_ | _ | m)
          · rw [eq_zero_of_zero_dvd d] at p2
            

Proof state:
case zero
p : ℕ
p2 : 2 ≤ 0
h : 2 ≤ zero → zero < p → ¬zero ∣ p
l : zero < p
d : zero ∣ p
⊢ zero = 1

Next tactic:
revert p2
theorem prime_def_lt' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m < p → ¬m ∣ p :=
  prime_def_lt.trans <|
    and_congr_right fun p2 =>
      forall_congr' fun m =>
        ⟨fun h m2 l d => not_lt_of_ge m2 ((h l d).symm ▸ by decide), fun h l d => by
          rcases m with (_ | _ | m)
          · rw [eq_zero_of_zero_dvd d] at p2
            revert p2
            

Proof state:
case zero
p : ℕ
h : 2 ≤ zero → zero < p → ¬zero ∣ p
l : zero < p
d : zero ∣ p
⊢ 2 ≤ 0 → zero = 1

Next tactic:
decide
theorem prime_def_lt' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m < p → ¬m ∣ p :=
  prime_def_lt.trans <|
    and_congr_right fun p2 =>
      forall_congr' fun m =>
        ⟨fun h m2 l d => not_lt_of_ge m2 ((h l d).symm ▸ by decide), fun h l d => by
          rcases m with (_ | _ | m)
          · rw [eq_zero_of_zero_dvd d] at p2
            revert p2
            decide
          · 

Proof state:
case succ.zero
p : ℕ
p2 : 2 ≤ p
h : 2 ≤ succ zero → succ zero < p → ¬succ zero ∣ p
l : succ zero < p
d : succ zero ∣ p
⊢ succ zero = 1

Next tactic:
rfl
theorem prime_def_lt' {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m < p → ¬m ∣ p :=
  prime_def_lt.trans <|
    and_congr_right fun p2 =>
      forall_congr' fun m =>
        ⟨fun h m2 l d => not_lt_of_ge m2 ((h l d).symm ▸ by decide), fun h l d => by
          rcases m with (_ | _ | m)
          · rw [eq_zero_of_zero_dvd d] at p2
            revert p2
            decide
          · rfl
          · 

Proof state:
case succ.succ
p : ℕ
p2 : 2 ≤ p
m : ℕ
h : 2 ≤ succ (succ m) → succ (succ m) < p → ¬succ (succ m) ∣ p
l : succ (succ m) < p
d : succ (succ m) ∣ p
⊢ succ (succ m) = 1

Next tactic:
exact (h le_add_self l).elim d
theorem prime_def_le_sqrt {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m ≤ sqrt p → ¬m ∣ p :=
  prime_def_lt'.trans <|
    and_congr_right fun p2 =>
      ⟨fun a m m2 l => a m m2 <| lt_of_le_of_lt l <| sqrt_lt_self p2, fun a =>
        have : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k := fun {m k} mk m1 e =>
          a m m1 (le_sqrt.2 (e.symm ▸ Nat.mul_le_mul_left m mk)) ⟨k, e⟩
        fun m m2 l ⟨k, e⟩ => by
        

Proof state:
p : ℕ
p2 : 2 ≤ p
a : ∀ (m : ℕ), 2 ≤ m → m ≤ sqrt p → ¬m ∣ p
this : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k
m : ℕ
m2 : 2 ≤ m
l : m < p
x✝ : m ∣ p
k : ℕ
e : p = m * k
⊢ False

Next tactic:
rcases le_total m k with mk | km
theorem prime_def_le_sqrt {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m ≤ sqrt p → ¬m ∣ p :=
  prime_def_lt'.trans <|
    and_congr_right fun p2 =>
      ⟨fun a m m2 l => a m m2 <| lt_of_le_of_lt l <| sqrt_lt_self p2, fun a =>
        have : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k := fun {m k} mk m1 e =>
          a m m1 (le_sqrt.2 (e.symm ▸ Nat.mul_le_mul_left m mk)) ⟨k, e⟩
        fun m m2 l ⟨k, e⟩ => by
        rcases le_total m k with mk | km
        · 

Proof state:
case inl
p : ℕ
p2 : 2 ≤ p
a : ∀ (m : ℕ), 2 ≤ m → m ≤ sqrt p → ¬m ∣ p
this : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k
m : ℕ
m2 : 2 ≤ m
l : m < p
x✝ : m ∣ p
k : ℕ
e : p = m * k
mk : m ≤ k
⊢ False

Next tactic:
exact this mk m2 e
theorem prime_def_le_sqrt {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m ≤ sqrt p → ¬m ∣ p :=
  prime_def_lt'.trans <|
    and_congr_right fun p2 =>
      ⟨fun a m m2 l => a m m2 <| lt_of_le_of_lt l <| sqrt_lt_self p2, fun a =>
        have : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k := fun {m k} mk m1 e =>
          a m m1 (le_sqrt.2 (e.symm ▸ Nat.mul_le_mul_left m mk)) ⟨k, e⟩
        fun m m2 l ⟨k, e⟩ => by
        rcases le_total m k with mk | km
        · exact this mk m2 e
        · 

Proof state:
case inr
p : ℕ
p2 : 2 ≤ p
a : ∀ (m : ℕ), 2 ≤ m → m ≤ sqrt p → ¬m ∣ p
this : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k
m : ℕ
m2 : 2 ≤ m
l : m < p
x✝ : m ∣ p
k : ℕ
e : p = m * k
km : k ≤ m
⊢ False

Next tactic:
rw [mul_comm] at e
theorem prime_def_le_sqrt {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m ≤ sqrt p → ¬m ∣ p :=
  prime_def_lt'.trans <|
    and_congr_right fun p2 =>
      ⟨fun a m m2 l => a m m2 <| lt_of_le_of_lt l <| sqrt_lt_self p2, fun a =>
        have : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k := fun {m k} mk m1 e =>
          a m m1 (le_sqrt.2 (e.symm ▸ Nat.mul_le_mul_left m mk)) ⟨k, e⟩
        fun m m2 l ⟨k, e⟩ => by
        rcases le_total m k with mk | km
        · exact this mk m2 e
        · rw [mul_comm] at e
          

Proof state:
case inr
p : ℕ
p2 : 2 ≤ p
a : ∀ (m : ℕ), 2 ≤ m → m ≤ sqrt p → ¬m ∣ p
this : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k
m : ℕ
m2 : 2 ≤ m
l : m < p
x✝ : m ∣ p
k : ℕ
e : p = k * m
km : k ≤ m
⊢ False

Next tactic:
refine' this km (lt_of_mul_lt_mul_right _ (zero_le m)) e
theorem prime_def_le_sqrt {p : ℕ} : Prime p ↔ 2 ≤ p ∧ ∀ m, 2 ≤ m → m ≤ sqrt p → ¬m ∣ p :=
  prime_def_lt'.trans <|
    and_congr_right fun p2 =>
      ⟨fun a m m2 l => a m m2 <| lt_of_le_of_lt l <| sqrt_lt_self p2, fun a =>
        have : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k := fun {m k} mk m1 e =>
          a m m1 (le_sqrt.2 (e.symm ▸ Nat.mul_le_mul_left m mk)) ⟨k, e⟩
        fun m m2 l ⟨k, e⟩ => by
        rcases le_total m k with mk | km
        · exact this mk m2 e
        · rw [mul_comm] at e
          refine' this km (lt_of_mul_lt_mul_right _ (zero_le m)) e
          

Proof state:
case inr
p : ℕ
p2 : 2 ≤ p
a : ∀ (m : ℕ), 2 ≤ m → m ≤ sqrt p → ¬m ∣ p
this : ∀ {m k : ℕ}, m ≤ k → 1 < m → p ≠ m * k
m : ℕ
m2 : 2 ≤ m
l : m < p
x✝ : m ∣ p
k : ℕ
e : p = k * m
km : k ≤ m
⊢ 1 * m < k * m

Next tactic:
rwa [one_mul, ← e]
theorem prime_of_coprime (n : ℕ) (h1 : 1 < n) (h : ∀ m < n, m ≠ 0 → n.Coprime m) : Prime n := by
  

Proof state:
n : ℕ
h1 : 1 < n
h : ∀ m < n, m ≠ 0 → Coprime n m
⊢ Prime n

Next tactic:
refine' prime_def_lt.mpr ⟨h1, fun m mlt mdvd => _⟩
theorem prime_of_coprime (n : ℕ) (h1 : 1 < n) (h : ∀ m < n, m ≠ 0 → n.Coprime m) : Prime n := by
  refine' prime_def_lt.mpr ⟨h1, fun m mlt mdvd => _⟩
  

Proof state:
n : ℕ
h1 : 1 < n
h : ∀ m < n, m ≠ 0 → Coprime n m
m : ℕ
mlt : m < n
mdvd : m ∣ n
⊢ m = 1

Next tactic:
have hm : m ≠ 0 := by
    rintro rfl
    rw [zero_dvd_iff] at mdvd
    exact mlt.ne' mdvd
theorem prime_of_coprime (n : ℕ) (h1 : 1 < n) (h : ∀ m < n, m ≠ 0 → n.Coprime m) : Prime n := by
  refine' prime_def_lt.mpr ⟨h1, fun m mlt mdvd => _⟩
  have hm : m ≠ 0 := by
    

Proof state:
n : ℕ
h1 : 1 < n
h : ∀ m < n, m ≠ 0 → Coprime n m
m : ℕ
mlt : m < n
mdvd : m ∣ n
⊢ m ≠ 0

Next tactic:
rintro rfl
theorem prime_of_coprime (n : ℕ) (h1 : 1 < n) (h : ∀ m < n, m ≠ 0 → n.Coprime m) : Prime n := by
  refine' prime_def_lt.mpr ⟨h1, fun m mlt mdvd => _⟩
  have hm : m ≠ 0 := by
    rintro rfl
    

Proof state:
n : ℕ
h1 : 1 < n
h : ∀ m < n, m ≠ 0 → Coprime n m
mlt : 0 < n
mdvd : 0 ∣ n
⊢ False

Next tactic:
rw [zero_dvd_iff] at mdvd
theorem prime_of_coprime (n : ℕ) (h1 : 1 < n) (h : ∀ m < n, m ≠ 0 → n.Coprime m) : Prime n := by
  refine' prime_def_lt.mpr ⟨h1, fun m mlt mdvd => _⟩
  have hm : m ≠ 0 := by
    rintro rfl
    rw [zero_dvd_iff] at mdvd
    

Proof state:
n : ℕ
h1 : 1 < n
h : ∀ m < n, m ≠ 0 → Coprime n m
mlt : 0 < n
mdvd : n = 0
⊢ False

Next tactic:
exact mlt.ne' mdvd
theorem prime_of_coprime (n : ℕ) (h1 : 1 < n) (h : ∀ m < n, m ≠ 0 → n.Coprime m) : Prime n := by
  refine' prime_def_lt.mpr ⟨h1, fun m mlt mdvd => _⟩
  have hm : m ≠ 0 := by
    rintro rfl
    rw [zero_dvd_iff] at mdvd
    exact mlt.ne' mdvd
  

Proof state:
n : ℕ
h1 : 1 < n
h : ∀ m < n, m ≠ 0 → Coprime n m
m : ℕ
mlt : m < n
mdvd : m ∣ n
hm : m ≠ 0
⊢ m = 1

Next tactic:
exact (h m mlt hm).symm.eq_one_of_dvd mdvd
theorem prime_two : Prime 2 := by 

Proof state:
⊢ Prime 2

Next tactic:
decide
theorem prime_three : Prime 3 := by 

Proof state:
⊢ Prime 3

Next tactic:
decide
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  

Proof state:
p : ℕ
hp : Prime p
h_two : p ≠ 2
h_three : p ≠ 3
⊢ 5 ≤ p

Next tactic:
by_contra! h
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  by_contra! h
  

Proof state:
p : ℕ
hp : Prime p
h_two : p ≠ 2
h_three : p ≠ 3
h : p < 5
⊢ False

Next tactic:
revert h_two h_three hp
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  by_contra! h
  revert h_two h_three hp
  -- Porting note: was `decide!`
  

Proof state:
p : ℕ
h : p < 5
⊢ Prime p → p ≠ 2 → p ≠ 3 → False

Next tactic:
match p with
  | 0 => decide
  | 1 => decide
  | 2 => decide
  | 3 => decide
  | 4 => decide
  | n + 5 => exact (h.not_le le_add_self).elim
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  by_contra! h
  revert h_two h_three hp
  -- Porting note: was `decide!`
  match p with
  | 0 => 

Proof state:
p : ℕ
h : 0 < 5
⊢ Prime 0 → 0 ≠ 2 → 0 ≠ 3 → False

Next tactic:
decide
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  by_contra! h
  revert h_two h_three hp
  -- Porting note: was `decide!`
  match p with
  | 0 => decide
  | 1 => 

Proof state:
p : ℕ
h : 1 < 5
⊢ Prime 1 → 1 ≠ 2 → 1 ≠ 3 → False

Next tactic:
decide
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  by_contra! h
  revert h_two h_three hp
  -- Porting note: was `decide!`
  match p with
  | 0 => decide
  | 1 => decide
  | 2 => 

Proof state:
p : ℕ
h : 2 < 5
⊢ Prime 2 → 2 ≠ 2 → 2 ≠ 3 → False

Next tactic:
decide
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  by_contra! h
  revert h_two h_three hp
  -- Porting note: was `decide!`
  match p with
  | 0 => decide
  | 1 => decide
  | 2 => decide
  | 3 => 

Proof state:
p : ℕ
h : 3 < 5
⊢ Prime 3 → 3 ≠ 2 → 3 ≠ 3 → False

Next tactic:
decide
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  by_contra! h
  revert h_two h_three hp
  -- Porting note: was `decide!`
  match p with
  | 0 => decide
  | 1 => decide
  | 2 => decide
  | 3 => decide
  | 4 => 

Proof state:
p : ℕ
h : 4 < 5
⊢ Prime 4 → 4 ≠ 2 → 4 ≠ 3 → False

Next tactic:
decide
theorem Prime.five_le_of_ne_two_of_ne_three {p : ℕ} (hp : p.Prime) (h_two : p ≠ 2)
    (h_three : p ≠ 3) : 5 ≤ p := by
  by_contra! h
  revert h_two h_three hp
  -- Porting note: was `decide!`
  match p with
  | 0 => decide
  | 1 => decide
  | 2 => decide
  | 3 => decide
  | 4 => decide
  | n + 5 => 

Proof state:
p n : ℕ
h : n + 5 < 5
⊢ Prime (n + 5) → n + 5 ≠ 2 → n + 5 ≠ 3 → False

Next tactic:
exact (h.not_le le_add_self).elim
theorem not_prime_mul {a b : ℕ} (a1 : 1 < a) (b1 : 1 < b) : ¬Prime (a * b) := fun h =>
  ne_of_lt (Nat.mul_lt_mul_of_pos_left b1 (lt_of_succ_lt a1)) <| by
    

Proof state:
a b : ℕ
a1 : 1 < a
b1 : 1 < b
h : Prime (a * b)
⊢ a * 1 = a * b

Next tactic:
simpa using (dvd_prime_two_le h a1).1 (dvd_mul_right _ _)
theorem not_prime_mul' {a b n : ℕ} (h : a * b = n) (h₁ : 1 < a) (h₂ : 1 < b) : ¬Prime n := by
  

Proof state:
a b n : ℕ
h : a * b = n
h₁ : 1 < a
h₂ : 1 < b
⊢ ¬Prime n

Next tactic:
rw [← h]
theorem not_prime_mul' {a b n : ℕ} (h : a * b = n) (h₁ : 1 < a) (h₂ : 1 < b) : ¬Prime n := by
  rw [← h]
  

Proof state:
a b n : ℕ
h : a * b = n
h₁ : 1 < a
h₂ : 1 < b
⊢ ¬Prime (a * b)

Next tactic:
exact not_prime_mul h₁ h₂