2

これが私が実行しようとしている関数です...

(defn mongean [cards times]
  (let [_cards (transient cards)]
    (loop [i 0 c (get cards i) _count (count cards) _current (/ _count 2)]
      (assoc! _cards _current c)
      (if ((rem i 2) = 0)
        (def _newcur (- _current (inc i)))
        (def _newcur (+ _current (inc i))))
      (if (<= i _count)
        (recur (inc i) (get cards i) _count _newcur )))
    (persistent! _cards)))

その結果、この例外が発生します...

Exception in thread "main" java.lang.ClassCastException: clojure.lang.PersistentHashSet$TransientHashSet cannot be cast to clojure.lang.ITransientAssociative

clojureに慣れていないので、上記のアプローチに対する建設的な批判もありがたいです。目標は、リストを取得し、並べ替えられたリストを返すことです。

4

2 に答える 2

8

モンゲアンシャッフルを実装しようとしていると思います。あなたのアプローチは非常に重要であり、より機能的なアプローチを使用するようにしてください。

replaceカードの最終的な順序を (ウィキペディアの式に従って) 計算し、組み込み関数を使用してマッピングを行う場合、これは可能な実装です。

 (defn mongean [cards]
   (let [num-cards (count cards)
         final-order (concat (reverse (range 1 num-cards 2)) (range 0 num-cards 2))]
      (replace cards final-order)))

  user> (mongean [1 2 3 4 5 6 7 8])
  (8 6 4 2 1 3 5 7)
于 2012-11-24T09:57:57.250 に答える
2

その関数をどのように呼びますか? セットを渡しているように見えるため、一時的なバージョンもセットになり、assoc連想データ構造とベクトルで動作するため、どの関数でも使用できません。

user=> (assoc #{} :a 1)
ClassCastException clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Associative  clojure.lang.RT.assoc (RT.java:691)

user=> (assoc! (transient #{}) :a 1)
ClassCastException clojure.lang.PersistentHashSet$TransientHashSet cannot be cast to clojure.lang.ITransientAssociative  clojure.core/assoc! (core.clj:2959)

; the following works as it uses maps and vectors
user=> (assoc {} :a 1)
{:a 1}
user=> (assoc! (transient {}) :a 1)
#<TransientArrayMap clojure.lang.PersistentArrayMap$TransientArrayMap@65cd1dff>
user=> (assoc [] 0 :a)
[:a]

それでは、コード自体について説明してみましょう。コードをたどって、達成したいことについてのヒントがなければ、実際の目標を理解しようとするのは少し難しいですが、一般的なコメントとしては:

  • timesまったく使用しない入力パラメーターがあります

  • 一時的な突然変異の結果を使用することになっていますが、一時的な突然変異がその場で突然変異するとは想定していません

  • 可能であればトランジェントを避けてください。これらはパフォーマンスの最適化のみを目的としています

  • 実際に返され、結果の位置として使用したいように見えるため、バインディング_current (/ _count 2)はおそらくあなたが望むものではありません(/ 5 2)5/2

  • のような定数はバインディング_countの一部である必要はありませんloop。外側を使用して、let反復ごとにそれらを渡す必要がないようにすることができます

  • 関数内のものに名前を付けるlet代わりに使用するdef

  • (if ((rem 1 2) = 0))あなたが望むものではないことは間違いありません

ここで、シャッフル アルゴリズムはさておき、シーケンスを再配置する必要がある場合は、新しい位置のシーケンスを作成するだけmapで、元のカードとペアを作成し[position card]、最後reduceに元のシーケンスを使用して新しい位置にカードを配置することでそれらを作成できます。シードとして:

(defn generate [coll] ; counts down from (count coll) to 0, change to
                      ; implement your shuffling algorithm
  (range (dec (count coll)) -1 -1))

(defn mongean [cards times]
  (let [positions (generate cards) ; get the new positions
        assemble (fn [dest [pos card]] ; assoc the card at the wanted position
                   (assoc dest pos card))]
    (reduce assemble cards (map vector positions cards))))

単にシャッフルしたい場合:

(defn mongean [cards times] (shuffle cards))
于 2012-11-24T10:17:54.013 に答える