Problem 90
Cube digit pairs
Each of the six faces on a cube has a different digit (0 to 9) written on it; the same is done to a second cube. By placing the two cubes side-by-side in different positions we can form a variety of 2-digit numbers.
For example, the square number 64 could be formed:
![](https://projecteuler.net/project/images/p090.gif)
In fact, by carefully choosing the digits on both cubes it is possible to display all of the square numbers below one-hundred: 01, 04, 09, 16, 25, 36, 49, 64, and 81.
For example, one way this can be achieved is by placing {0, 5, 6, 7, 8, 9} on one cube and {1, 2, 3, 4, 8, 9} on the other cube.
However, for this problem we shall allow the 6 or 9 to be turned upside-down so that an arrangement like {0, 5, 6, 7, 8, 9} and {1, 2, 3, 4, 6, 7} allows for all nine square numbers to be displayed; otherwise it would be impossible to obtain 09.
In determining a distinct arrangement we are interested in the digits on each cube, not the order.
{1, 2, 3, 4, 5, 6} is equivalent to {3, 6, 4, 1, 2, 5}
{1, 2, 3, 4, 5, 6} is distinct from {1, 2, 3, 4, 5, 9}
But because we are allowing 6 and 9 to be reversed, the two distinct sets in the last example both represent the extended set {1, 2, 3, 4, 5, 6, 9} for the purpose of forming 2-digit numbers.
How many distinct arrangements of the two cubes allow for all of the square numbers to be displayed?
立方体数字对
在一个立方体的六个面上分别标上不同的数字(从0到9),对另一个立方体也如法炮制。将这两个立方体按不同的方向并排摆放,我们可以得到各种各样的两位数。
例如,平方数64可以通过这样摆放获得:
![](https://projecteuler.net/project/images/p090.gif)
事实上,通过仔细地选择两个立方体上的数字,我们可以摆放出所有小于100的平方数:01、04、09、16、25、36、49、64和81。
例如,其中一种方式就是在一个立方体上标上{0, 5, 6, 7, 8, 9},在另一个立方体上标上{1, 2, 3, 4, 8, 9}。
在这个问题中,我们允许将标有6或9的面颠倒过来互相表示,只有这样,如{0, 5, 6, 7, 8, 9}和{1, 2, 3, 4, 6, 7}这样本来无法表示09的标法,才能够摆放出全部九个平方数。
在考虑什么是不同的标法时,我们关注的是立方体上有哪些数字,而不关心它们的顺序。
{1, 2, 3, 4, 5, 6}等价于{3, 6, 4, 1, 2, 5}
{1, 2, 3, 4, 5, 6}不同于{1, 2, 3, 4, 5, 9}
但因为我们允许在摆放两位数时将6和9颠倒过来互相表示,这个例子中的两个不同的集合都可以代表拓展集{1, 2, 3, 4, 5, 6, 9}。
对这两个立方体有多少中不同的标法可以摆放出所有的平方数?
package projecteuler;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase;
public class Prj90 extends TestCase {
public void testHashCode() {
CubeDigitPairs pair = null;
CubeDigitPairs pair2 = null;
Set<Integer> lf = new HashSet<Integer>();
Set<Integer> rt = new HashSet<Integer>();
lf.addAll(Arrays.asList(0, 1, 2, 3, 4, 6));
rt.addAll(Arrays.asList(0, 5, 6, 7, 8, 9));
pair = new CubeDigitPairs(lf, rt);
pair2 = new CubeDigitPairs(rt, lf);
Set<CubeDigitPairs> set = new HashSet<Prj90.CubeDigitPairs>();
set.add(pair);
set.add(pair2);
assertTrue( pair.equals(pair2));
assertTrue( set.size() == 1);
}
public void testCubeDigitPairs() {
int count = 0;
Set<CubeDigitPairs> set = new HashSet<CubeDigitPairs>();
for (int i1 = 0; i1 <= 9; i1++) {
for (int i2 = i1 + 1; i2 <= 9; i2++) {
if (i2 == i1) {
continue;
}
for (int i3 = i2 + 1; i3 <= 9; i3++) {
if (i3 == i1 || i3 == i2) {
continue;
}
for (int i4 = i3 + 1; i4 <= 9; i4++) {
if (i4 == i1 || i4 == i2 || i4 == i3) {
continue;
}
for (int i5 = i4 + 1; i5 <= 9; i5++) {
if (i5 == i1 || i5 == i2 || i5 == i3 || i5 == i4) {
continue;
}
for (int i6 = i5 + 1; i6 <= 9; i6++) {
if (i6 == i1 || i6 == i2 || i6 == i3
|| i6 == i4 || i6 == i5) {
continue;
}
count++;
for (int j1 = 0; j1 <= 9; j1++) {
for (int j2 = j1 + 1; j2 <= 9; j2++) {
if (j2 == j1) {
continue;
}
for (int j3 = j2 + 1; j3 <= 9; j3++) {
if (j3 == j1 || j3 == j2) {
continue;
}
for (int j4 = j3 + 1; j4 <= 9; j4++) {
if (j4 == j1 || j4 == j2
|| j4 == j3) {
continue;
}
for (int j5 = j4 + 1; j5 <= 9; j5++) {
if (j5 == j1 || j5 == j2
|| j5 == j3
|| j5 == j4) {
continue;
}
for (int j6 = j5 + 1; j6 <= 9; j6++) {
if (j6 == j1
|| j6 == j2
|| j6 == j3
|| j6 == j4
|| j6 == j5) {
continue;
}
Set<Integer> lf = new HashSet<Integer>();
Set<Integer> rt = new HashSet<Integer>();
lf.addAll(Arrays
.asList(i1, i2,
i3, i4,
i5, i6));
rt.addAll(Arrays
.asList(j1, j2,
j3, j4,
j5, j6));
if (lf.size() != 6
|| rt.size() != 6) {
continue;
}
CubeDigitPairs pairs = new CubeDigitPairs(
lf, rt);
if (pairs
.checkCondition()) {
set.add(pairs);
}
}
}
}
}
}
}
}
}
}
}
}
}
for (CubeDigitPairs pair : set) {
System.out.println(pair.left.toString() + "|"
+ pair.right.toString());
}
System.out.println("count=" + set.size() + ",count=" + count);
}
public static class CubeDigitPairs {
public Set<Integer> left = new HashSet<Integer>();
public Set<Integer> right = new HashSet<Integer>();
public CubeDigitPairs(Set<Integer> left, Set<Integer> right) {
super();
this.left.clear();
for (int val : left) {
this.left.add(val);
}
this.right.clear();
for (int val : right) {
this.right.add(val);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((left == null) ? 0 : left.hashCode() + right.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CubeDigitPairs other = (CubeDigitPairs) obj;
return (left.equals(other.left) && right.equals(other.right))
| (left.equals(other.right) && right.equals(other.left));
}
public boolean checkCondition() {
// 01、04、09、16、25、36、49、64\81
boolean ok_01 = (left.contains(0) && right.contains(1))
|| left.contains(1) && right.contains(0);
boolean ok_04 = (left.contains(0) && right.contains(4))
|| left.contains(4) && right.contains(0);
boolean ok_09 = (left.contains(0) && right.contains(9))
|| left.contains(9) && right.contains(0);
ok_09 |= (left.contains(0) && right.contains(6))
|| left.contains(6) && right.contains(0);
boolean ok_16 = (left.contains(1) && right.contains(6))
|| left.contains(6) && right.contains(1);
ok_16 |= (left.contains(1) && right.contains(9))
|| left.contains(9) && right.contains(1);
boolean ok_25 = (left.contains(2) && right.contains(5))
|| left.contains(5) && right.contains(2);
boolean ok_36 = (left.contains(3) && right.contains(6))
|| left.contains(6) && right.contains(3);
ok_36 |= (left.contains(3) && right.contains(9))
|| left.contains(9) && right.contains(3);
boolean ok_49 = (left.contains(4) && right.contains(9))
|| left.contains(9) && right.contains(4);
ok_49 |= (left.contains(4) && right.contains(6))
|| left.contains(6) && right.contains(4);
boolean ok_64 = (left.contains(6) && right.contains(4))
|| left.contains(4) && right.contains(6);
ok_64 |= (left.contains(9) && right.contains(4))
|| left.contains(4) && right.contains(9);
boolean ok_81 = (left.contains(8) && right.contains(1))
|| left.contains(1) && right.contains(8);
return ok_01 && ok_04 && ok_09 && ok_16 && ok_25 && ok_36 && ok_49
&& ok_64 && ok_81;
}
}
}