Closed7
paizaでClojureの勉強 - 【シミュレーション 2】perfuct shuffle (paizaランク B 相当)
トランプの初期値の生成
(defn initail-cards-of-suit [suit]
(vec (map #(str suit "_" %) (range 1 14))))
(defn initail-cards []
(flatten (vec (map #(initail-cards-of-suit %) ["S" "H" "D" "C"]))))
テストコード
(deftest initial-cards-test
(is (= (initail-cards)
["S_1" "S_2" "S_3" "S_4" "S_5" "S_6" "S_7" "S_8" "S_9" "S_10" "S_11" "S_12" "S_13"
"H_1" "H_2" "H_3" "H_4" "H_5" "H_6" "H_7" "H_8" "H_9" "H_10" "H_11" "H_12" "H_13"
"D_1" "D_2" "D_3" "D_4" "D_5" "D_6" "D_7" "D_8" "D_9" "D_10" "D_11" "D_12" "D_13"
"C_1" "C_2" "C_3" "C_4" "C_5" "C_6" "C_7" "C_8" "C_9" "C_10" "C_11" "C_12" "C_13"])))
トランプをシャフルする
(defn shuffle-cards [cards]
(let [half (quot (count cards) 2)
first-half (take half cards)
second-half (drop half cards)]
(vec (interleave first-half second-half))))
テストコード
(deftest shuffle-cards-test
(is (= (shuffle-cards (initail-cards))
["S_1" "D_1" "S_2" "D_2" "S_3" "D_3" "S_4" "D_4" "S_5" "D_5" "S_6" "D_6" "S_7"
"D_7" "S_8" "D_8" "S_9" "D_9" "S_10" "D_10" "S_11" "D_11" "S_12" "D_12" "S_13" "D_13"
"H_1" "C_1" "H_2" "C_2" "H_3" "C_3" "H_4" "C_4" "H_5" "C_5" "H_6" "C_6" "H_7"
"C_7" "H_8" "C_8" "H_9" "C_9" "H_10" "C_10" "H_11" "C_11" "H_12" "C_12" "H_13" "C_13"])))
Clojureは結構便利な関数が多くあるなあ
quot
2つの引数の商を整数で返す。割り算の結果が整数である場合に使用。
(quot 10 3) ; => 3
(quot 11 3) ; => 3
(quot -10 3) ; => -3
(quot -11 3) ; => -3
take
シーケンスの先頭から指定された数の要素を取得して、新しいシーケンスを作成
(take 3 [1 2 3 4 5]) ; => (1 2 3)
(take 0 [1 2 3 4 5]) ; => ()
(take 10 [1 2 3 4 5]) ; => (1 2 3 4 5)
drop
シーケンスの先頭から指定された数の要素を除いた残りの要素を取得して、新しいシーケンスを作成
(drop 3 [1 2 3 4 5]) ; => (4 5)
(drop 0 [1 2 3 4 5]) ; => (1 2 3 4 5)
(drop 10 [1 2 3 4 5]) ; => ()
interleave
複数のシーケンスを交互に並べ替えて、新しいシーケンスを作成
要素数が異なる場合は、要素数が少ない方に合わせて処理
(interleave [1 2 3] [4 5 6]) ; => (1 4 2 5 3 6)
(interleave [1 2 3] [4 5 ]) ; => (1 4 2 5)
指定した回数、トランプをシャフルする
(defn shuffle-cards-repeatedly [cards n]
(nth (iterate shuffle-cards cards) n))
テストコード
(deftest shuffle-cards-repeatedly-test
(is (= (shuffle-cards-repeatedly (initail-cards) 1)
["S_1" "D_1" "S_2" "D_2" "S_3" "D_3" "S_4" "D_4" "S_5" "D_5" "S_6" "D_6" "S_7"
"D_7" "S_8" "D_8" "S_9" "D_9" "S_10" "D_10" "S_11" "D_11" "S_12" "D_12" "S_13" "D_13"
"H_1" "C_1" "H_2" "C_2" "H_3" "C_3" "H_4" "C_4" "H_5" "C_5" "H_6" "C_6" "H_7"
"C_7" "H_8" "C_8" "H_9" "C_9" "H_10" "C_10" "H_11" "C_11" "H_12" "C_12" "H_13" "C_13"]))
(is (= (shuffle-cards-repeatedly (initail-cards) 3)
["S_1" "D_7" "H_1" "C_7" "D_1" "S_8" "C_1" "H_8" "S_2" "D_8" "H_2" "C_8" "D_2"
"S_9" "C_2" "H_9" "S_3" "D_9" "H_3" "C_9" "D_3" "S_10" "C_3" "H_10" "S_4" "D_10"
"H_4" "C_10" "D_4" "S_11" "C_4" "H_11" "S_5" "D_11" "H_5" "C_11" "D_5" "S_12" "C_5"
"H_12" "S_6" "D_12" "H_6" "C_12" "D_6" "S_13" "C_6" "H_13" "S_7" "D_13" "H_7" "C_13"])))
nth
シーケンスの指定された位置にある要素を取得
シーケンスは、ベクター、リスト、マップ、文字列など、インデックスでアクセスできるものであれば何でも使用可能
(nth [1 2 3 4 5] 2) ; => 3
(nth "hello" 1) ; => \e
(nth {:a 1 :b 2 :c 3} :b) ; => 2
iterate
指定された関数を繰り返し適用して、無限のシーケンスを生成
最初の要素は、指定された引数であり、2番目以降の要素は、前の要素に対して指定された関数を適用した結果。
(take 5 (iterate inc 0)) ; => (0 1 2 3 4)
(nth 5 (iterate #(* % 2) 1)) ; => 32
コードの全体像
提出コード
(defn read-int-value-line []
(Integer/parseInt (read-line)))
(defn initail-cards-of-suit [suit]
(vec (map #(str suit "_" %) (range 1 14))))
(defn initail-cards []
(flatten (vec (map #(initail-cards-of-suit %) ["S" "H" "D" "C"]))))
(defn shuffle-cards [cards]
(let [half (quot (count cards) 2)
first-half (take half cards)
second-half (drop half cards)]
(vec (interleave first-half second-half))))
(defn shuffle-cards-repeatedly [cards n]
(nth (iterate shuffle-cards cards) n))
(defn main []
(let [n (read-int-value-line)
cards (initail-cards)
shuffled-cards (shuffle-cards-repeatedly cards n)]
(doseq [card shuffled-cards]
(println card))))
(main)
このスクラップは2023/07/07にクローズされました