2011-02-10 13 views
4

すべての素数の怠惰な無限シーケンスを作成しようとすると、クローキングが学習されます。 より効率的なアルゴリズムがあることを知っています。理想的な解決策よりもPO​​C /レッスンとして、次のことをやっています。前の要素に応じてレイジーシーケンス

(next-prime [2 3 5]) ; result: 7 

私の怠惰なシーケンスは、したがって、その後、この関数に自分自身を渡し、結果を取り、にそれを追加する必要があります。

私は素数のシーケンス与えられ、次の素数が何であるかを私に語った、機能を持っています自体。

私の最初の試み:はIllegalArgumentExceptionで

(def lazy-primes 
    (lazy-cat [2 3 5] (find-next-prime lazy-primes))) 

..which結果:からISEQを作成する方法を知ってはいけない:java.lang.Integerの

私の第二の試み:

(def lazy-primes 
    (lazy-cat [2 3 5] [(find-next-prime lazy-primes)])) 

.. 10要素を求められたときに私に[2 3 5 7]が与えられます。

試み3:彼らは動作するはずです(または、少なくとも、前が機能しなかったことを考えると動作するはずです)のような

(def lazy-primes 
    (lazy-cat [2 3 5] 
    (conj lazy-primes (find-next-prime lazy-primes)))) 

(take 10 lazy-primes) ; result: (2 3 5 7 2 3 5 7 2 3) 

これらのすべてが見えます。なぜ私はそれぞれのケースで偽の出力を得ているのですか?

答えて

1

理由:

  1. (見つける-次プライムレイジー素数を)[整数を返しますが、怠惰な猫はシーケンス
  2. を必要とします(発見-次プライム(lazy-cates、lazy-primes)]はベクトルを作成します(したがってseqableです)が、最初にアクセスされたときに一度だけ評価されます。
  3. conjはシーケンスの開始に新しい素数を追加しますシーケンス)...おそらくあなたが望むものではありません!また、おそらく混乱のfind-次プライムそれがどのように実装されるかに依存だし、周りにいくつかの微妙な問題があるかもしれませんあなたは代わりのようなものを使用することをお勧めします.....同様

をシーケンスをチャンク:

(defn seq-fn [builder-fn num ss] 
    (cons 
    (builder-fn (take num ss)) 
    (lazy-seq (seq-fn builder-fn (inc num) ss)))) 

(def lazy-primes 
    (lazy-cat [2 3 5] (seq-fn next-prime 3 lazy-primes))) 

少し複雑な、しかし、基本的に私がやっていることは、それが生成できるように、これまでに作成した素数の数を含んでいるパラメータのセットの上に閉鎖を提供するために、高次のヘルパー関数を使用しています次に、各ステップで段階的にプライムします。

P.S.素数を生成するためのより高速なアルゴリズムがあることは確かです。私は、これが主にClojureでの練習とレイジーシーケンスの使用を目的としていると仮定しています。しかし、たくさんの素数を生成することに本当に関心があるなら、私は見てみることをお勧めします。Sieve of Atkin

0

お探しの組み合わせはconcat + lazy-seq +ローカルfnです。しかし、https://github.com/richhickey/clojure-contrib/blob/78ee9b3e64c5ac6082fb223fc79292175e8e4f0c/src/main/clojure/clojure/contrib/lazy_seqs.clj#L66

つ以上の単語:

はClojureのContribのライブラリでErathostenes'ふるいの実装を見てみましょう。この実装はsophisticated algorithm for the Sieve in a functional language以上を使用しています。

Clojureの別の実装はRosetta codeにあります。しかし、私はそれがClojureでこのalgoの解決のために必要としない原子を使用するので、その1つを好きではありません。あなたの最初の試みがうまくいかない理由

+0

興味深いサイトが、あなたは私に私のコードが何をしているかの説明を与えることができますか? – Kricket

1

あるいは、関数の出力を遅らせて関数に適用する組み込み関数iterateを使うことができます再び

clojure.core/iterate                                       
([f x])                                         
Returns a lazy sequence of x, (f x), (f (f x)) etc. 
f must be free of side-effects 

あなたはそれを動作させるようにするためで、次のプライム機能は、その入力にその結果を連結し、連結したものを返す必要があります。

次に、最初の100 素数のリストを取得するために(100を取る(lister - primes [1]を繰り返す)ことができます。あなたは以下のコードスニペットを持つすべての素数の怠惰なシーケンスを生成することができ、あなたのnext-prime機能付

1

(def primes (map peek (iterate #(conj % (next-prime %)) [2]))) 
関連する問題