Reputation:
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)
)
Upvotes: 1
Views: 169
Reputation: 13483
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)
Upvotes: 0
Reputation: 20194
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.
Upvotes: 3
Reputation: 97004
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
.
Upvotes: 1