我正在解决EAT + THAT = APPLE的问题,其中每个字母代表0-9之间的不同数字。我需要找到所有组合。我在想是否有更好的写法,特别是’if’和’for’语句的部分。
我尝试这样写,但它给了我无限的结果
public class Main {public static void main(String[] args) {int count = 0;int E,A,T,P,L,H;for (E = 0; E <=9; E++) { for (A = 0; A <=9; A++) for (T = 0; T <=9; T++) for (P = 0; P <=9; P++) for (L = 0; L <=9; L++) for (H = 0; H <=9; H++) if (((E != A) && (E != L) && (E != T)&&(E !=P) &&(E!=L)&&(E!=H) && (T != A) && (T != L) && (T != E) &&(T!=P)&&(T!=L)&&(T!=H))) { System.out.println("A"+A+"P"+P+"P"+P+"L"+L+"E"+E); } else count = count +1; }System.out.println(count); }}
回答:
面对这样的问题,尽可能简化问题非常重要。
让我们创建一个子问题:
假设THAT
必须等于8208。每个字符的值是多少?
你可以注意到你只是在解一个方程:T
* 1000 + H
* 100 + A
* 10 + T
= 8208(唯一的解是T
= 8, H
= 2, A
= 0)
回到我们的主要问题:
使用上面的逻辑,将主要问题简化为一个方程,
EAT
+ THAT
= APPLE
=> EAT
+ THAT
– APPLE
= 0;
这实际上意味着:
E
* 100 + A
* 10 + T
+ T
* 1000 + H
* 100 + A
* 10 + T
– A
* 10000 – P
* 1000 – P
* 1000 – L
* 10 – E
= 0
简化后你得到:-9980 * A
– 1100 * P
+ 1002 * T
+ 100 * H
+ 99 * E
– 10 * L
= 0
由于每个变量的值非常有限,我们可以自由地使用暴力破解法来解决问题。
public class MyClass { public static int[] calc(){ for(int A = 0; A < 10; A++){ for(int P = 0; P < 10; P++){ for(int T = 0; T < 10; T++){ for(int H = 0; H < 10; H++){ for(int E = 0; E < 10; E++){ for(int L = 0; L < 10; L++){ if(A!=P && A != T && A != H && A != E && A != L && P != T && P != H && P != E && P != L && T != H && T != E && T != L && H != E && H != L && E != L){ //在你的代码中缺少这个语句,它检查值是否确实是方程的解 if(-9980 * A - 1100 * P + 1002 * T + 100 * H + 99 * E - 10 * L == 0){ int[] outArr = {A, P, T, H, E, L}; return outArr; } } } } } } } } return null; } public static void main(String args[]) { int[] answer = calc(); System.out.println("A" + answer[0] + " P" + answer[1] + " P" + answer[1] + " L" + answer[5] + " E" + answer[4]); }}
如果你不希望你的if语句如此庞大,你可以创建一个大小为10的数组,填充零,对于每个变量(我们称之为i
),通过array[i]++;
增加给定索引的值,如果在任何时候任何索引array[x]
> 1,你就会知道值是重复的。
有优化脚本工作方式的方法,通过承认数字之间的关系(例如,你可以观察到A
只能等于0或1,而0会导致矛盾的方程,所以A
必须等于1,以此类推,直到你仅通过逻辑找到每个数字的确切值),但最终你会得到一个纯粹的数学解,我认为这不是你想要的结果。