Challenge 14
19/01/26 08:13
package net.p3consulting.so.challenges;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Challenge14 {
public static void main(final String[] args) {
final String classPath = System.getProperty("java.class.path", ".");
final String[] classPathElements = classPath.split(System.getProperty("path.separator"));
final File dir = new File(classPathElements[0]);
final Pattern pattern = Pattern.compile(".*/challenge14_\\d+.csv");
Arrays.stream(dir.listFiles()).sorted().forEach(
file -> {
String fileName = null;
try {
fileName = file.getCanonicalPath();
if (pattern.matcher(fileName).matches()) {
fileName = fileName.substring(fileName.lastIndexOf('/'));
System.out.println(fileName);
int[][] problems = readFile(fileName);
int totalValue = 0;
char status;
int start = -1;
boolean debug = false;
boolean problem = true;
Pattern pat = Pattern.compile("((C*DC*M)|(C*MC*D))C*L?");
for (int p = 0; p < problems.length; p++) {
int[] data = problems[p];
Arrays.sort(data);
final StringBuilder concatStatus = new StringBuilder("");
final Stack solStack = new Stack<>();
for (int i = 0; i < data.length - 1; i++) {
if (data[i] + 1 == data[i + 1])
status = 'C'; // (C)ontinuous
else if (data[i] == data[i + 1])
status = 'D'; // (D)uplicate
else if (data[i] + 2 == data[i + 1])
status = 'M'; // (M)issing
else if (
(data[i] - 1 == (i > 0 ? data[i - 1] : Integer.MAX_VALUE)) ||
(data[i] - 2 == (i > 0 ? data[i - 1] : Integer.MAX_VALUE))
)
status = 'L';
else
status = 'A'; // (A)ny other
concatStatus.append(status);
}
// the latest number classification is a special case since no next value to compare with
if ((data[data.length - 1] == data[data.length - 2] + 1) // C
|| (data[data.length - 1] == data[data.length - 2] + 2) // M
|| (data[data.length - 1] == data[data.length - 2]) // D
) {
concatStatus.append('L');
}
final String cs = concatStatus.toString();
if (debug)
System.out.println("\nconcatStatus '" + cs + "' " + Arrays.toString(data));
final Matcher m = pat.matcher(cs);
if (m.find()) {
int pos;
int maxPos;
int maxEnd;
int maxLen = Integer.MIN_VALUE;
do {
int startPos = m.start(0);
int endPos = m.end(0);
if (debug)
System.out.println("ID: " + (p + 1) + " @" + start + ", status: '" + cs
+ "' matches: "
+ m.start(0) + " to " + m.end(0) + " " +
cs.substring(m.start(0), m.end(0)));
int len = endPos - startPos;
if (len == maxLen) {
// push another solution
solStack.push(new int[]{startPos, endPos});
} else if (len > maxLen) {
// replace the solutions
solStack.clear();
solStack.push(new int[]{startPos, endPos});
maxLen = len;
}
pos = startPos + 1;
if (debug)
System.out.println("\tnext pos " + pos);
if (pos == Integer.MAX_VALUE)
break;
}
while (m.find(pos));
while (!solStack.empty()) {
int[] positions = solStack.pop();
maxPos = positions[0];
maxEnd = positions[1];
if (debug)
System.out.println("\tmax at " + maxPos + " to " + maxEnd);
int dupIdx = cs.substring(maxPos, maxEnd).indexOf('D');
int missIdx = cs.substring(maxPos, maxEnd).indexOf('M');
final List noise = new ArrayList<>();
for (int i = 0; i < data.length; i++) {
if (i < maxPos || i > maxEnd - 1)
noise.add(data[i]);
}
maxEnd--;
System.out.println("ID: " + (p + 1) +
" " + Arrays.toString(data) + "\n\tFrom " + data[maxPos] + " to " + data[maxEnd]
+ " " + (debug ? cs + " " : "")
+ ", sum: " + (data[maxPos] + data[maxEnd])
+ ", missing: " + ((missIdx == -1) ? "" : data[maxPos + missIdx] + 1)
+ ", duplicate: " + ((dupIdx == -1) ? "" : data[maxPos + dupIdx])
+ ", noise: " + noise
);
totalValue += data[maxPos] + data[maxEnd];
}
} else {
System.out.println("ID: " + (p + 1) + " @" + start + ", status: '" + cs + "' DOESN'T matches.");
}
} // p
System.out.println("Total: " + totalValue);
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
);
}
private static int[][] readFile(final String filePath) {
final InputStream is = Challenge14.class.getResourceAsStream(filePath);
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
String content;
int[][] result;
try {
byte[] byteChunk = new byte[4096];
int n;
while ((n = is.read(byteChunk)) > 0) {
baos.write(byteChunk, 0, n);
}
content = baos.toString(StandardCharsets.UTF_8.name());
String[] lines = content.split("\n");
result = new int[lines.length][];
int resIdx = 0;
for (String line : lines) {
String[] numbers = line.split(",\s*");
int[] numLine = new int[numbers.length];
int idx = 0;
for (String num : numbers) numLine[idx++] = Integer.valueOf(num);
result[resIdx++] = numLine;
}
} catch (final IOException e) {
throw new RuntimeException(e);
}
return result;
}
}
/*
PATTERN( ( (C*DC*M) | (C*MC*D) ) C* L? )
DEFINE
C AS val + 1 = NEXT(val), -- Continuous
D AS val = NEXT(val), -- Duplicate
M AS val + 2 = NEXT(val), -- Missing
L AS val - 1 = PREV(val) OR val - 2 = PREV(val) -- Latest
*/