Frage

How does one write a function to split a list and then merge it back together such that the resulting list represents the shuffle of a deck?

The list (1 2 3 4 5 6 7 8 9 10) should end up as (1 6 2 7 3 8 4 9 5 10)

Is there a way to use split-at or reduce or some other function to achieve this?

So far I'm here:

(defn shuffle [cards] 
  (split-at (/ (count cards) 2) cards)
)
War es hilfreich?

Lösung

(apply interleave (split-at 5 (range 1 11)))

(1 6 2 7 3 8 4 9 5 10)

Andere Tipps

Clojure has an excellent selection of sequence functions.

user> (range 1 11)
(1 2 3 4 5 6 7 8 9 10)
user> (apply mapcat list (split-at 5 (range 1 11)))
(1 6 2 7 3 8 4 9 5 10)

You can get an overview at the clojure cheatsheet, it's a little out of date but mostly still relevant, and gives a good overview of the Clojure basics.

Split like you already have, then zip the two halves together and flatten:

(defn shuffle [cards]
  (->> cards
    (split-at (/ (count cards) 2))
    (apply map list)
    (flatten)))

(shuffle '(1 2 3 4 5 6 7 8 9 10)) ;=> (1 6 2 7 3 8 4 9 5 10)

Of course if you want a “truly” random shuffle, use clojure.core/shuffle.

A general solution is

(defn riffle [s]
  (let [v (vec s), c (quot (count v) 2)]
    (interleave (subvec v 0 c) (subvec v c))))

In this case

(riffle '(1 2 3 4 5 6 7 8 9 10))
; (1 6 2 7 3 8 4 9 5 10)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top