diff --git a/2022/README.md b/2022/README.md index 28c46de9430e425ce27ea2c237c4980c24402eac..a081fdf5cbca4d05ffbbeff11d10abb919d28fd1 100644 --- a/2022/README.md +++ b/2022/README.md @@ -49,5 +49,21 @@ Where we parameterized the commonality on Day 1, today we'll simply extract the ## Day 3 +- [The problem](https://adventofcode.com/2022/day/3) +- [The solution](src/main/java/edu/unl/cse/bohn/year2022/Day3.java) + +### Part 1 + +The subproblems are +- Determine an item's priority +- For each knapsack, determine which items are in each compartment + - Assume an even non-zero number of items +- For each knapsack, determine which item is common to both compartments + - Assume there is exactly one item that is common + - *Aha!* one of the knapsacks in the sample data has 'L' as a common item, twice +- Sum the priorities of all the "common items" + +#Day 4 + (coming soon) diff --git a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day3.java b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day3.java new file mode 100644 index 0000000000000000000000000000000000000000..2e21cef5ccda4ba9174058b92b54e5e751967478 --- /dev/null +++ b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day3.java @@ -0,0 +1,98 @@ +package edu.unl.cse.bohn.year2022; + +import edu.unl.cse.bohn.Puzzle; + +import java.util.Iterator; +import java.util.List; + +@SuppressWarnings("unused") +public class Day3 extends Puzzle { + public Day3(boolean isProductionReady) { + super(isProductionReady); + //noinspection SpellCheckingInspection + sampleData = """ + vJrwpWtwJgWrhcsFMMfFFhFp + jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL + PmmdzqPrVvPwwTWBwg + wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn + ttgJtRGJQctTZtZT + CrZsJsPPZsGzwwsLwLmpwMDw"""; + } + + @Override + public long computePart1(List<String> data) { + long prioritySum = 0; + for (String datum : data) { + String compartment1 = datum.substring(0, datum.length() / 2); + String compartment2 = datum.substring(datum.length() / 2); + if (compartment1.length() != compartment2.length()) { + throw new IllegalArgumentException("A knapsack has an odd number of items; cannot divide evenly " + + "between compartments: " + compartment1 + " " + compartment2); + } + char commonItem = getCommonItem(compartment1, compartment2); + prioritySum += getPriority(commonItem); + } + return prioritySum; + } + + @Override + public long computePart2(List<String> data) { + return 0; + } + + private char getCommonItem(String firstCompartment, String secondCompartment) { + Character commonItem = null; + List<Character> firstCompartmentItems = firstCompartment.chars().sorted().mapToObj(c -> (char) c).toList(); + List<Character> secondCompartmentItems = secondCompartment.chars().sorted().mapToObj(c -> (char) c).toList(); + Iterator<Character> firstCompartmentIterator = firstCompartmentItems.iterator(); + Iterator<Character> secondCompartmentIterator = secondCompartmentItems.iterator(); + Character firstItem = null; + Character secondItem = null; + // with the items sorted, we will advance through the items until we reach the end one of the compartments + while (firstCompartmentIterator.hasNext() || secondCompartmentIterator.hasNext()) { + firstItem = (firstItem == null && firstCompartmentIterator.hasNext()) ? + firstCompartmentIterator.next() : firstItem; + secondItem = (secondItem == null && secondCompartmentIterator.hasNext()) ? + secondCompartmentIterator.next() : secondItem; + if (commonItem == null && (firstItem == null || secondItem == null)) { + throw new IllegalArgumentException("Reached the end of a compartment among " + + firstCompartment + " and " + secondCompartment + " without finding a common item."); + } + else if (firstItem == secondItem) { + if (commonItem == null || commonItem == firstItem) { + commonItem = firstItem; + firstItem = null; + secondItem = null; + } else { + throw new IllegalStateException("Found a common item (" + firstItem + ") when one already exists " + + "(" + commonItem + ") for compartments " + firstCompartment + " and " + secondCompartment); + } + } else if (firstItem != null && secondItem != null) { + if (firstItem < secondItem) { + firstItem = null; + } else { + secondItem = null; + } + } else { // if we've gotten this far with a null item, then we just need to exhaust the remaining string + firstItem = null; + secondItem = null; + } + } + if (commonItem == null) { + throw new IllegalArgumentException("No common item found among " + + firstCompartment + " and " + secondCompartment); +// + firstCompartmentItems + " and " + secondCompartmentItems); + } + return commonItem; + } + + private int getPriority(char c) { + if ('a' <= c && c <= 'z') { + return (c - 'a' + 1); + } else if ('A' <= c && c <= 'Z') { + return (c - 'A' + 27); + } else { + throw new IllegalArgumentException("The character '" + c + "' is not a valid item."); + } + } +}