-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathproblem170.pizza
148 lines (130 loc) · 4.18 KB
/
problem170.pizza
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import net.sf.pizzacompiler.util.Vector;
public class problem170 {
public static void main(String[] args) {
long bestResult = 0L;
for (int i = 3; i < 100; i += 3) {
if (i % 11 == 0) {
continue;
}
bestResult = Math.max(bestResult, buildResult(i));
}
System.out.println(bestResult);
}
private static long[] allocator(int capacity) {
return new long[capacity];
}
private static long[] concatenatedProduct(long n, Vector<long> values, int omitFromEnd) {
long[] result = new long[values.size()];
for (int i = 0; i < values.size() - omitFromEnd; i++) {
result[i] = n * values.elementAt(i);
}
return result;
}
private static boolean isPandigital(String s) {
if (s.length() != 10) {
return false;
}
for (char ch = '0'; ch <= '9'; ch++) {
if (s.indexOf(ch) < 0) {
return false;
}
}
return true;
}
private static boolean isPandigital(long[] ns) {
return isPandigital(concatenateNumbers(ns));
}
private static String concatenateNumbers(long[] ns) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < ns.length; i++) {
buf.append(ns[i]);
}
return buf.toString();
}
private static boolean repeatsDigits(long[] ns) {
boolean[] uniqueDigits = new boolean[10];
for (int i = 0; i < ns.length; i++) {
long n = ns[i];
while (n > 0) {
int digit = (int)(n % 10);
if (uniqueDigits[digit]) {
return true;
}
uniqueDigits[digit] = true;
n /= 10;
}
}
return false;
}
private static long numberLength(long n) {
if (n == 0) {
return 1;
}
long count = 0;
while (n > 0) {
count++;
n /= 10;
}
return count;
}
private static long buildResult(long leadingValue) {
Vector<long> values = new Vector(10, allocator, 0L);
boolean[] usedDigits = new boolean[10];
long usedDigitsCount = 1L;
usedDigits[(int)(leadingValue % 10)] = true;
if (leadingValue >= 10) {
usedDigits[(int)(leadingValue / 10)] = true;
usedDigitsCount++;
}
return buildResult(leadingValue, values, usedDigitsCount, usedDigits, 0L);
}
private static long buildResult(long leadingValue, Vector<long> values, long usedDigitsCount, boolean[] usedDigits, long outputDigitCount) {
if (outputDigitCount > usedDigitsCount) {
return 0L;
}
if (repeatsDigits(concatenatedProduct(leadingValue, values, 1))) {
return 0L;
}
// Base case: All digits are used so check if we have a valid
// product.
if (usedDigitsCount == 10L) {
long[] product = concatenatedProduct(leadingValue, values, 0);
if (isPandigital(product)) {
return Long.parseLong(concatenateNumbers(product));
} else {
return 0L;
}
}
long bestResult = 0L;
// Recursive step 1: We could start a new number.
for (int i = 0; i < 10; i++) {
if (usedDigits[i]) {
continue;
}
values.addElement(i);
usedDigits[i] = true;
long recursiveResult = buildResult(leadingValue, values, usedDigitsCount + 1, usedDigits, outputDigitCount + numberLength(leadingValue * i));
bestResult = Math.max(bestResult, recursiveResult);
usedDigits[i] = false;
values.removeElementAt(values.size() - 1);
}
// Recursive step 2: We could continue the current number, if it
// exists and is not a leading zero.
if ((values.size() > 0) && (values.lastElement() != 0)) {
for (int i = 0; i < 10; i++) {
if (usedDigits[i]) {
continue;
}
long oldOutputLength = numberLength(leadingValue * values.lastElement());
values.setElementAt(values.lastElement() * 10 + i, values.size() - 1);
usedDigits[i] = true;
long newOutputLength = numberLength(leadingValue * values.lastElement());
long recursiveResult = buildResult(leadingValue, values, usedDigitsCount + 1, usedDigits, outputDigitCount - oldOutputLength + newOutputLength);
bestResult = Math.max(bestResult, recursiveResult);
usedDigits[i] = false;
values.setElementAt(values.lastElement() / 10, values.size() - 1);
}
}
return bestResult;
}
}