朝日新聞2006年4月28日パズル横丁解答

プログラムの実行結果は以下の通り。

嘘つきの帽子の色は 赤

プログラムのソースは以下の通り。

#include "puzutl.h"

int check( int a, int b, int c, int d)
{
  // 他の人の帽子の色から自分の帽子の色が判るか判らないか判断する。
  int n = b+c+d;
  if( n == 3) return    1;      // 自分以外の3人が赤の帽子だから自分は白
  if( n == 1) return    1;      // 自分以外の2人が白の帽子だから自分は赤
  return    0;                  // 判らない
}

void count( int color, int& cntR, int& cntW)
{
  if(color)cntR++;
  else     cntW++;
}

int main( int argc, cstring argv[])
{
  int cntR=0, cntW=0;           // 嘘つきが答えた色
  for( int a=0; a< 2; a++) {
    for( int b=0; b< 2; b++) {
      for( int c=0; c< 2; c++) {
        for( int d=0; d< 2; d++) {
          int n = a+b+c+d;    // 赤色帽子の数
          if( n < 1 || n >= 4) continue; // 配られた中に赤は必ず1つあり,4つは無い
          int A,B,C,D;
          A = check( a,b,c,d); // 自分の帽子の色が判る?
          B = check( b,a,c,d);
          C = check( c,a,b,d);
          D = check( d,a,b,c);
          int m = A+B+C+D;    // 帽子の色が判った人の数
          if( m == 2) {
            // 自分の帽子の色が判った人の数2名,判らない人2名。
            // 判った人が嘘をつくと判った人1名,判らない人3名になる。
            if( A) count(a,cntR,cntW); // 嘘つきの帽子の色を数える
            if( B) count(b,cntR,cntW);
            if( C) count(c,cntR,cntW);
            if( D) count(d,cntR,cntW);
          }
          else if( m == 0) {
            // 自分の帽子の色が判った人の数0名,判らない人4名
            // 判らない人の1名が嘘をついて,判った人1名,判らない人3名になる。
            // 実際にはここには来ない。
            assert(0);
          }
          else {
            // 判ったと答える人1名,判らないと答える人3名にならない組み合わせ。
          }
        }
      }
    }
  }
  if( cntR==0) ps( "嘘つきの帽子の色は 白\n");
  else if( cntW==0) ps( "嘘つきの帽子の色は 赤\n");
  else ps( "答えが見つからない\n");
  return    0;
}