diff --git a/2022/README.md b/2022/README.md index 9d7ef625411f9165b1be2b36985cd050aa573ed4..d6d1b75bffa14c401092015a271e84fb2dd5567a 100644 --- a/2022/README.md +++ b/2022/README.md @@ -336,7 +336,7 @@ I'm revisiting the signal strength code. - [The problem](https://adventofcode.com/2022/day/11) - [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day11.java) -Oof. This is a long description. Probably because the input is so verbose, and then you have the exmaple. +Oof. This is a long description. Probably because the input is so verbose, and then you have the example. ### Part 1 @@ -514,5 +514,36 @@ Then look for the shortest distance to the finish from the 'a' `Location`s. ## Day 13 +- [The problem](https://adventofcode.com/2022/day/13) +- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day13.java) + +### Part 1 + +The subproblems are +- Decode packets + - Pairs of packets, each on its own line, with pairs separated by blank lines + - A packet is a list + - A list consists of integers and lists +- Validate pairs of packets + 1. When two integers are in the same position in both lists, the lesser must occur in the first list + - If we encounter non-equal integers before anything else, we are done + - If we have equal integers, fewer than two integers, then advance deeper into the lists + 2. Convert a solitary integer to a list of only that integer + 3. When two lists are adjacent, compare their elements using rules 1-3 + - If integer comparison does not establish the validation, then compare list lengths + - If all integer pairs are equal then the shorter list must be the first list + - If we have lists of the same length with identical elements, then advance deeper into the containing lists + +### Part 2 + +The subproblems are +- Add the divider packets (trivial) +- Sort the packets +- Determine the indicies of the divider packets (using 1-based indexing) + +Since I created a `compareTo()` method as part of Part 1, Part 2 is easy. + +## Day 14 + (coming soon) diff --git a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day13.java b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day13.java new file mode 100644 index 0000000000000000000000000000000000000000..0d062227bec937a932523ff46faf8bccbe8036b8 --- /dev/null +++ b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day13.java @@ -0,0 +1,189 @@ +package edu.unl.cse.bohn.year2022; + +import edu.unl.cse.bohn.Puzzle; + +import java.util.LinkedList; +import java.util.List; + +@SuppressWarnings("unused") +public class Day13 extends Puzzle { + public Day13(boolean isProductionReady) { + super(isProductionReady); + sampleData = """ + [1,1,3,1,1] + [1,1,5,1,1] + + [[1],[2,3,4]] + [[1],4] + + [9] + [[8,7,6]] + + [[4,4],4,4] + [[4,4],4,4,4] + + [7,7,7,7] + [7,7,7] + + [] + [3] + + [[[]]] + [[]] + + [1,[2,[3,[4,[5,6,7]]]],8,9] + [1,[2,[3,[4,[5,6,0]]]],8,9]"""; + } + + public static final boolean verbose = false; + + @Override + public long computePart1(List<String> data) { + int index = 0; + List<Integer> pairsInCorrectOrder = new LinkedList<>(); + while (3 * index < data.size()) { + Element firstElement = new Element(data.get(3 * index)); + Element secondElement = new Element(data.get(3 * index + 1)); + index++; + if (firstElement.compareTo(secondElement) <= 0) { + pairsInCorrectOrder.add(index); + } + } + return pairsInCorrectOrder.stream().reduce(0, Integer::sum); + } + + @Override + public long computePart2(List<String> data) { + List<Element> packets = new LinkedList<>(); + String firstDividerPacket = "[[2]]"; + String secondDividerPacket = "[[6]]"; + packets.add(new Element(firstDividerPacket)); + packets.add(new Element(secondDividerPacket)); + for (String datum : data) { + if (datum.length() > 0) { + packets.add(new Element(datum)); + } + } + packets.sort(null); + int indexOfFirstDividerPacket = 0; + int indexOfSecondDividerPacket = 0; + int index = 1; + for (Element packet : packets) { + if (verbose) { + System.out.println(packet); + } + if (packet.toString().equals(firstDividerPacket)) { + indexOfFirstDividerPacket = index; + } + if (packet.toString().equals(secondDividerPacket)) { + indexOfSecondDividerPacket = index; + } + index++; + } + return (long) indexOfFirstDividerPacket * (long) indexOfSecondDividerPacket; + } + + private static class Element implements Comparable<Element> { + Integer integer; + List<Element> list; + + public Element(String data) { + if (data.charAt(0) != '[') { + integer = Integer.parseInt(data); + list = null; + } else if (data.equals("[]")) { + integer = null; + list = List.of(); + } else { + integer = null; + list = new LinkedList<>(); + // let us guarantee that *every* element has a comma after it + String workingData = data.substring(1, data.length() - 1) + ","; + while (workingData.length() > 0) { + int startIndex = 0; + int endIndex; + if (workingData.charAt(0) == '[') { // list + int numberOfSquareBrackets = 1; + endIndex = 1; + while (numberOfSquareBrackets > 0) { + if (workingData.charAt(endIndex) == '[') { + numberOfSquareBrackets++; + } + if (workingData.charAt(endIndex) == ']') { + numberOfSquareBrackets--; + } + endIndex++; + } + } else { // integer + endIndex = workingData.indexOf(','); + } + list.add(new Element(workingData.substring(startIndex, endIndex))); + workingData = workingData.substring(endIndex + 1); + } + } + } + + @Override + public String toString() { + if (integer != null) { + return integer.toString(); + } + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("["); + for (Element element : list) { + stringBuilder.append(element.toString()).append(","); + } + if (stringBuilder.length() > 1) { + stringBuilder.deleteCharAt(stringBuilder.lastIndexOf(",")); + } + stringBuilder.append("]"); + return stringBuilder.toString(); + } + + @Override + public int hashCode() { + // IntelliJ default + int result = integer != null ? integer.hashCode() : 0; + result = 31 * result + (list != null ? list.hashCode() : 0); + return result; + } + + @Override + public boolean equals(Object other) { + if (this == other) return true; + if (!(other instanceof Element element)) return false; + return this.compareTo((Element) other) == 0; + } + + @Override + public int compareTo(Element other) { + if (verbose) { + System.out.println("Compare " + this + " vs " + other); + } + int result = 0; + if (this.integer != null && other.integer != null) { + result = this.integer - other.integer; + } else if (this.integer == null && other.integer != null) { + result = this.compareTo(new Element("[" + other + "]")); + } else if (this.integer != null) { + result = new Element("[" + this + "]").compareTo(other); + } else { + int i = 0; + while (result == 0 && i < this.list.size() && i < other.list.size()) { + result = this.list.get(i).compareTo(other.list.get(i)); + i++; + } + if (result == 0) { + if (verbose) { + System.out.println("Comparing list length"); + } + result = this.list.size() - other.list.size(); + } + } + if (verbose && result != 0) { + System.out.println("Elements are " + (result > 0 ? "**not** " : "") + "in the correct order."); + } + return result; + } + } +}