以下の計算式が成り立つように「こ」,「う」,「ん」に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件出力されました。
解速度
即