Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>My idea is to have a queue of cards to be played. The queue is shuffled and then played one at a time until emptied. As each card is being played, if the card was played less than m turns ago add it to the end of the queue and pick the next card. Once the queue is emptied it can be filled again and reshuffled. An array can be used to keep track of what turn a card was last played at. This runs O(1) per song on average.</p> <p>Here's my solution in F#.</p> <pre><code>let deal (deck : _[]) m = let played = Array.create (deck.Length) (-m) let rec subDeal (cards : Queue&lt;_&gt;) i = seq { if cards.Count = 0 then yield! subDeal (shuffledQueue deck) i else let card = cards.Dequeue() if i - played.[card] &gt; m then played.[card] &lt;- i yield card else cards.Enqueue card yield! subDeal cards (i + 1) } subDeal (shuffledQueue deck) 1 </code></pre> <p>Some test data for a deal of 0 .. 7 with m = 4.</p> <pre><code>[|3; 1; 4; 0; 2; 6; 5; 4; 0; 2; 3; 6; 1; 5; 0; 1; 2; 6; 4; 3; 5; 2; 0; 6; 3; 4; 5; 1; 6; 0; 3; 2; 5; 4; 1; 3; 5; 2; 0; 6; 1; 4; 2; 5; 3; 4; 0; 1; 6; 5; 2; 4; 3; 0; 6; 1; 3; 5; 6; 2; 4; 1; 0; 5; 2; 6; 3; 1; 4; 0; 2; 6; 1; 4; 0; 5; 3; 2; 1; 0; 5; 6; 4; 3; 2; 1; 3; 0; 5; 6; 4; 3; 1; 2; 0; 5; 6; 4; 3; 0; ...|] // card number and the number of occurrences of said card [|(3, 286); (6, 286); (5, 285); (0, 286); (1, 285); (4, 286); (2, 286)|] // longest time before each card is repeated [|11; 11; 11; 11; 12; 11; 11|] </code></pre> <p>Full test program.</p> <pre><code>open System open System.Collections.Generic let rnd = new Random() let shuffle cards = let swap (a: _[]) x y = let tmp = a.[x] a.[x] &lt;- a.[y] a.[y] &lt;- tmp Array.iteri (fun i _ -&gt; swap cards i (rnd.Next(i, Array.length cards))) cards cards let shuffledQueue cards = let queue = new Queue&lt;_&gt;() cards |&gt; shuffle |&gt; Array.iter (fun x -&gt; queue.Enqueue x) queue let deal (deck : _[]) m = let played = Array.create (deck.Length) (-m) let rec subDeal (cards : Queue&lt;_&gt;) i = seq { if cards.Count = 0 then yield! subDeal (shuffledQueue deck) i else let card = cards.Dequeue() if i - played.[card] &gt; m then played.[card] &lt;- i yield card else cards.Enqueue card yield! subDeal cards (i + 1) } subDeal (shuffledQueue deck) 1 let size = 7 let deck = Array.init size (fun i -&gt; i) let cards = deal deck 4 let getMaxWait seq value = Seq.fold (fun (last, count) test -&gt; if test = value then (0, count) else (last + 1, max (last+1) count) ) (0, 0) seq |&gt; snd let test = cards |&gt; Seq.take 2000 test |&gt; Seq.take 200 |&gt; Seq.toArray |&gt; printfn "%A" test |&gt; Seq.countBy (fun x -&gt; x) |&gt; Seq.toArray |&gt; printfn "%A" deck |&gt; Seq.map (fun x -&gt; getMaxWait test x) |&gt; Seq.toArray |&gt; printfn "%A" Console.ReadLine() |&gt; ignore </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload