Christmas Cracker Mystery Calculator

25

1

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.

enter image description here

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

Digital Trauma

Posted 2016-12-30T16:55:57.927

Reputation: 64 644

2I'm just waiting for the bubblegum answer. – Mike Bufardeci – 2016-12-30T17:14:30.327

@MikeBufardeci here - A mediocre 184 bytes.

– Digital Trauma – 2016-12-30T23:04:14.913

Are leading spaces acceptable? – Titus – 2018-12-27T15:56:15.390

@Titus Sorry, no, md5s have been given, and additional whitespace would mess those up. – Digital Trauma – 2019-01-04T18:38:03.687

Answers

10

Python 2, 99 96 93 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.

Try it online! or verify the MD5 hash.

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.

Dennis

Posted 2016-12-30T16:55:57.927

Reputation: 196 637

7

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);}

orlp

Posted 2016-12-30T16:55:57.927

Reputation: 37 067

5

Jelly, 27 26 bytes

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

Try it online! or verify the MD5 hash.

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.

Dennis

Posted 2016-12-30T16:55:57.927

Reputation: 196 637

2That G builtin is seriously overpowered for this challenge. I needed about 10 bytes to do the same. – DLosc – 2016-12-31T02:19:31.130

5

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.

Try it online.

orlp

Posted 2016-12-30T16:55:57.927

Reputation: 37 067

5

Pip, 49 48 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)

DLosc

Posted 2016-12-30T16:55:57.927

Reputation: 21 213

4

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
}

Level River St

Posted 2016-12-30T16:55:57.927

Reputation: 22 049

3

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())

Neil

Posted 2016-12-30T16:55:57.927

Reputation: 95 035

2

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

Brad Gilbert b2gills

Posted 2016-12-30T16:55:57.927

Reputation: 12 713

2

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.

Magic Octopus Urn

Posted 2016-12-30T16:55:57.927

Reputation: 19 422

TFW you see your own answer from years ago ¯\(º_o)/¯. – Magic Octopus Urn – 2019-04-29T21:21:44.380

1

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.

Neil

Posted 2016-12-30T16:55:57.927

Reputation: 95 035

1

@DigitalTrauma The best ways to try it really require Wine (http://askubuntu.com/a/54271) or that you download a VM (https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/) (I recommend you to download Windows 7 with IE8, to save space. Or try to get your hands on an Windows XP + IE6 VM that used to be available)

– Ismael Miguel – 2016-12-30T22:30:49.203

1

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())

Arnauld

Posted 2016-12-30T16:55:57.927

Reputation: 111 334

1

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.

Mitchell Spector

Posted 2016-12-30T16:55:57.927

Reputation: 3 392

1

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.

Titus

Posted 2016-12-30T16:55:57.927

Reputation: 13 814

1

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)
                                                                    # add the perforation break
                                                                    +' -'*11
     # print the generated string, then increment the counter
     print..................................................................;i+=1
# execute the following statements 6 times
exec"............................................................................."*6

Triggernometry

Posted 2016-12-30T16:55:57.927

Reputation: 765

Good, except the - - - separator should only appear between cards and not an extra one at the end. – Digital Trauma – 2019-01-04T18:39:47.913

@DigitalTrauma Dang, and I was SO PROUD of getting a smaller bytecount than Dennis, too. Thanks for pointing it out, tho! – Triggernometry – 2019-01-04T19:19:11.573

1

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.

Try it online or verify md5sum.

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)

Kevin Cruijssen

Posted 2016-12-30T16:55:57.927

Reputation: 67 575

0

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.

Naruyoko

Posted 2016-12-30T16:55:57.927

Reputation: 459

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. – Post Rock Garf Hunter – 2019-04-28T21:40:40.960