Who's magic?

ferreira on 2006-11-14T13:47:17

My kid asked me to think of a number between 1 and 60 and to point out which of five cards the number showed at. And then he "divined" my number. I thought for a moment and then I proposed another guessing game for him: tell me your number between 1 and 60 and then I "divined" the cards the number should show off. My guesses proved to be flawless to the amusement of him and his sister.

The really good part was when I explained (very mildly) how the cards were built by representing the numbers in binary and assigning each card a position and the numbers which had a bit 1 in that position. I managed to do it without fuss and without letting them realize I was actually lecturing on something.

They enjoyed the decomposition algorithm I taught them - decomposing 28 to 16 + 8 + 4 or 13 to 8 + 4 + 1. All very simple with ordinary mathematics a young kid can handle easily. All of a sudden, the "magical" trick turned out to be a simple mathematic problem at their reach.

The real trick was building the cards - not really a trick after the rationale was found, but boring and error-prone to do by hand. So I wrote this:

#!/usr/bin/perl

use strict;
use warnings;

my %cards = (
    1 => [],
    2 => [],
    4 => [],
    8 => [],
    16 => []
);
my @keys = sort { $a <=> $b } keys %cards;

sub add_number {
    my $n = shift;
    for my $k (@keys) {
         last if $k>$n;

         push @{$cards{$k}}, $n if $n & $k;
    }
}

sub show {
    for my $k (@keys) {
         my @numbers = @{$cards{$k}};
         last unless @numbers; # don't show empty cards

         printf "%3.d:". (" %3.d" x @numbers) . "(%d)\n", $k, @numbers, scalar @numbers;
    }
    print "\n";
}

for my $i (1..63) {
    add_number($i);
}

    show();

That was instructive after all.