# Christmas Cracker Mystery Calculator

The presents have been opened. The mince-pies have been eaten. The Star Wars have been watched. The Christmas Season is beginning to wind down. By now you may well have pulled a few Christmas Crackers. If you're lucky, instead of the usual useless plastic toys, you may have won a Mystery Calculator with which you can amaze your friends and relatives.

This trick consists of 6 cards each with a 4x8 grid of numbers printed on it. Each card contains a different subset of the integers [1,63]. The magician will ask you to pick a number from one card and keep that number secret. The magician will then ask which cards have that number. With that knowledge, the magician will magically be able to determine and disclose the original number guessed.

Output the full set of 6 Mystery Calculator cards exactly as follows:

 1  3  5  7  9 11 13 15
17 19 21 23 25 27 29 31
33 35 37 39 41 43 45 47
49 51 53 55 57 59 61 63
- - - - - - - - - - -
2  3  6  7 10 11 14 15
18 19 22 23 26 27 30 31
34 35 38 39 42 43 46 47
50 51 54 55 58 59 62 63
- - - - - - - - - - -
4  5  6  7 12 13 14 15
20 21 22 23 28 29 30 31
36 37 38 39 44 45 46 47
52 53 54 55 60 61 62 63
- - - - - - - - - - -
8  9 10 11 12 13 14 15
24 25 26 27 28 29 30 31
40 41 42 43 44 45 46 47
56 57 58 59 60 61 62 63
- - - - - - - - - - -
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63
- - - - - - - - - - -
32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63


Output may or may not contain one final trailing newline. There must be no trailing whitespace. Each card is separated by 11 - perforations.

• md5sum with final newline: 7aa2d9339b810ec62a2b90c5e11d6f4a
• md5sum without final newline: e9abe4e32dca3e8fbfdaa4886fc5efd2

For those of you of more of a windows orientation, I will also allow CRLF style line endings. In that case, the md5s are:

• md5sum with final newline: e4f16ff9752eee2cedb5f97c7b5aec6d
• md5sum without final newline: 78c560eed3b83513e3080117ab5dc5fa
• I'm just waiting for the bubblegum answer. – Mike Bufardeci Dec 30 '16 at 17:14
• @MikeBufardeci here - A mediocre 184 bytes. – Digital Trauma Dec 30 '16 at 23:04
• Are leading spaces acceptable? – Titus Dec 27 '18 at 15:56
• @Titus Sorry, no, md5s have been given, and additional whitespace would mess those up. – Digital Trauma Jan 4 '19 at 18:38

# Python 2, 999693 91 bytes

k=1
while 1:print('%2d '*7+'%2d\n')*4%tuple(n for n in range(64)if k&n),11/(k<32)*' -';k*=2


Exits with an error, which is allowed by default.

### How it works

After initializing k as 1, we enter an infinite loop that executes the following code.

print('%2d '*7+'%2d\n')*4%tuple(n for n in range(64)if k&n),11/(k<32)*' -';k*=2


tuple(n for n in range(64)if k&n) creates a tuple of all non-negative integers below 64 that have there jth bit set, where j is the iteration count of the loop, i.e., 2j = k.

('%2d '*7+'%2d\n')*4 first creates the format string '%2d %2d %2d %2d %2d %2d %2d \n', then repeats it four times. This is a template for each card, which pads each integer in the tuple to two characters (prepending spaces), separates each group of 8 integers by spaces, and the groups themselves by linefeeds.

Now, Python 2's print statement is a curious beast. It takes several expressions, separated by commata, and prints them one by one. It evaluates the first expression, prints it, evaluates the next expressions, prints it, etc. until no more expressions are left. Unless the last expression is followed by a comma, it appends a linefeed to it. Also, it prepends a space to all expressions, unless they are printed at the beginning of a line.

In each iteration, we first print the result of applying the format string to the tuple. We're at the beginning of a line, so no space is prepended.

Then, we (attempt to) print the result of 11/(k<32)*' -'. If k < 32, this expressions evaluates to ' - - - - - - - - - - -'. Again, we're at the beginning of a line, so no space is prepended. There is no comma after this expression, so print appends a linefeed. However, in the sixth iteration, k = 25 = 32, so trying to evaluate 11/(k<32)*' -' raises an uncaught ZeroDivisionError. This breaks out of the loop and ends the program immediately.

# C (gcc), 105 bytes

o;main(i){for(;i<384;i++%64||puts(" - - - - - - - - - - -"))i&1<<i/64&&printf("%2d%c",i%64,++o%8?32:10);}


# Python 2, 132 bytes

for c in range(6):s=" ".join("%2d"%n for n in range(64)if n&1<<c);print"\n".join([s[24*i:24*i+23]for i in range(4)]+[" -"*11]*(c<5))


Splitting sequences is annoying in Python.

# Jelly, 27 26 bytes

Ts8GW
⁾ -ẋ11W
63RBUz0Ñ€j¢Y


### How it works

63RBUz0Ñ€j¢Y  Main link. No arguments.

63R           Range 63; yield [1, ..., 63].
B          Binary; convert each integer to base 2.
U         Upend; reverse the binary representations.
z0       Zip with filler 0; transpose rows and columns, filling gaps in
the (non-rectangular) matrix with zeroes.
Ñ€     Map the first helper link over the new rows.
¢   Yield the return value of the second helper link.
j    Join the left result, separating by the right result.
Y  Join the results, separating by line feeds.

Ts8G          First helper link. Argument: A (array of 1's and 0's)
T             Truth; get all indices of 1's.
s8           Split the indices into chunks of length 8.
G          Grid; convert the 2D array into a string, separating row items
by spaces, rows by linefeeds, and left-padding each integer
with spaces to equal lengths.
W         Wrap the generated string in an array.

⁾ -ẋ11W       Second helper link. No arguments.

⁾ -           Yield " -".
ẋ11        Repeat the string 11 times.
W       Wrap the generated string in an array.

• That G builtin is seriously overpowered for this challenge. I needed about 10 bytes to do the same. – DLosc Dec 31 '16 at 2:19

# Pip, 4948 44 bytes

43 bytes of code, +1 for -S flag.

Fi,6{IiP" -"X11P(sX2-#_._M2**iBA_FI,64)<>8}


Try it online!

### Explanation

                                             s is space (preinitialized)
Fi,6{                                     }  For i in range(6):
Ii                                      If i is nonzero (i.e. all except 1st loop):
P" -"X11                              Print hyphens
FI,64       Range(64), filtered on this function:
2**iBA_              2**i bitwise AND with argument (is nonzero)
M                   To each remaining number, map this function:
2-#_                        2-len(argument)
sX                            ^ that many spaces
._                      prepended to argument
(                     )<>8   Group list into length-8 sublists
P                             Print (-S flag joins on space then newline)


# Ruby, 90 bytes

1.upto(383){|i|print (j=i%64)<1?' -'*11+$/:"%2d%s"%[j,j+1&15>>i/256>0?' ':$/]*(j>>i/64&1)}


Ungolfed

Fairly straightforward. The only thing that may require additional explanation is when to follow a number with a newline rather than a space. This happens when j+1%16==0 in the first four cards and j+1%8==0 in the last two. Hence the expression 15>>i/64/4 or equivalently 15>>i/256is ANDed with j to determine whether space or newline is required.

1.upto(383){|i|                              #Count starting at 1 instead of 0 to supress - -  before 1st card
print (j=i%64)<1?                          #j=number to consider for card. If 0,
' -'*11+$/: #print - - -... else print "%2d%s"%[j,j+1&15>>i/256>0?' ':$/]*     #j formatted to 2 spaces followed by a space (or if j+1 divisible by 16 or 8 depending on card, a newline.)
(j>>i/64&1)                             #only print appropriate numbers for this card, i.e. when this expression evaluates to 1
}


## JavaScript (ES6), 150 bytes

f=
_=>[1,2,4,8,16,32].map(m=>[...Array(64)].map((_,i)=> ${i}.slice(-2)).filter(i=>i&m).join .replace(/(.{23}) /g,$1
)).join(
${ -.repeat(11)} ) ;document.write(<pre>+f()) # Perl 6, 194 116 86 bytes put join "\n{' -'x 11}\n",map {join "\n",.[^32].rotor(8)».fmt('%2s')},(1,3...63),(2,{|($_ X+1,4)}...*),(4,{|($_ X+1,2,3,8)}...*),(8,{|((1...7,16)X+$_)}...*),(16,{|((1...15,32)X+$_)}...*),32..63  Try it for 1..383 {print !($/=$_%64)??"{' -'x 11}\n"!!$/+>($_/64)%2??$/.fmt('%2d')~(($/+1)+&(15+>($_/256))??' '!!"\n")!!''}


Try it

for 1..383 {$_%64||put ' -'x 11;$_+&(1+<($_/64))&&printf "%2d%c",$_%64,++$/%8??32!!10}  Try it (check the Debug sections for the MD5 results) The last two were inspired/transcribed from the Ruby and C implementations # 05AB1E, 71 bytes 63L©DÉÏ®À2ô®ÉÏ®ÀÀÀ4ô®ÉÏ®Á8ô®ÈÏ63®Á16ô®ÈÏ63D32sŸ)˜32ôvy8ôvy.B}„ -11×})¨»  Try it online! This approach, don't try it. Will likely delete this out of shame to be honest. Matrix manipulation is not my strong suit so I tried to brute force generate all 6 sequences and then pump them together sloppily. • TFW you see your own answer from years ago ¯＼(º_o)/¯. – Magic Octopus Urn Apr 29 '19 at 21:21 ## Batch, 249 bytes @echo off set s= for %%i in (1 2 4 8 16 32)do for /l %%j in (0,1,63)do call:c %%i %%j exit/b :c if %2==0 if %1 gtr 1 echo - - - - - - - - - - - set/an=%1^&%2 if %n%==0 exit/b set n= %2 set s=%s%%n:~-3% if not "%s:~23%"=="" echo%s%&set s=  Outputs a trailing CRLF. ## JavaScript (ES6), 103 102 bytes f=(k=1,n=z=0)=>n>>6?k>>5?'':' -'.repeat(11)+ +f(k*2):(n&k?(n>9?'':' ')+n+ [++z&7&&1]:'')+f(k,++n)  MD5: 7AA2D9339B810EC62A2B90C5E11D6F4A ### Test f=(k=1,n=z=0)=>n>>6?k>>5?'':' -'.repeat(11)+ +f(k*2):(n&k?(n>9?'':' ')+n+ [++z&7&&1]:'')+f(k,++n) console.log(f()) # bash / Unix utilities, 125 124 bytes b='- - - - ';for ((x=1;x<33;x*=2));{ for n in {0..63};{ ((x&n))&&printf \ %2d$n;};echo $b$b$b;}|fold -w24|sed -e\$d -es/.//


Edit: Removed an unnecessary ^ from the regex at the end; the regex will always match at the beginning of the line anyway.

# PHP, 102 bytes

for(;$c<6;$n%32||$c+=print str_pad(" ",25," -"),$n%2**$c||$b+=1<<$c)printf(" "[$n++%8]."%3d",++$b%64);  prints a leading but no trailing newline, and one leading space in each line. Run with -nr or try it online. For PHP<5.6, replace 2**$c with (1<<$c). PHP 5.5 could use &~1<<$c?: instead of %2**$c||. For PHP<5.5, replace "\n"[$n++%8] with ($n++%8?"":"\n"). Dashes are one character off due to the leading space; append a space to the first str_pad parameter (insert a space before the second code line) to fix. Removing the leading space instead requires some fiddling and three additional bytes: printf("%c%2d",$n++%8?32:10,++$b%64); and 23 instead of 25. Turning the leading newline into a trailing one would cost another three bytes: for(;$c<6;$n%32||$c+=print str_pad("",22," -")."
",$n%2**$c||$b+=1<<$c)printf("%2d%c",++$b%64,++$n%8?32:10);


# PHP, 109 bytes

for($c=1;~$c&64;$n%32||$c<<=print str_pad("",22," -")."
",$n%$c||$b+=$c)printf("%2d%c",++$b%64,++$n%8?32:10);


matches all specs and works with all PHP versions.

# Python 2, 89 bytes

i=0;exec"print('%2d '*7+'%2d\\n')*4%tuple(j for j in range(64)if j&2**i)+' -'*11;i+=1;"*6


Try it online!

Explanation:

# initialize outer counter variable
i=0
# generate a formatting string for a single row of numbers
# %2d will left pad an integer with spaces, up to string length 2
# the \\n is so that exec will interpret it as a character rather than a literal line break
'%2d '*7+'%2d\\n'
# create a formatting string of 4 lines of 8 numbers
(.................)*4
# format the string with a generated tuple of numbers that have a 1 in the current bit slot
# (or more literally, bitwise j AND 2^i is not zero)
%tuple(j for j in range(64)if j&2**i)
+' -'*11
# print the generated string, then increment the counter
print..................................................................;i+=1
# execute the following statements 6 times
exec"............................................................................."*6

• Good, except the  - - -  separator should only appear between cards and not an extra one at the end. – Digital Trauma Jan 4 '19 at 18:39
• @DigitalTrauma Dang, and I was SO PROUD of getting a smaller bytecount than Dennis, too. Thanks for pointing it out, tho! – Triggernometry Jan 4 '19 at 19:19

# 05AB1E, 29 bytes

63L2вíƶ0ζε0K8ô§2j»}„ -11×¶.øý


Port from @Emigna's 05AB1E answer here, after which I added additional code to print it according to the requirements in this challenge.

Explanation:

63L          # Create a list in the range [1,63]
2в        # Convert each number to binary as lists of 0s and 1s
í       # Reverse each binary list
ƶ      # Multiply each binary digit by its 1-based index [1,length] (so [1,63])
0ζ    # Zip/transpose; swapping rows/columns, with "0" as filler
ε            # Map each inner list to:
0K          #  Remove all 0s
8ô        #  Split it into (four) lists of size 8
§       #  Cast each integer to string (bug, shouldn't be necessary..)
2j     #  And pad leading spaces to make each string size 2
»    #  Join the inner lists by spaces, and then all strings by newlines
}„ -         # After the map: push string " -"
11×      # Repeated 11 times to " - - - - - - - - - - -"
¶.ø   # Surround it with newlines: "\n - - - - - - - - - - -\n"
ý  # And join the mapped strings with this delimiter-string
# (after which the result is output implicitly)


# JavaScript, 234 bytes.

for(a=[[],[],[],[],[],[]],i=1;i<64;i++)for(j=0;j<6;j++)i&2**j?a[j].push(i<10?" "+i:i):0;for(j=0;j<6;j++){for(s=[],i=0;i<4;)s.push(a[j].slice(i*8,++i*8).join(" "));b=s.join(n="\n");a[j]=b.substr(0,b.length)};a.join(n+" -".repeat(11)+n)


I will write explanation later.

If console.log is required, the byte count would be 247 bytes.

• Welcome to the site! Are you putting your output in an array? I don't know Javascript but that would require you to log since you can not output via a variable. – Wheat Wizard Apr 28 '19 at 21:40