Problem 93
Arithmetic expressions
By using each of the digits from the set, {1, 2, 3, 4}, exactly once, and making use of the four arithmetic operations (+, −, *, /) and brackets/parentheses, it is possible to form different positive integer targets.
For example,
8 = (4 * (1 + 3)) / 2
14 = 4 * (3 + 1 / 2)
19 = 4 * (2 + 3) − 1
36 = 3 * 4 * (2 + 1)
Note that concatenations of the digits, like 12 + 34, are not allowed.
Using the set, {1, 2, 3, 4}, it is possible to obtain thirty-one different target numbers of which 36 is the maximum, and each of the numbers 1 to 28 can be obtained before encountering the first non-expressible number.
Find the set of four distinct digits, a < b < c < d, for which the longest set of consecutive positive integers, 1 to n, can be obtained, giving your answer as a string: abcd.
算术表达式
使用集合{1, 2, 3, 4}中每个数字恰好一次以及(+, −, *, /)四则运算和括号,可以得到不同的正整数。
例如,
8 = (4 * (1 + 3)) / 2
14 = 4 * (3 + 1 / 2)
19 = 4 * (2 + 3) − 1
36 = 3 * 4 * (2 + 1)
注意不允许直接把数字连起来,如12 + 34。
使用集合{1, 2, 3, 4},可以得到31个不同的数,其中最大值是36,以及1到28之间所有的数。
若使用包含有四个不同数字a < b < c < d的集合可以得到从1到n之间所有的数,求其中使得n最大的集合,并将你的答案写成字符串:abcd。
package projecteuler;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import junit.framework.TestCase;
public class Prj93 extends TestCase {
public Map<Sequence, Set<Integer>> MAP = new HashMap<Sequence, Set<Integer>>();
public void testArithmeticExpressions() {
int[] idx = new int[4];
dfs(idx, 0);
int max = 0;
Sequence sq = null;
for (Entry<Sequence, Set<Integer>> entry : MAP.entrySet()) {
Set<Integer> set = entry.getValue();
int n = calMaxN(set);
if (n > max) {
max = n;
sq = entry.getKey();
}
}
System.out.println(sq);
System.out.println(max);
}
private int calMaxN(Set<Integer> set) {
int n = 1;
while (set.contains(n)) {
n++;
}
return n - 1;
}
public static class ArithmeticExpressionsPattern {
/**
* [1,2,3,4]; p_12=(1+2)+3 + 4; p_13=(1+2+3) + 4;
*/
public static final String P_12 = "(%d%s%d)%s%d%s%d";
public static final String P_13 = "(%d%s%d%s%d)%s%d";
public static final String P_23 = "%d%s(%d%s%d)%s%d";
public static final String P_24 = "%d%s(%d%s%d%s%d)";
public static final String P_34 = "%d%s%d%s(%d%s%d)";
public static final String P_13_12 = "((%d%s%d)%s%d)%s%d";
public static final String P_13_23 = "(%d%s(%d%s%d))%s%d";
public static final String P_24_23 = "%d%s((%d%s%d)%s%d)";
public static final String P_24_34 = "%d%s(%d%s(%d%s%d))";
public static List<String> getPatterns() {
return Arrays.asList(P_12, P_13, P_23, P_24, P_34, P_13_12,
P_13_23, P_24_23, P_24_34);
}
}
public void dfs(int[] idx, int depth) {
if (depth >= 4) {
calAllCombinations(idx);
return;
}
for (int i = 1; i <= 9; i++) {
if (depth == 0) {
idx[depth] = i;
dfs(idx, depth + 1);
} else if (depth == 1) {
if (i == idx[0]) {
continue;
}
idx[1] = i;
dfs(idx, depth + 1);
} else if (depth == 2) {
if (i == idx[0] || i == idx[1]) {
continue;
}
idx[2] = i;
dfs(idx, depth + 1);
} else if (depth == 3) {
if (i == idx[0] || i == idx[1] || i == idx[2]) {
continue;
}
idx[3] = i;
dfs(idx, depth + 1);
}
}
}
private void calAllCombinations(int[] idx) {
System.out.println(idx[0] + "," + idx[1] + "," + idx[2] + "," + idx[3]);
StringBuilder sb = new StringBuilder();
List<String> patterns = ArithmeticExpressionsPattern.getPatterns();
String[] operations = new String[] { "+", "-", "*", "/" };
int count = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++) {
for (String str : patterns) {
String tp = String.format(str, idx[0], operations[i],
idx[1], operations[j], idx[2], operations[k],
idx[3]);
sb.append("var p" + Integer.toString(count++) + "="
+ tp + ";");
}
}
}
}
Set<Integer> set = new Operate().caculateArr(sb.toString(), count);
Sequence sq = new Sequence(idx);
if (!MAP.containsKey(sq)) {
MAP.put(sq, new HashSet<Integer>());
}
MAP.get(sq).addAll(set);
}
public static class Sequence {
public Sequence(int[] arr) {
int[] tp = new int[arr.length];
tp[0] = arr[0];
tp[1] = arr[1];
tp[2] = arr[2];
tp[3] = arr[3];
Arrays.sort(tp);
a = tp[0];
b = tp[1];
c = tp[2];
d = tp[3];
}
public int a;
public int b;
public int c;
public int d;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (a + b + c + d);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Sequence other = (Sequence) obj;
if (a != other.a)
return false;
if (b != other.b)
return false;
if (c != other.c)
return false;
if (d != other.d)
return false;
return true;
}
@Override
public String toString() {
return "Sequence [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d
+ "]";
}
}
public static class Operate {
ScriptEngineManager manager = new ScriptEngineManager();
public Set<Integer> caculateArr(String string, int count) {
ScriptEngine engine = manager.getEngineByName("JavaScript");
Set<Integer> ret = new HashSet<Integer>();
try {
Object val = engine.eval(string);
for (int i = 0; i < count; i++) {
val = engine.get("p" + Integer.toString(i));
Double d = Double.parseDouble(val.toString());
if (d == 1.0 * d.intValue() && d > 0) {
ret.add(d.intValue());
}
}
} catch (ScriptException e) {
e.printStackTrace();
}
return ret;
}
}
}