トランプの積と和のパズル

今回の問題は、トランプを用いた推理パズルです。ジョーカーを除くトランプ 52 枚から 2 枚を抜いて、その 2 枚の積と和を計算します (A=1, J=11, Q=12, K=13)。計算結果の積を A さんに,和を B さんに伝えて、2 枚のカードの数を尋ねたところ、次の順番で回答がありました。

A: (この情報だけでは) 分かりません
B: 私も分かりません。ただ,A さんが『分かりません』と回答するのは分かっていました
A: それなら,分かりました
B: それなら,私も分かりました

上記の回答から、A さんと B さんに告げられた数、および 2 枚のカードの数を当てるのが今回のパズルです。 A さんと B さんが交互に答えていますが、そのいずれにも「分かる」の変化形が含まれています。 「分かりません」、「分かっていました」、「分かりました」の意味を考えてどのように解釈するかが、 パズルを解くポイントになります。それでは、回答を1つずつ検討していくことにしましょう。

ここまで検討してきたのをコード化したものが、次のプログラムです。最初の A さんの回答は省略して、最初の B さんの回答のコードの中で間接的に確認するような構成になっています。 それ以外は、説明の順序にしたがっているので解りやすいのではないかと思います。

use strict;
my $n = $ARGV[0] || 13;
my (%wa, %seki, %result);

foreach my $i (1 .. $n) {    # %wa と %seki を作成
  foreach my $j ($i .. $n) {
    my $wa = $i + $j;   push @{$wa{$wa}}, "$i:$j";
    my $seki = $i * $j; push @{$seki{$seki}}, "$i:$j";
  }
}

WA: foreach my $key_1 (keys %wa) {       # %wa の解析
  next if @{$wa{$key_1}} == 1;
  foreach my $comb (@{$wa{$key_1}}) {    # 積の組み合わせに1つのものが含まれる場合はスキップする
    my $key_2 = eval(join '*', split /:/, $comb);
    next WA if @{$seki{$key_2}} == 1;
  }
  foreach my $comb (@{$wa{$key_1}}) {    # 積のハッシュを作成
    my $key_2 = eval(join '*', split /:/, $comb);
    push @{$result{seki}->{$key_2}}, $comb;
  }
}

foreach (keys %{$result{seki}}) {    # 積のハッシュから和のハッシュを作成
  next if @{$result{seki}->{$_}} >= 2;
  my $key = eval(join '+', split /:/, $result{seki}->{$_}->[0]);
  push @{$result{wa}->{$key}}, $result{seki}->{$_}->[0];
}

foreach (sort { $a <=> $b } keys %{$result{wa}}) {    # 正解を表示
  next if @{$result{wa}->{$_}} >= 2;
  my ($i, $j) = split /:/, $result{wa}->{$_}->[0];
  print "A:", $i * $j, " B:", $i + $j, " $result{wa}->{$_}->[0]\n";
}

プログラムでは、3つのハッシュ %wa, %seki, %result を使っています。%wa と %seki は、説明中に記載してある表とほぼ同じのデータ構造です。%result は正解を導き出すハッシュで、 次のようなデータ構造が作られます。

%result = ( seki => { 4 => ['1:4'], 6 => ['2:3', '1:6'], 10 => ['2:5'], 12 => ['3:4'] },
            wa   => { 5 => ['1:4'], 7 => ['2:5', '3:4'] });

%wa を解析して、通過した 5 と 7 のリストを積の値で分類します。 次に、積のリストが複数あるものを除外して和のリストを作成します。 そして、和のリストの複数のものを除外して正解を表示するという流れになります。

今回のパズルはトランプを題材にしているので 1 から 13 の数値を使っていますが、プログラム自体は引数に n を指定できるようになっています (省略すると 13)。引数 n を指定すると 1 から n までの数を使って、 正解を見つけようとします。100 以下の引数では、次のような正解が表示されます。

   - 9    --
10 - 13   A:4 B:5 1:4
14 - 21   A:4 B:5 1:4, A:12 B:7 3:4
22 - 24   A:4 B:5 1:4
25 - 37   A:4 B:5 1:4, A:28 B:11 4:7
38 - 45   A:4 B:5 1:4, A:28 B:11 4:7, A:40 B:13 5:8
46 - 48   A:4 B:5 1:4, A:40 B:13 5:8, A:52 B:17 4:13
49 - 61   A:4 B:5 1:4, A:8 B:9 1:8, A:40 B:13 5:8, A:52 B:17 4:13
62 - 73   A:4 B:5 1:4, A:8 B:9 1:8, A:40 B:13 5:8, A:52 B:17 4:13, A:88 B:19 8:11
74 - 85   A:4 B:5 1:4, A:8 B:9 1:8, A:52 B:17 4:13, A:88 B:19 8:11
86 - 93   A:4 B:5 1:4, A:8 B:9 1:8, A:52 B:17 4:13, A:56 B15 7:8, A:88 B:19 8:11
94 - 100  A:4 B:5 1:4, A:8 B:9 1:8, A:56 B:15 7:8, A:88 B:19 8:11

9 以下では正解がなく、単一解があるのは 10 - 13 と 22 - 24 のみです。それ以外は、すべて複数解があります。それも n が大きくなると解の数が単純に多くなるのではなく、多くなったり少なくなったりしながらだんだんと多くなる感じです。 ちなみに 1000 の場合は 27 の正解があり、2000 では 33 の正解があります。

100 以下の正解は、すべて奇数と偶数の組み合わせになっています。もうひとつ 2 つの数の組み合わせの法則性は分からないのですが、n の値を大きくしていくと奇数と奇数の組み合わせが現れます。 しかも、169 から 942 の間は、奇数と奇数と組み合わせの正解は 1 つしか存在しません (大まかな確認なので、抜けがあるかも)。そこで、冒頭のパズルを少し変形して、 新たなパズルとしてみました。オリジナルパズルよりも優れているとはいえませんが、考えて頂けたらと思います。

1 から 169 までの奇数 (1, 3, 5, ... , 165, 167, 169) 2 組の中から 2 つの数字を選んで、 その積と和を計算します。計算結果の積を A さんに,和を B さんに伝えて、2 つの数を尋ねたところ、 次の順番で回答がありました。

A: (この情報だけでは) 分かりません
B: 私も分かりません。ただ,Aさんが『分かりません』と回答するのは分かっていました
A: それなら,分かりました
B: それなら,私も分かりました

上記の回答から、A さんと B さんに伝えられた数、および 2 つの数字を当ててください。

(2012/09/01)

TopPage