Archive for the ‘chop’ Tag

projecteuler7 と 10...または、newLISP の関数 format

 今回の projecteuler は、10001 番目の素数を求めるという問題 72000000 以下の素数の和 を求める 問題 10 の二つ。どちらも素数を探し出すために繰り返し処理を実行するので、まとめました。

(let (i 3 res '(2))
  (while (< (res -1) 2000000)
    (when (= (length (factor i)) 1) (push i res -1))
    (++ i 2))
  (println "The answer of Problem  7 = " (format "%12d" (res 10000)))
  (print "The answer of Problem 10 = ") (apply + (chop res)))

 このスクリプトの動作は、リスト変数 res に予め素数の初期値を 2 入れて置き、3 から二つ置き(奇数だけ)に組込関数 factor を使って、因数分解数が一個のものを素数と判定し、res に追加していきます。最後に見つかった素数 (res -1)2000000 を超えたら while を抜けて、各問題の答えを表示します。
 ++ は組込で、Common Lisp の incf に相当します。ちなみに、++ は整数用で、浮動小数点数には inc を使います。上記スクリプトに inc を使っても動作します。newLISP の方で必要に応じて型変換してくれますから。もちろん、減算用の ––dec もあります。
 printlnprint も組込で、共に引数を評価して表示します(正確にはカレントI/Oデバイスに出力する)。違いは改行出力の有無です。
 また、組込 chop は Common Lisp の butlast に相当します。つまり、リストの最後の要素を取り除いて返します。リストだけでなく、文字列にも使えるのが newLISP 流です(笑)。これを使って、2000000 超の素数を取り除いています。
 残る副題にもなっている組込 format は文字列を整形する書式関数ですが、Common Lisp の書式を大きく異なります。と言うより、C 言語の printf の書式とほぼ同等です。Lisper には馴染めなくとも、私のような C 言語習得者にとっては救いの神です(笑)。注意が必要なのは、newLISP の整数は 64 ビットですが、通常の整数書式は 32 ビット対応である点 と 32 ビット以上の整数を整形するのに必要な 64 ビット用の書式が OS によって異なる点くらいでしょうか。詳しくは、マニュアルの format の項を見てください。
 さて、気になる答えは、

> [cmd]
(let (i 3 res '(2))
  (while (< (res -1) 2000000)
    (when (= (length (factor i)) 1) (push i res -1))
    (++ i 2))
  (println "The answer of Problem  7 = " (format "%12d" (res 10000)))
  (print "The answer of Problem 10 = ") (apply + (chop res)))
[/cmd]
The answer of Problem  7 =       104743
The answer of Problem 10 = 142913828922
> 

 こんな感じ。

 以上、如何でしょうか?

追記:2013/6/9 スクリプト修正、検討途中のスクリプトを入れてしまった、、、(汗)

projecteuler2...または、newLISP リストのインデックス操作

 projecteuler も2回目。
 問題2は 1, 2 から始まるフィボナッチ(Fibonacci)数列で四百万を超えない偶数値の和。
 まずは、フィボナッチ数列を求めます。

> [cmd]
(let (fibo '(1 2))
  (while (< (fibo -1) 4000000)
    (push (apply + (-2 2 fibo)) fibo -1))
 (chop fibo))
[/cmd]
(1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 
 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578)
> 

 こんな感じ。ここで、関数chop は組込関数で Common Lisp の butlast に相当します。つまり、リストの最後の要素を削除するもの。また Common Lisp では自分で定義する必要のある while も newLISP では組込です。動作は、、、説明いりませんね(笑)。
 今回のもう一つの主題、リストのインデックス操作。そのための関数(nthslice)もありますが、インデックス数を使って直接操作するのが newLISP 流(笑)。暗黙のインデックス機能(Implicit indexing)です。
 上記の中では、リストから最後の要素を取り出す

(fibo -1)

 や最後から二つの要素の部分リストを作る

(-2 2 fibo)

 がそれに相当します。
 そして、本題。求めたフィボナッチ数列から偶数を取り出すのに前回の select-numbers を使ってもよいのですが、述語(条件式)が一つですから、ここは newLISP組込filter を使います。この関数は、リストから述語(条件式)で真(true)になるものだけ返します。

> (filter even? (sequence 1 10))
(2 4 6 8 10)
> 

 もちろん、この関数とは逆に、述語(条件式)で真(true)になるものだけリストから削除する関数clean もあります。
 さてと、問題2の解答は、

> [cmd]
(let (fibo '(1 2))
  (while (< (fibo -1) 4000000)
    (push (apply + (-2 2 fibo)) fibo -1))
  (apply + (filter even? (chop fibo))))
[/cmd]
4613732
> 

 となります。
 あっ、述語(条件式)even? も組込です。説明、、、いりませんね(笑)。

 以上、如何でしょうか?