今回の問題は、トランプを用いた推理パズルです。ジョーカーを除くトランプ 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: (この情報だけでは) 分かりません
カード 2 枚の数値の組み合わせは、91 通り
(13 + 12 + ... + 2 + 1) あります。これを積の値で表にすると、以下のようになります。
1: 1:1 24: 2:12, 3:8, 4:6 55: 5:11 104: 8:13 2: 1:2 25: 5:5 56: 7:8 108: 9:12 3: 1:3 26: 2:13 60: 5:12, 6:10 110: 10:11 4: 1:4, 2:2 27: 3:9 63: 7:9 117: 9:13 5: 1:5 28: 4:7 64: 8:8 120: 10:12 6: 1:6, 2:3 30: 3:10, 5:6 65: 5:13 121: 11:11 7: 1:7 32: 4:8 66: 6:11 130: 10:13 8: 1:8, 2:4 33: 3:11 70: 7:10 132: 11:12 9: 1:9, 3:3 35: 5:7 72: 6:12, 8:9 143: 11:13 10: 1:10, 2:5 36: 3:12, 4:9, 6:6 77: 7:11 144: 12:12 11: 1:11 39: 3:13 78: 6:13 156: 12:13 12: 1:12, 2:6, 3:4 40: 4:10, 5:8 80: 8:10 169: 13:13 13: 1:13 42: 6:7 81: 9:9 14: 2:7 44: 4:11 84: 7:12 15: 3:5 45: 5:9 88: 8:11 16: 2:8, 4:4 48: 4:12, 6:8 90: 9:10 18: 2:9, 3:6 49: 7:7 91: 7:13 20: 2:10, 4:5 50: 5:10 96: 8:12 21: 3:7 52: 4:13 99: 9:11 22: 2:11 54: 6:9 100: 10:10
A さんが「分かりません」と答えているので、複数個の組み合わせがあることを示しています。 A さんに伝えられた積の値は、4, 6, 8, 9, 10, 12, 16, 18, 20, 24, 30, 36, 40, 48, 60, 72 のうちの1つです。
B: 私も分かりません。ただ,A さんが『分かりません』と回答するは分かっていました
B さんの回答には、2つの内容が含まれています。1つ目は「私にも分かりません」です。
2枚のカードの和の値が 2, 3, 25, 26 のときは、2枚のカードの数値が特定できるので、
「分かりました」と答えるはずです。したがって、B さんに伝えられた和の数は、残る 4 から 24 のうちの
1 つというこうとになります。
2: 1:1 3: 1:2 4: *1:3, 2:2 5: 1:4, 2:3 6: *1:5, 2:4, 3:3 7: 1:6, 2:5, 3:4 8: *1:7, 2:6, *3:5, 4:4 9: 1:8, *2:7, 3:6, 4:5 10: 1:9, 2:8, *3:7, 4:6, *5:5 11: 1:10, 2:9, 3:8, *4:7, 5:6 12: *1:11, 2:10, *3:9, *4:8, *5:7, 6:6 13: 1:12, *2:11, 3:10, 4:9, 5:8, *6:7 14: *1:13, 2:12, *3:11, 4:10, *5:9, 6:8, *7:7 15: *2:13, 3:12, *4:11, *5:10, *6:9, *7:8 16: *3:13, 4:12, *5:11, 6:10, *7:9, *8:8 17: *4:13, 5:12, *6:11, *7:10, *8:9 18: *5:13, 6:12, *7:11, *8:10, *9:9 19: *6:13, *7:12, *8:11, *9:10 20: *7:13, *8:12, *9:11, *10:10 21: *8:13, *9:12, *10:11 22: *9:13, *10:12, *11:11 23: *10:13, *11:12 24: *11:13, *12:12 25: 12:13 26: 13:13
2つ目の「A さんが『分かりません』と回答するは分かっていました」は、少し分かりにくい表現です。2 枚のカードの和が 4 と 5 を例にして、説明してみましょう。和が 4 の場合の組み合わせは 1:3 と 2:2 で、積が 4 になる組み合わせは 1:4 と 2:2 の2種類ありますが、積が 3 になる組み合わせは 1:3 の1種類しかなく「A さんが『分かりません』と回答するは分かっていました」とは言えないことになります。一方、和が 5 の場合の組み合わせは 1:4 と 2:3 で、積が 4 (1:4 と 2:2) も 6 (1:6 と 2:3) も複数種類あるので、 「A さんが『分かりません』と回答するは分かっていました」と言えることになります。
「A さんが『分かりません』と回答するは分かっていました」と言えるには、 和の組み合わせすべてに、それから求めた積の組み合わせが複数種類存在することが必要です。上の表の * の付いた組み合わせは積の数が 1 つですので、* を含む行は除外されることになります。その観点から 4 から 24 を検討すると、B さんに告げられた和の数は 5 あるいは 7 のどちらかということになります。
「A さんが『分かりません』と回答するは分かっていました」には、もう 1 つの意味があります。B さんは A さんが答える前から分かっていたわけですから、回答の順番を入れ替えて最初に B さんが答えたかのように扱うことができます。このことは、プログラムのコード化の際に役立ちます。先に B さんの回答をコード化すると、その過程で積の複数種類存在も確認するので一度で済んでしまいます。
A: それなら,分かりました
B さんの回答から2枚のカードの和は 5 または 7
のどちらかですので、A さんに告げられた2枚のカードの積は 4 (1:4), 6 (2:3), 6 (1:6), 10 (2:5), 12 (3:4)
のうちの1つですが、「それなら、分かりました」と A さんが回答しているので複数の組み合わせがある 6 ではありません。
残る 4, 10, 12 のうちの1つが A さんに告げられた積の数ということになります。なお、A
さんは「それなら、分かりました」と答えることはできますが、パズルを解く第三者 (私やあなた)
には A さんの回答からは分かりません。
B: それなら,私も分かりました
この段階で2枚のカードの組み合わせは、1:4, 2:5, 3:4
の3つに絞り込まれました。和が 5 になるのが 1:4 の1つ、和が 7 になるのが 2:5 と 3:4 の2つです。
「それなら、私も分かりました」と答えているので、B さんに告げられた数は 5 ということになります。
なお、A さんに告げられた数は 4 で、2枚のカードは 1 と 4 です。
ここまで検討してきたのをコード化したものが、次のプログラムです。最初の 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)