練習(素数)

問題

2から100までの素数を求めよ。

調査

素数… 数学弱いので、抽出方法を調べてみました。

エラトステネスの篩

数学において、エラトステネスの篩(エラトステネスのふるい)は素数判定法の一種で、指定された整数以下の全ての素数を発見するための単純なアルゴリズムである。古代ギリシアの科学者、エラトステネスが考案したとされるため、この名がある。

http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%A9%E3%83%88%E3%82%B9%E3%83%86%E3%83%8D%E3%82%B9%E3%81%AE%E7%AF%A9

へ~って感じです。

回答

;2から n までの検索用リストを作成する。
(defun make-search-lst (n &optional (lst nil))
  (if (= n 1)
    lst
    (make-search-lst (1- n) (cons n lst))))
;numで指定された数の倍数をlstから削除する。
(defun delete-multiple-from-search-lst (num lst)
  (labels
    ((rec (i)
          (if (> (* num i) (car (last lst)))
            lst
            (progn
              (setf lst (delete (* num i) lst))
              (rec (1+ i))))))
    (rec 1)))
;s-lstの中から素数を抽出し返却する。
(defun create-prime-lst (s-lst &optional (p-lst nil))
  (if (and
        (not (null p-lst))
        (< (car (last s-lst)) (* (car (last p-lst)) (car (last p-lst)))))
    (append p-lst s-lst)
    (progn
      (setf p-lst (append p-lst (list (car s-lst))))
      (setf s-lst (delete-multiple-from-search-lst (car (last p-lst)) s-lst))
      (create-prime-lst s-lst p-lst))))
;結果表示関数
(defun print-lst (lst)
  (format t "~a => (" 'lst)
  (labels
    ((rec (lst)
          (if (null lst)
            (format t ")~%")
            (progn
              (format t "~d " (car lst))
              (rec (cdr lst))))))
    (rec lst)))
(print-lst (create-prime-lst (make-search-lst 100)))

まとめ

結構てこずってしまった。少し慣れてきたので油断してしまう。

やっぱり、基本が大事なのを思い知らされた。

  • 機能は小さく関数分割する
  • 関数に複数の仕事をさせない
  • 関数はなるべく副作用がないようにする

これらをちゃんと守れれば、xyzzyとかの*scrach*でS式単位毎に<C-J>しながら作っていける。

lispの旨みってこうゆうことなんだろうな。多分。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


The reCAPTCHA verification period has expired. Please reload the page.

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください