project euler 98

Problem 98


Anagramic squares

By replacing each of the letters in the word CARE with 1, 2, 9, and 6 respectively, we form a square number: 1296 = 362. What is remarkable is that, by using the same digital substitutions, the anagram, RACE, also forms a square number: 9216 = 962. We shall call CARE (and RACE) a square anagram word pair and specify further that leading zeroes are not permitted, neither may a different letter have the same digital value as another letter.

Using words.txt (right click and ‘Save Link/Target As…’), a 16K text file containing nearly two-thousand common English words, find all the square anagram word pairs (a palindromic word is NOT considered to be an anagram of itself).

What is the largest square number formed by any member of such a pair?

NOTE: All anagrams formed must be contained in the given text file.


重排平方数

将单词CARE中的四个字母依次赋值为1、2、9、6,我们得到了一个平方数:1296 = 362。神奇的是,使用同样的数字赋值,重排后的单词RACE同样构成了一个平方数:9216 = 962。我们称CARE和RACE为重排平方单词对,同时规定这样的单词对不允许有前导零或是不同的字母赋相同的值。

在这个16K的文本文件words.txt(右击并选择“目标另存为……”)中包含了将近两千个常见英文单词,找出所有的重排平方单词对(一个回文单词不视为它自己的重排)。

重排平方单词对所给出的最大平方数是多少?

注意:所有的重排单词必须出现在给定的文本文件中。

package projecteuler;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
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 java.util.StringTokenizer;

import junit.framework.TestCase;

public class Prj98 extends TestCase {

	public static final String PATH = "E:\\whua\\mathWorkspace\\test_jgraph\\src\\projecteuler\\Prj98.txt";

	public void testAnagramicSquares() {

		List<String> strList = readStrs();
		Map<String, Set<String>> map = new HashMap<String, Set<String>>();
		for (String str : strList) {
			String sortStr = getSortStr(str);
			if (!map.containsKey(sortStr)) {
				map.put(sortStr, new HashSet<String>());
			}
			map.get(sortStr).add(str);
		}

		Map<String, Set<String>> copyMap = new HashMap<String, Set<String>>();
		// Set<String> set = new HashSet<String>();
		// set.add("CARE");
		// set.add("RACE");
		// copyMap.put("CARE", set);
		for (Entry<String, Set<String>> entry : map.entrySet()) {
			if (entry.getValue().size() != 2) {
				continue;
			} else {

				Object[] strs = entry.getValue().toArray();
				if (isReverse(strs[0].toString(), strs[1].toString())) {
					continue;
				}
				copyMap.put(entry.getKey(), entry.getValue());
			}
		}
		System.out.println(copyMap);
		System.out.println(copyMap.size());

		int max = 0;
		String id = "";
		for (Entry<String, Set<String>> entry : copyMap.entrySet()) {
			Object[] strs = entry.getValue().toArray();
			int val = getMax(strs[0].toString(), strs[1].toString(),
					entry.getKey());
			if (val > max) {
				max = val;
				id = entry.getKey();
			}
		}

		System.out.println("max=" + max + copyMap.get(id));

	}

	private int getMax(String str1, String str2, String key) {

		System.out.println(str1 + "=" + str2);
		Set<Character> set = new HashSet<Character>();
		for (int i = 0; i < key.length(); i++) {
			set.add(key.charAt(i));
		}
		List<Character> base = new ArrayList<Character>();
		base.addAll(set);
		int size = base.size();

		Comb c = new Comb(10, size);
		List<int[]> cc = c.calculateComb();

		Combination cb = new Combination(size, 0);
		List<int[]> cbs = cb.generateCom();

		int max = -1;
		for (int i = 0; i < cc.size(); i++) {
			int[] _cc = toArr(cc.get(i), size);

			for (int j = 0; j < cbs.size(); j++) {
				int[] _cbs = cbs.get(j);
				int[] tp = new int[size];
				for (int k = 0; k < size; k++) {
					tp[k] = _cc[_cbs[k]];

				}

				String _str1 = str1;
				String _str2 = str2;
				for (int m = 0; m < size; m++) {
					_str1 = _str1.replace(base.get(m), Integer.toString(tp[m])
							.charAt(0));
					_str2 = _str2.replace(base.get(m), Integer.toString(tp[m])
							.charAt(0));
				}

				if (_str1.charAt(0) == '0' || _str2.charAt(0) == '0') {
					continue;
				}

				int val1 = Integer.parseInt(_str1);
				int val2 = Integer.parseInt(_str2);

				if (isSquare(val1) && isSquare(val2)) {
					if (val1 > max) {
						max = val1;
					}
					if (val2 > max) {
						max = val2;
					}
					System.out.println(max);
				}
			}
		}
		return max;
	}

	private boolean isSquare(int val) {
		int _val = (int) Math.sqrt(val);
		return _val * _val == val;
	}

	private int[] toArr(int[] arr, int size) {
		int[] ret = new int[size];

		int i = 0;
		for (int j = 0; j < arr.length; j++) {
			if (arr[j] == 1) {
				ret[i++] = j;
			}
		}

		return ret;
	}

	boolean isReverse(String str, String reverse) {
		assert (str.length() == reverse.length());

		for (int i = 0; i < str.length(); i++) {
			if (reverse.charAt(str.length() - 1 - i) != str.charAt(i)) {
				return false;
			}
		}
		return true;
	}

	public String getSortStr(String str) {
		char[] chars = new char[str.length()];
		str.getChars(0, str.length(), chars, 0);
		Arrays.sort(chars);
		return new String(chars);
	}

	List<String> readStrs() {
		List<String> ret = new ArrayList<String>();
		try {

			BufferedReader reader = new BufferedReader(new InputStreamReader(
					new FileInputStream(PATH), "utf8"));
			String str = "";
			while ((str = reader.readLine()) != null) {
				List<String> dataList = splitStrs(str);
				ret.addAll(dataList);
			}

			reader.close();

		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return ret;

	}

	List<String> splitStrs(String str) {
		List<String> ret = new ArrayList<String>();

		StringTokenizer tk = new StringTokenizer(str);
		while (tk.hasMoreElements()) {
			String s = tk.nextToken(",");
			ret.add(s.substring(s.indexOf("\"") + 1, s.lastIndexOf("\"")));
		}
		return ret;
	}

	/**
	 * 排列
	 * 
	 * @author suc
	 *
	 */
	public static class Combination {
		private int[] startArr;

		public Combination(int size) {

			this(size, 1);
		}

		public Combination(int size, int startNum) {
			startArr = new int[size];
			for (int i = 0; i < size; i++) {
				startArr[i] = i + startNum;
			}
		}

		public List<int[]> generateCom() {
			List<int[]> ret = new ArrayList<int[]>();

			ret.add(Arrays.copyOf(startArr, startArr.length));

			while (true) {

				int lastAsc = findLastAsc(startArr);

				if (lastAsc == -1) {
					break;
				}

				int lasBigThanAsc = findBigThanAsc(startArr, lastAsc);

				exchangeEach(lastAsc, lasBigThanAsc, startArr);

				ret.add(Arrays.copyOf(startArr, startArr.length));
			}

			return ret;
		}

		private int findBigThanAsc(int[] startArr2, int lastAsc) {
			int i = 0;
			for (i = startArr2.length - 1; i > lastAsc; i--) {
				if (startArr2[i] > startArr2[lastAsc]) {
					return i;
				}
			}

			assert (i > lastAsc);
			return i;
		}

		private void exchangeEach(int lastAsc, int lasBigThanAsc,
				int[] startArr2) {

			int temp = startArr2[lastAsc];
			startArr2[lastAsc] = startArr2[lasBigThanAsc];
			startArr2[lasBigThanAsc] = temp;

			int[] sortArr = getCopyArr(lastAsc + 1, startArr2);

			for (int i = 0; i < sortArr.length / 2; i++) {

				temp = sortArr[sortArr.length - 1 - i];
				sortArr[sortArr.length - 1 - i] = sortArr[i];
				sortArr[i] = temp;
			}

			for (int i = lastAsc + 1; i < startArr2.length; i++) {
				startArr2[i] = sortArr[i - lastAsc - 1];
			}
		}

		private int[] getCopyArr(int start, int[] startArr2) {

			int[] ret = new int[startArr2.length - start];
			for (int i = start; i < startArr2.length; i++) {
				ret[i - start] = startArr2[i];
			}

			return ret;
		}

		private int findLastAsc(int[] startArr2) {
			for (int i = startArr2.length - 1; i > 0; i--) {
				if (startArr2[i] > startArr2[i - 1]) {
					return i - 1;
				}
			}
			return -1;
		}

		public static long getIntVal(int[] arr) {
			long sum = arr[0];

			for (int i = 1; i < arr.length; i++) {
				sum = sum * 10 + arr[i];
			}

			return sum;

		}
	}

	/**
	 * 组合
	 * 
	 * @author suc
	 *
	 */
	public static class Comb {

		private int n;
		private int p;

		public Comb(int n, int p) {
			this.n = n;
			this.p = p;
		}

		public List<int[]> calculateComb() {

			assert (p < n && p > 0);

			List<int[]> ret = new ArrayList<int[]>();

			int[] arrs = new int[n];
			for (int i = 0; i < p; i++) {
				arrs[i] = 1;
			}

			ret.add(Arrays.copyOf(arrs, arrs.length));

			for (;;) {

				boolean find = findNext(arrs);
				ret.add(Arrays.copyOf(arrs, arrs.length));
				if (!find) {
					break;
				}

			}

			return ret;

		}

		private boolean findNext(int[] arrs) {

			int count = 0;
			int find = -1;

			for (int i = 0; i < arrs.length - 1; i++) {
				if (arrs[i] == 1) {
					count++;
				}

				if (arrs[i] == 1 && arrs[i + 1] == 0) {

					int tmp = arrs[i + 1];
					arrs[i + 1] = arrs[i];
					arrs[i] = tmp;
					find = i;
					break;
				}

			}

			count--;

			for (int i = 0; i < find; i++) {
				if (i < count) {
					arrs[i] = 1;
				} else {
					arrs[i] = 0;
				}
			}

			return !(find == -1);
		}

	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值