12
\$\begingroup\$

Shuffling a deck of cards is hard for kids, so they must figure out ways to get a reasonable well shuffled deck as simply as possible.

One way to do this that gives reasonably good results is:

  1. Take the top card out and insert it a random place in the deck
  2. Take the bottom card out and insert it in a random place in the deck
  3. Continue until you believe it's good enough.

Note that you shall never insert a card in the top or bottom spot, it should be placed somewhere in the deck.


Instead of shuffling cards, we'll shuffle alphanumerical characters: 0-9, A-J, a-j, q-z and Q-Z.

Start with the string shown below and shuffle the characters the way it's described above. You can choose if you want to continue shuffling infinitely or shuffle the cards 100 rounds (100 cards from the top and 100 cards from the bottom).

0123456789abcdefghijqrstuvwxyzABCDEFGHIJQRSTUVWXYZ

The challenge is to display the characters being shuffled. Each "shuffle" (take out and insert card) shall take between 0.25 and 0.35 seconds.

The gif below shows an example output:

enter image description here


This is so the shortest code in bytes wins.


"Why don't you have a-t instead of a-j, q-z?" Because this shall illustrate suits of cards, not just characters. And yes, there are 5 suits.


Note: I have decided to stop using the check mark on -challenges. Relevant meta posts here and here.

\$\endgroup\$
8
  • \$\begingroup\$ How are there 5 suits? \$\endgroup\$ Jan 9, 2017 at 8:29
  • 1
    \$\begingroup\$ @TrojanByAccident The five sets are cards (ASCII characters) by suit are 0-9, A-J, a-j, q-z and Q-Z, according to the question. \$\endgroup\$
    – mbomb007
    Jan 9, 2017 at 22:14
  • \$\begingroup\$ and there are 50 cards, not 52. perhaps the kids lost some. \$\endgroup\$
    – Jasen
    Jan 9, 2017 at 22:28
  • \$\begingroup\$ @mbomb007 I was asking how there were 5 suits of cards. Unless I'm missing something, there's only Spades, Clubs, Hearts, and Diamonds. That's 4. \$\endgroup\$ Jan 9, 2017 at 23:25
  • 2
    \$\begingroup\$ @TrojanByAccident This doesn't use cards. It uses ASCII instead of cards. These are the five suits of ASCII. Instead of shuffling cards, we'll shuffle alphanumerical characters \$\endgroup\$
    – mbomb007
    Jan 10, 2017 at 1:27

10 Answers 10

5
\$\begingroup\$

JavaScript (ES6), 192 188 185 bytes

document.write('<pre id=o>')
s='ABCDEFGHIJQRSTUVWXYZ'
a=[0,...123456789+s.toLowerCase()+s]
setInterval('o.innerText=a.join``;a.splice(Math.random(s^=1)*48+1,0,s?a.pop():a.shift())',250)

Edit: Saved 4 bytes thanks to @L.Serné. Saved 3 bytes thanks to @Arnauld.

\$\endgroup\$
2
  • \$\begingroup\$ I think you can save a few bytes if you move e^=1 inside the empty parentheses of the Math.random call. You can also change textContent to innerHTML, since you're not passing any special chars. You can also set e to 0 inside the toLowerCase call. \$\endgroup\$
    – Luke
    Jan 8, 2017 at 16:16
  • \$\begingroup\$ You don't really need e. You could just use s. (Because ('some_string'^1) === 1) \$\endgroup\$
    – Arnauld
    Jan 8, 2017 at 22:05
4
\$\begingroup\$

Perl, 117 bytes

@F=(0..9,a..j,"q"..z,A..J,Q..Z);{print"\r",@F;splice@F,++$|+rand(@F-2),0,++$v%2?shift@F:pop@F;select$,,$,,$,,.3;redo}

To run it:

perl -e '@F=(0..9,a..j,"q"..z,A..J,Q..Z);{print"\r",@F;splice@F,++$|+rand(@F-2),0,++$v%2?shift@F:pop@F;select$,,$,,$,,.3;redo}'

Explanations:
-@F=(0..9,a..j,"q"..z,A..J,Q..Z) creates the initial deck, and stores it in @F.
-{...;redo} executes ... forever.
-splice@F,++$|+rand(@F-2),0,++$v%2?shift@F:pop@F alternatively remove the first/last element from the deck and insert in at a random position (while incrementing $|, so the prints aren't buffered),
- print"\r",@F prints the deck,
- select$,,$,,$,,.3 sleeps for 0.3 seconds (Perl's sleep can't sleep for less than 1 second),

\$\endgroup\$
2
  • \$\begingroup\$ the numeric range is 0..9, not 1..9, and your initial deck is out of order as well :) \$\endgroup\$
    – ardnew
    Jan 9, 2017 at 17:07
  • \$\begingroup\$ @ardnew indeed, thanks. I must have been tired when I wrote this code. It's fixed anyway :) \$\endgroup\$
    – Dada
    Jan 9, 2017 at 18:17
4
\$\begingroup\$

Python 3, 199 196 192 186 bytes

Saved 4 bytes thanks to TuukkaX, and 6 bytes thanks to FlipTack!

import time,random
s="abcdefghijqrstuvwxyz";s="0123456789"+s+s.upper()
f=0
while 1:print(end="\r"+s);time.sleep(.3);s,e=s[1^f:50-f],s[f and-1];i=random.randint(1,49);s=s[:i]+e+s[i:];f^=1

Uses Python 3's print function to suppress newline, shorter than Python 2's sys.stdout.write.

Uses a flip-flop variable to switch between moving the top and the bottom cards.

Ungolfed:

from random import randint
from time import sleep

string = "abcdefghijqrstuvwxyz"
string = "0123456789" + string + string.upper()
flip_flop = 0
while True:
    print("\r"+string,end="")
    sleep(0.3)
    string,char = string[not flip_flop:50-flip_flop], string[flip_flop and -1]
    position = randint(1,49)
    string = string[:position] + char + string[position:]
    f = not f
\$\endgroup\$
3
  • \$\begingroup\$ Would import random,time be shorter? \$\endgroup\$
    – FlipTack
    Jan 9, 2017 at 15:37
  • \$\begingroup\$ @FlipTack Yeah, 6 bytes shorter, thanks! \$\endgroup\$
    – busukxuan
    Jan 9, 2017 at 15:42
  • \$\begingroup\$ @mbomb007 Thanks, done :-) \$\endgroup\$
    – busukxuan
    Jan 9, 2017 at 22:19
4
\$\begingroup\$

MATL, 62 58 56 bytes

2 Bytes saved thanks to @Luis

4Y2'A':'J'tk'Q':'Z'tk&h`48YrQJh&)@o?l&)wb}wO&)]&htD3&XxT

This version will run indefinitely. Try the online demo at MATL Online, an experimental online interpreter that supports dynamic output. This will run for 30 seconds (a hard limit imposed by the online version) if it isn't killed first.

Explanation

4Y2     % Predefined literal for the characters '0'...'9'
'A':'J' % Create an array of the characters 'A'...'J'
tk      % Duplicate and make lowercase
'Q':'Z' % Create an array of the characters 'Q'...'Z'
tk      % Duplicate and make lowercase
&h      % Horizontally concatenate everything
`       % Do...while loop
  48YrQ % Determine a random integer between 2 and 49 
  Jh&)  % Split the string at the selected location
  @o?   % If this is an odd time through the loop
    l&) % Grab the first character
    wb  % Move it to the middle of the stack of three strings
  }     % Else...
    wO&)% Grab the last character and move it to the middle of the stack
  ]     % End of if statment
  &h    % Horizontally concatenate all strings on the stack
  tD    % Duplicate and display the current string
  3&Xx  % Pause for 0.3 seconds and clear the display
  T     % Push a literal TRUE to the stack to make this an infinite loop
        % Implicit end of while loop
\$\endgroup\$
0
3
\$\begingroup\$

C, 290 285 bytes

#include<stdio.h>
#include<time.h>
#define S(s,a,b){int p=rand()%48+1;clock_t c=clock()+300;while(c>clock());int x=d[s];for(int i=s;i a p;)d[i b]=d[i];d[p]=x;printf(d);}
main(){char d[]="0123456789abcdefghijqrstuvwxyzABCDEFGHIJQRSTUVWXYZ\r";srand(time(0));for(;;){S(0,<,++)S(49,>,--)}}

Ungolfed:

#include<stdio.h> // variadic(printf) functions without a valid prototype = UB
#include<time.h>  // required for the implementation-defined clock_t type
// note that <stdlib.h> isnt required for srand()/rand() because they are
//  validly declared implicitly
#define S(s,a,b) // macro function
{
    int p=rand()%48+1;     // get a random position within the array
    clock_t c=clock()+300; // get the time 300 milliseconds from now
    while(c>clock());      // wait for that time
    int x=d[s];            // save the s'th character in a tempvar
    for(int i=s;i a p;)    // shift everything in the array from p
        d[i b]=d[i];       // a determines the comparison: </>
                           // b determines the operation: ++/--
    d[p]=x;                // put the tempvar in its new position
    printf(d);             // print the modified string
} // note: the \r at the end makes it so the next printf overwrites it

main() // main entry point
{      // deck to shuffle below
    char d[]="0123456789abcdefghijqrstuvwxyzABCDEFGHIJQRSTUVWXYZ\r";
    srand(time(0)); // seed the random number generator
    for(;;)         // infinite loop
    {
        S(0,<,++)   // shuffle from the start of the deck
        S(49,>,--)  // shuffle from the end of the deck
    }
}
\$\endgroup\$
2
\$\begingroup\$

Swift, 288 bytes

import Darwin
var o=Array("0123456789abcdefghijqrstuvwxyzABCDEFGHIJQRSTUVWXYZ".characters)
while true{
print(String(o),terminator:"\r")
fflush(__stdoutp);{o.insert(o.removeLast(),at:$0())
o.insert(o.removeFirst(),at:$0()+1)}({Int(arc4random_uniform(UInt32(o.count-1)))})
usleep(300000)
}

Golfing in Swift is always a challenge, as one of its selling points is expressiveness.

\$\endgroup\$
2
\$\begingroup\$

Ruby (138 119 Bytes)

f=0;a=[*0..9,*?a..?j,*?q..?z,*?A..?J,*?Q..?Z];loop{$><<a*''+?\r;a.insert(rand(48),f>0? a.shift : a.pop);f^=1;sleep 0.3}

Not as short as @PaulPrestidge but at least I understand it.. Also great to learn that ruby is like a endless tunnel of awesome!

\$\endgroup\$
1
\$\begingroup\$

Ruby, 111 101 characters

s=[*0..9,*?a..?j,*?q..?z,*?A..?J,*?Q..?Z,?\r]*''
loop{$><<s;s[1+rand(48),0]=s.slice!$.^=-2;sleep 0.3}

Loops infinitely.

\$\endgroup\$
1
\$\begingroup\$

Noodel, noncompeting 41 bytes

"Q…Z"A…J"q…z"a…j"0…9⁵⁺ḷçṛ47⁺1ɱɲOṃḃɲ49ḅṙḍq

Try it:)

How It Works

"Q…Z"A…J"q…z"a…j"0…9⁵⁺                    # Creates the string literal to be shuffled.
                      ḷçṛ47⁺1ɱɲO      ṙḍq # The main "infinite" loop that applies the animation.
                                ṃḃɲ49ḅ    # Sub-loop that acts like an if-statement that only runs every odd iteration of the loop.

"Q…Z                                      # Pushes the string literal "QRSTUVWXYZ".
    "A…J                                  # Pushes the string literal "ABCDEFGHIJ".
        "q…z                              # Pushes the string literal "qrstuvwxyz".
            "a…j                          # Pushes the string literal "abcdefghij".
                "0…9                      # Pushes the string literal "0123456789".
                    ⁵⁺                    # Add the five strings on the stack to make one string.
                      ḷ                   # Unconditionally loop the following code.
                       ç                  # Copy what is on the top of the stack, clear the screen, and then print the copy.
                        ṛ47               # Create a random integer from 0 to 47.
                           ⁺1             # Increment the number to get 1 - 48 such that will not be the top or bottom of the deck.
                             ɱ            # Push the number of times that the unconditional loop has ran.
                              ɲO          # Consume the counter and push on zero if is even and one if is odd.
                                ṃ         # Conditional loop that only passes if the top of the stack is truthy (if the counter is odd).
                                 ḃ        # Throws away the top of the stack.
                                  ɲ49     # Pushes the literal 49 in order to represent the top of the deck.
                                     ḅ    # Ends the conditional loop.
                                      ṙ   # Relocate an element in the string by using the two numbers on the stack (either 0 or 49 to the random number).
                                       ḍq # Delay for a quarter of second. (End of unconditional loop)

<div id="noodel" code='"Q…Z"A…J"q…z"a…j"0…9⁵⁺ḷçṛ47⁺1ɱɲOṃḃɲ49ḅṙḍq' input="" cols="50" rows="2"></div>

<script src="https://tkellehe.github.io/noodel/release/noodel-0.0.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>

\$\endgroup\$
3
  • \$\begingroup\$ Why is this non competing? \$\endgroup\$ Jan 9, 2017 at 15:33
  • \$\begingroup\$ @StewieGriffin I did not finalize the release of the js parser until after the challenge. All functionality existed before that, but I did not know if it was correct for me to allow Noodel to compete. So, I took the safe route:) \$\endgroup\$
    – tkellehe
    Jan 9, 2017 at 15:49
  • \$\begingroup\$ @mbomb007, thank you for fixing that. I did not realize it was placed on top. \$\endgroup\$
    – tkellehe
    Jan 10, 2017 at 14:03
0
\$\begingroup\$

bash, 170 bytes

r(){((r=RANDOM%48+1));echo -n $c^;sleep .3;}
c=0123456789abcdefghijqrstuvwxyzABCDEFGHIJQRSTUVWXYZ
while r
do
c=${c:1:r}${c:0:1}${c:r+1}
r
c=${c:0:r}${c:49}${c:r:-1}
done

here '^' (on the first line) represents ctrl-m: entered on the command-line as ctrl-v enter or in an editor according to how your editor works (assuming your editor works)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.