open MyNat
/-- 素数。1より大きく、自分自身と1以外で割り切れない数 -/
@[simp, grind]
def MyNat.IsPrime (n : MyNat) : Prop :=
n > 1 ∧ ∀ k, 1 < k → k < n → ¬ k ∣ n
instance MyNat.lt_wfRel : WellFoundedRelation MyNat where
rel := (· < ·)
wf := by
apply WellFounded.intro
intro n
induction n with
| zero =>
apply Acc.intro 0
grind
| succ n ih =>
apply Acc.intro (n + 1)
intro m h
have : m = n ∨ m < n := by
apply MyNat.eq_or_lt_of_le
simp_all [MyNat.lt_iff_add_one_le]
match this with
| Or.inl e => simp_all
| Or.inr e =>
cases ih
grind
noncomputable def strongRecOn.{u}
{motive : MyNat → Sort u}
(n : MyNat)
(ind : ∀ n, (∀ m, m < n → motive m) → motive n) : motive n :=
MyNat.lt_wfRel.wf.fix ind n
theorem MyNat.exists_prime_factor (n : MyNat) (hgt : 1 < n) :
∃ k, IsPrime k ∧ k ∣ n := by
induction n using strongRecOn with
| ind n ih =>
-- nが素数であるかどうかによって場合分けをする。
by_cases hprime : IsPrime n
case pos =>
-- nが素数であるときは明らか。
grind
-- 以下、nは素数でないとする。
-- nは素数ではないのでnより真に小さい約数を持つ。
have ⟨k, _, _, _⟩ : ∃ k, 1 < k ∧ k < n ∧ k ∣ n := by
simp_all
-- 帰納的に、k には素因数が存在するとしてよい。
have := ih k ‹k < n› ‹1 < k›
-- k ∣ n なので、k に素因数があるなら n にも存在する。
grind
/-- 階乗関数 -/
@[grind, simp]
def MyNat.factorial : MyNat → MyNat
| 0 => 1
| n + 1 => (n + 1) * factorial n
@[inherit_doc factorial] notation:max n "!" => factorial n
@[simp]
theorem MyNat.factorial_zero : 0 ! = 1 := by
rfl
@[grind =]
theorem MyNat.factorial_succ (n : MyNat) : (n + 1)! = (n + 1) * n ! := by
rfl
/-- 階乗は常に正 -/
@[grind <=]
theorem MyNat.factorial_pos (n : MyNat) : 0 < n ! := by
induction n with
| zero => simp +decide
| succ n ih => grind
/-- 1 ≤ k ≤ n なら k は n! の約数 -/
@[grind →]
theorem MyNat.dvd_factorial (n : MyNat) {k : MyNat} (hk : k ≤ n) (kpos : 0 < k) : k ∣ (n !) := by
induction n with
| zero =>
grind
| succ n ih =>
have : k = n + 1 ∨ k ≤ n := by
have : k = n + 1 ∨ k < n + 1 := by exact eq_or_lt_of_le hk
cases this with grind
rcases this with eq | le
· grind
· replace ih := ih le
rw [show (n + 1)! = (n + 1) * n ! from by rfl]
grind
/-- 素数は無限に存在する -/
theorem MyNat.InfinitudeOfPrimes : ∀ n : MyNat, ∃ p > n, IsPrime p := by
-- n が与えられたとする。
intro n
-- このとき n! + 1 の素因数 p を考える。
have : 1 < n ! + 1 := by grind
obtain ⟨p, hp, _⟩ := exists_prime_factor (n ! + 1) this
-- p は素数なので、p > n を示せばよい。
suffices p > n from by grind
-- 仮に p ≤ n だとする。
suffices ¬ (p ≤ n) from by grind
intro hle
-- このとき p は n! の約数である。
have hpdvd : p ∣ n ! := by
apply dvd_factorial <;> grind
-- p は n! + 1 の約数でもあるので、したがって p は 1 の約数であることになる。
have : p ∣ 1 := by
rw [show 1 = (n ! + 1) - n ! from by grind]
grind [Nat.dvd_sub]
-- つまり、p = 1 である。
-- これは p が素数であることに矛盾する。
grind