#java #алгоритм #инспекция_кода
Я новичок в Java (программировал в Pascal) и мне нужно написать программу для решения
следующего задания (что-то вроде числового ребуса):
AB + CC = DC
CE * FB = CEB
FF * GC = GHC
AB - CE = FF
CC + FB = GC
DC + CEB = GHC
П.С. Каждый символ одна цифра (от 0 до 9). Каждая цифра может использоваться только
один раз.
Итак, я написал следующую программу:
public class javaapplication1 {
public static void main(String[] args) {
boolean bb=false;
for (int h = 0; h < 10; h++) {
for (int g = 0; g < 10; g++) {
if (bb) {
break;
}
for (int f = 0; f < 10; f++) {
if (bb) {
break;
}
for (int e = 0; e < 10; e++) {
if (bb) {
break;
}
for (int d = 0; d < 10; d++) {
if (bb) {
break;
}
for (int c = 0; c < 10; c++) {
if (bb) {
break;
}
for (int b = 0; b < 10; b++) {
if (bb) {
break;
}
for (int a = 0; a < 10; a++) {
if (a*10 + b + c*10 + c == d*10 + c) {
if ((c*10+e)*(f*10+b)==(c*100+e*10+b)) {
if ((f*10+f)*(g*10+c)==g*100+h*10+c) {
if ((a*10+b)-(c*10+e) == f*10+f) {
if ((c*10+c)+(f*10+b) ==
g*10+c) {
if ((d*10+c)+(c*100+e*10+b)
== g*100+h*10+c) {
if (a!=b && a!=c
&& a!=d && a!=e && a!=f && a!=g && a!=h) {
if (b!=c && b!=d
&& b!=e && b!=f && b!=g && b!=h) {
if (c!=d
&& c!=e && c!=f && c!=g && c!=h) {
if (d!=e
&& d!=f && d!=g && d!=h) {
if
(e!=f && e!=g && e!=h) {
if (f!=g && f!=h) {
if (g!=h) {
bb = true;
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
System.out.println(e);
System.out.println(f);
System.out.println(g);
System.out.println(h);
break;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
Она работает и выдаёт правильные результаты, однако я уверен, что она написано неправильно,
так как решение само по себе глупое - чистый подбор. Прошу показать мне, как можно
оптимизировать данную программу.
З.Ы. Большое количество if-ов писал в большей степени для большей понятности кода
для себя лично.
Ответы
Ответ 1
Незачем делать сложный break через булеву переменную. Достаточно return, это прервёт все циклы. Условие "Каждая цифра может использоваться только один раз" нужно проверять не самым последним, а на этапе перебора. Так у вас будет всего 10!/2!=10*9*8*7*6*5*4*3 проверки, а не 10^8. Определяете множество всех цифр. Во внешнем цикле перебор по этому множеству. В следующем цикле перебор по множеству из предыдущего цикла без той цифры, которая выбрана в предыдущем цикле. В следующем цикле перебор по множеству из предыдущего цикла без той цифры, которая выбрана в предыдущем цикле... и так далее. Условия можно выделить и хранить как список методов (лямбд), а потом делать проверку в цикле.Ответ 2
Решение "джаст фор фан", но по производительности даже получше, учитывая распараллеливание: IntFunctiona = x -> x / 10000000 % 10; IntFunction b = x -> x / 1000000 % 10; IntFunction c = x -> x / 100000 % 10; IntFunction d = x -> x / 10000 % 10; IntFunction e = x -> x / 1000 % 10; IntFunction f = x -> x / 100 % 10; IntFunction g = x -> x / 10 % 10; IntFunction h = x -> x % 10; IntFunction fx = i -> IntStream.range(0, 10).filter(x -> { if (x == i) return false; for (int j = i; j > 0; j /= 10) { if (x == j % 10) { return false; } } return true; }).map(x -> 10 * i + x); IntStream.range(0, 10).parallel() .flatMap(fx) .flatMap(fx) .flatMap(fx) .flatMap(fx) .flatMap(fx) .flatMap(fx) .flatMap(fx) .filter(x -> a.apply(x) * 10 + b.apply(x) + c.apply(x) * 10 + c.apply(x) == d.apply(x) * 10 + c.apply(x)) .filter(x -> (f.apply(x) * 10 + f.apply(x)) * (g.apply(x) * 10 + c.apply(x)) == g.apply(x) * 100 + h.apply(x) * 10 + c.apply(x)) .filter(x -> (a.apply(x) * 10 + b.apply(x)) - (c.apply(x) * 10 + e.apply(x)) == f.apply(x) * 10 + f.apply(x)) .filter(x -> (c.apply(x) * 10 + e.apply(x)) * (f.apply(x) * 10 + b.apply(x)) == (c.apply(x) * 100 + e.apply(x) * 10 + b.apply(x))) .filter(x -> (c.apply(x) * 10 + c.apply(x)) + (f.apply(x) * 10 + b.apply(x)) == g.apply(x) * 10 + c.apply(x)) .filter(x -> (d.apply(x) * 10 + c.apply(x)) + (c.apply(x) * 100 + e.apply(x) * 10 + b.apply(x)) == g.apply(x) * 100 + h.apply(x) * 10 + c.apply(x)) .forEach(System.out::println);
Комментариев нет:
Отправить комментарий