#!/usr/bin/perl
#require 5.008;
our $VERSION = "0.00"; #Time-stamp: <2011-11-17T04:46:27Z>

use strict;
use warnings;
use utf8; # Japanese

use Encode;

# EPSON Endeavor NP15 (Atom D525 1.8GHz) で 133分 かかった。(ブラウジン
# グとかしながらだけど。)

sub new_permutation {
  my ($l, $num) = @_;
  return {cur => undef, list => $l, num => $num};
}

sub first_permutation {
  my ($perm) = @_;
  my $c = [];
  for (my $j = 0; $j < $perm->{num}; $j++) {
    push(@$c, $perm->{num} - $j - 1);
    if ($j >= @{$perm->{list}}) {
      return undef;
    }
  }
  $perm->{cur} = $c;

  my $r = [];
  for (my $i = 0; $i < $perm->{num}; $i++) {
    push(@$r, $perm->{list}->[$c->[$i]]);
  }
  return $r;
}

sub next_permutation {
  my ($perm) = @_;
  my $c = $perm->{cur};
  if (! defined $c) {
    return first_permutation($perm);
  }
  my @t = (undef) x @{$perm->{list}};

  for (my $i = 0; $i < $perm->{num}; $i++) {
    $t[$c->[$i]] = $i;
  }

  for (my $i = 0; $i < $perm->{num}; $i++) {
    for (my $j = $c->[$i] + 1; $j < @{$perm->{list}}; $j++) {
      if (defined $t[$j] && $t[$j] > $i) {
	next;
      } else {
	$t[$c->[$i]] = undef;
	$c->[$i] = $j;
	$t[$j] = $i;
	my $l = 0;
	for (my $k = $i - 1; $k >= 0; $k--) {
	  if ($l >= @{$perm->{list}}) {
	    $perm->{cur} = undef;
	    warn "Why?";
	    return undef;
	  }
	  for (; $l < @{$perm->{list}}; $l++) {
	    if (defined $t[$l] && $t[$l] >= $i) {
	      next;
	    } else {
	      $c->[$k] = $l++;
	      last;
	    }
	  }
	}

	my $r = [];
	for (my $k = 0; $k < $perm->{num}; $k++) {
	  push(@$r, $perm->{list}->[$c->[$k]]);
	}
	return $r;
      }
    }
  }
  $perm->{cur} = undef;
  return undef;
}

sub change {
  my ($c, $spin) = @_;

  my $odd = 0;
  my $simul = 0;
  for (my $i = 0; $i < @$c; $i++) {
    my $card = $c->[$i];
    if ($card % 2) {
      $odd++;
    }
    if ($card == 8 || $card == 11) {
      $simul++;
    }
  }

  if ($simul == 2) {
    for (my $i = 0; $i < @$c; $i++) {
      if ($c->[$i] == 8) {
	$c->[$i] = 11;
      } elsif ($c->[$i] == 11) {
	$c->[$i] = 8;
      }
    }
  } elsif ($simul == 1) {
    for (my $i = 0; $i < @$c; $i++) {
      if ($c->[$i] == 8
	  && ($odd > 3
	      || ($odd == 3 && $spin))) {
	$c->[$i] = 11;
      } elsif ($c->[$i] == 11
	  && ($odd < 3
	      || ($odd == 3 && $spin))) {
	$c->[$i] = 8;
      }
    }
  }

  return $c;
}

MAIN:
{
  our @CARDS = (0 .. 21);
  splice(@CARDS, 13, 1);
  splice(@CARDS, 0, 1);

  my $trials = 0;
  my @n = (0) x 64;
  my @b = (0) x 7;
  my $perm = new_permutation(\@CARDS, 6);
  my $prev_sig  = "";

  while (my $c = next_permutation($perm)) {
    my $perm2 = new_permutation([0, 1], 1);
    while (my $spin = next_permutation($perm2)) {
      $spin = $spin->[0];

      my $cur_sig = join(",", $c->[4], $c->[5]);
      if ($cur_sig ne $prev_sig) {
	print STDERR "...," . $cur_sig . "\n";
      }
      $prev_sig = $cur_sig;

      my $d = change([@$c], $spin);

      my $k = 0;
      my $b = 0;
      for (my $i = 0; $i < 6; $i++) {
	$k = $k * 2;
	if ($d->[$i] % 2) {
	  $k++;
	  $b++;
	}
      }
      $n[$k]++;
      $b[$b]++;

      $trials++;
    }
  }

  print STDERR "== RESULT ==\n";

  for (my $i = 0; $i < 64; $i++) {
    printf("%02x: %g ( %d / %d )\n", $i, $n[$i]/$trials, $n[$i], $trials);
  }

  for (my $i = 0; $i < 7; $i++) {
    printf("%01d: %g ( %d / %d )\n", $i, $b[$i]/$trials, $b[$i], $trials);
  }
}
