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
むらむーむらむー

コードの全体像

https://github.com/eno314/clojure-practice/pull/6

提出コード

(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にクローズされました