project euler 93

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;

		}

	}

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值