这是
emacs
中的一个小游戏:给一个用大写字母表示的乘法算式,计算出每个大写字母代表的数字。例如,以下的乘法竖式:
B I D
x D J
-------
A B H D
H J I D
---------
H D A I D
在这个式子中,
BID = 475
,
DJ = 53
,
ABHD = 1425
,
HJID = 2375
,
HDAID = 25175
。现在写一个程序,根据给定的算式计算每一个大写字母代表的数字。
因为在
emacs
的这个小游戏中,所有算式都有相同的特点:被乘数
3
位数,乘数
2
位数,中间结果都是
4
位数,最终结果都是
5
位数。所以,专门针对
emacs
的小游戏的这个程序的一个非常简单的思路就是:枚举所有三位数和两位数相乘的式子,检测它们是否与给定的字母表示相容,如果有冲突,继续枚举下一个式子,否则就找到了解。
如何判断找到的式子是否与给定的字母表示相容呢?假设
A, B
是任意两个字母表示,
a,b
是枚举出来的与
A,B
对应的数字值。不相容有两种情况:
A==B
但
a!=b
,或者
A!=B
但
a==b
,即
flag = (A == B && a != b) || (A != B && a == b)
,当
flag
为
1
时,表示有冲突。从
flag
的表达式很容易能看出
flag
的表达式可以简写为:
flag = (A == B) ^ (a == b)
。
下面是源代码:
#include
<stdio.h>
#include <string.h>
#define print(cnt, format, array) for (i = 0; i < cnt; i++) printf(format, *(array+i))
int main() {
int op1, op2, a, b;
char all[32], temp[32];
int i, j, flag;
*all = 0;
puts( "input op1:" ); scanf ( "%s" , all + strlen (all));
puts( "input op2:" ); scanf ( "%s" , all + strlen (all));
puts( "input median result and final result line by line:" );
scanf ( "%s" , all + strlen (all)); /* get first median resutl */
scanf ( "%s" , all + strlen (all)); /* get second median resutl */
scanf ( "%s" , all + strlen (all)); /* get final result */
for( op1 = 100; op1 <= 999; op1++) {
for( op2 = 10; op2 <= 99; op2++) {
a = op2 % 10;
b = op2 / 10;
if( op1 * a < 1000 || op1 * b < 1000) continue ;
memset ( temp, 0, sizeof (temp));
sprintf ( temp, "%d%d%d%d%d" , op1, op2, op1 * a, op1 * b, op1 * op2);
flag = 1;
if( strlen (all) != strlen (temp)) { flag = 0; break ; }
for( i = 0; i < strlen (all); i++) {
for( j = 0; j < i; j++) {
if( (all[i] == all[j]) ^ (temp[i] == temp[j])) {
flag = 0; break ;
}
}
if( flag == 0) break ;
}
if( flag) {
print(3, "%c" , all); printf ( " = " ); print(3, "%c" , temp); printf ( "/n" );
print(2, "%c" , all + 3); printf ( " = " );print(2, "%c" , temp + 3); printf ( "/n" );
print(4, "%c" , all + 5); printf ( " = " );print(4, "%c" , temp + 5); printf ( "/n" );
print(4, "%c" , all + 9); printf ( " = " );print(4, "%c" , temp + 9); printf ( "/n" );
printf ( "%s = %s/n" , all + 13, temp + 13);
return 0;
}
}
}
return 0;
}
例如对一开始的例子运行,输入:
#include <string.h>
#define print(cnt, format, array) for (i = 0; i < cnt; i++) printf(format, *(array+i))
int main() {
int op1, op2, a, b;
char all[32], temp[32];
int i, j, flag;
*all = 0;
puts( "input op1:" ); scanf ( "%s" , all + strlen (all));
puts( "input op2:" ); scanf ( "%s" , all + strlen (all));
puts( "input median result and final result line by line:" );
scanf ( "%s" , all + strlen (all)); /* get first median resutl */
scanf ( "%s" , all + strlen (all)); /* get second median resutl */
scanf ( "%s" , all + strlen (all)); /* get final result */
for( op1 = 100; op1 <= 999; op1++) {
for( op2 = 10; op2 <= 99; op2++) {
a = op2 % 10;
b = op2 / 10;
if( op1 * a < 1000 || op1 * b < 1000) continue ;
memset ( temp, 0, sizeof (temp));
sprintf ( temp, "%d%d%d%d%d" , op1, op2, op1 * a, op1 * b, op1 * op2);
flag = 1;
if( strlen (all) != strlen (temp)) { flag = 0; break ; }
for( i = 0; i < strlen (all); i++) {
for( j = 0; j < i; j++) {
if( (all[i] == all[j]) ^ (temp[i] == temp[j])) {
flag = 0; break ;
}
}
if( flag == 0) break ;
}
if( flag) {
print(3, "%c" , all); printf ( " = " ); print(3, "%c" , temp); printf ( "/n" );
print(2, "%c" , all + 3); printf ( " = " );print(2, "%c" , temp + 3); printf ( "/n" );
print(4, "%c" , all + 5); printf ( " = " );print(4, "%c" , temp + 5); printf ( "/n" );
print(4, "%c" , all + 9); printf ( " = " );print(4, "%c" , temp + 9); printf ( "/n" );
printf ( "%s = %s/n" , all + 13, temp + 13);
return 0;
}
}
}
return 0;
}
例如对一开始的例子运行,输入:
BID
DJ
ABHD
HJID
HDAID
程序就会输出结果:
BID = 475
DJ = 53
ABHD = 1425
HJID = 2375