朝日新聞2005年5月20日のパズル横丁問題

問題

以下の計算式が成り立つように「こ」,「う」,「ん」に0〜9の別々の数字を割り当てる。

解答への道(ヒント)

3週連続の数字の割り当て問題。数字の数は3種類あるが,「こ」は「う」,「ん」に依存して決まるために実質2種類の数字割り当て問題になる。

数字の割り当て問題と見ないで,「うん」を00から99までの数字と見なして虱潰す方法も考えられる。

[方法1]数字の割り当て問題を利用し,「う」にaを,「ん」にbを対応して考える。「こううん」は(a*10+b)*(a*10+b) になる。

  for( int a=0; a< 10; a++) {
    used[a] = YES;
    for( int b=0; b< 10; b++) {
      if( used[b]) continue;
      used[b] = YES;
      int x = (a*10 + b) * (a*10+b);
      int x1 = x % 10; x /= 10;
      int x2 = x % 10; x /= 10;
      int x3 = x % 10; x /= 10;
      int x4 = x % 10; x /= 10;
      if( 「う」⇒a,「ん」⇒b,「こ」⇒x4,「う」⇒x3,「う」⇒x2,「ん」⇒x1 が成り立つか?) {
        ps( "  %-.2s%-.2s\n", ns+a*2, ns+b*2);
        ps( "× %-.2s%-.2s\n", ns+a*2, ns+b*2);
        ps( "----------\n");
        ps( "%-.2s%-.2s%-.2s%-.2s\n", ns+x4*2, ns+x3*2, ns+x2*2, ns+x1*2);
      }
      used[b] = NO;
    }
    used[a] = NO;
  }

[方法2]00〜99まで全ての数について,二乗を計算し,計算結果が条件を満たすか調べる。

  for( int i=0; i< 100; i++) {
    int j = i;
    int x = i*i;
    int x1 = x % 10; x /= 10;
    int x2 = x % 10; x /= 10;
    int x3 = x % 10; x /= 10;
    int x4 = x % 10; x /= 10;
    int i1 = j % 10; j /= 10;
    int i2 = j % 10; j /= 10;
    if( 「う」⇒i2,「ん」⇒i1,「こ」⇒x4,「う」⇒x3,「う」⇒x2,「ん」⇒x1 が成り立つか?) {
      ps( "  %-.2s%-.2s\n", ns+i2*2, ns+i1*2);
      ps( "× %-.2s%-.2s\n", ns+i2*2, ns+i1*2);
      ps( "----------\n");
      ps( "%-.2s%-.2s%-.2s%-.2s\n", ns+x4*2, ns+x3*2, ns+x2*2, ns+x1*2);
    }
  }

答えを全角で出力するように以下のように設定する。

cstring       ns = "0123456789";

方法1,方法2とも1件出力されました。

解速度