Вот версия, в которой используется рекурсия для определения оптимальной стратегии преобразования в минимальном количестве операций. Я предполагаю, что каждый раз, когда вы удваиваетесь, это считается одной операцией; каждый раз, когда вы добавляете 1, это считается одной операцией, и цель состоит в том, чтобы минимизировать общее количество операций.
И тестирование на примере 5-> 23 дает:
((((5)*2)+1)*2)+1=23
С синтаксисом вы можете быть более кратким, но, надеюсь, немного многословия поможет показать смысл кода.
Шляпа для josh.trow, когда я использовал его идею о том, как сделать форматирование строки.
import java.util.ArrayList;
import java.util.List;
public class DoubleAndAddAlgorithm {
public enum Op {
DOUBLE, ADD_ONE
}
private static List<Op> getOptimalTransform(int a, int b) throws IllegalArgumentException {
// Returns the list of operations that comprises the optimal way to get from a to b
// If a is already bigger than b, we have a problem
if (a > b) {
throw new IllegalArgumentException("a cannot be greater than b");
}
List<Op> result = new ArrayList<Op>();
// If we can get there in one operation, do so
if (2*a == b) {
result.add(Op.DOUBLE);
} else if (a+1 == b) {
result.add(Op.ADD_ONE);
}
// If doubling would cause us to overshoot, all we can do is add 1
// and take it from there...
else if (2*a > b) {
result.add(Op.ADD_ONE);
result.addAll(getOptimalTransform(a+1, b));
}
// Otherwise, let's try doubling, and let's try adding one, and use
// recursion to see which gets us to the target quicker
else {
List<Op> trialResultDouble = getOptimalTransform(2*a, b);
List<Op> trialResultAddOne = getOptimalTransform(a+1, b);
// Let's say (arbitrarily), that if neither operation results in us
// getting to the target any quicker than the other, we choose to add 1
if (trialResultDouble.size() < trialResultAddOne.size()) {
result.add(Op.DOUBLE);
result.addAll(trialResultDouble);
} else {
result.add(Op.ADD_ONE);
result.addAll(trialResultAddOne);
}
}
return result;
}
public static String getFormattedResult(int a, int b) {
try {
List<Op> ops = getOptimalTransform(a, b);
StringBuilder sb = new StringBuilder();
sb.append(Integer.toString(a));
for (Op op: ops) {
if (op == Op.DOUBLE) {
sb.insert(0, "(");
sb.append(")*2");
} else if (op == Op.ADD_ONE) {
sb.insert(0, "(");
sb.append(")+1");
}
}
sb.append("=");
sb.append(Integer.toString(b));
return sb.toString();
} catch (IllegalArgumentException e) {
return "Illegal arguments supplied";
}
}
public static void main(String[] args) {
System.out.println( getFormattedResult(5, 23) );
}
}