I use Java to earn money, even though I don’t really like working with it. Everything is so damn verbose. If you return to writing Java code within Emacs you’ll realize that a big chunk of the code you’re writing gets written by the IDE, e.g. imports. Static typing and object orientation has resulted in basically every object defining a separate interface which you need to memorize. It’s hard to write code without completion. Anyway, I decided to solve today’s Advent of Code riddles using Java.
First question. Your input is a list of strings. Each string has the form NAME-ID[CHECKSUM]. NAME consists of lowercase letters separated by dashes, ID is a number and CHECKSUM are the five most common letters in NAME, sorted by frequency with ties broken by alphabetical sorting. What is the sum of all the IDs where the CHECKSUM is correct?
This checksum is valid, for example and thus the sum would be 123:
zzzyyyxxxwwva-123[xyzwa]
The enjoyable part about this exercise was that I got to use Java 8 streams. Yay me!
import java.lang.*; import java.util.*; import java.util.regex.*; import java.util.stream.*; class Part1 { Scanner scanner = new Scanner(System.in); Pattern p = Pattern.compile("([a-z-]+)-([0-9]+)\\[([a-z]{5})\\]"); String readRoom() { return scanner.next(); } int readValidSectorId () { String room = readRoom(); Matcher m = p.matcher(room); if (m.matches()) { String name = m.group(1); int id = Integer.parseInt(m.group(2)); String checksum = m.group(3); // count the occurences of every character HashMap<Character, Integer> charMap = new HashMap<Character, Integer>(); for (Character c: name.toCharArray()) { if (charMap.containsKey(c)) { charMap.put(c, charMap.get(c) + 1); } else { charMap.put(c, 1); } } // get the five most common characters String computed = charMap.keySet().stream() .filter((elem) -> elem.charValue() != '-') .sorted(new Comparator<Character>() { @Override public int compare(Character a, Character b) { int r = charMap.get(b).compareTo(charMap.get(a)); if (r == 0) { return a.compareTo(b); } return r; } }) .limit(5) .map(Object::toString) .collect(Collectors.joining()); if (checksum.equals(computed)) { return id; } // System.out.println(computed + " != " + checksum); } return 0; } int sum () { int sum = 0; try { while (true) { sum += readValidSectorId(); } } catch (NoSuchElementException e) { // end of file } return sum; } public static void main(String args[]) { Part1 p = new Part1(); System.out.println("Sum: " + p.sum()); } }
Second question. For every string with correct CHECKSUM, rotate the letters in NAME by the ID. The example given shows how the letter `q` in a NAME with ID 343 would end up a `v`. To find the actual answer asked for in the question, grep the result for a line containing “north”.
import java.lang.*; import java.util.*; import java.util.regex.*; import java.util.stream.*; class Part2 { Scanner scanner = new Scanner(System.in); Pattern p = Pattern.compile("([a-z-]+)-([0-9]+)\\[([a-z]{5})\\]"); String readRoom() { return scanner.next(); } void readValidSectorId () { String room = readRoom(); Matcher m = p.matcher(room); if (m.matches()) { String name = m.group(1); int id = Integer.parseInt(m.group(2)); String checksum = m.group(3); // count the occurences of every character HashMap<Character, Integer> charMap = new HashMap<Character, Integer>(); for (Character c: name.toCharArray()) { if (charMap.containsKey(c)) { charMap.put(c, charMap.get(c) + 1); } else { charMap.put(c, 1); } } // get the five most common characters String computed = charMap.keySet().stream() .filter((elem) -> elem.charValue() != '-') .sorted(new Comparator<Character>() { @Override public int compare(Character a, Character b) { int r = charMap.get(b).compareTo(charMap.get(a)); if (r == 0) { return a.compareTo(b); } return r; } }) .limit(5) .map(Object::toString) .collect(Collectors.joining()); if (checksum.equals(computed)) { // do the rotating String s = name.chars() .map(c -> { if (c == '-') { return ' '; } else { return ((c + id - 'a') % 26 + 'a'); } }) .mapToObj(c -> Character.toString((char)c)) .collect(Collectors.joining()); System.out.println(room + " = " + s); } } } void read () { try { while (true) { readValidSectorId(); } } catch (NoSuchElementException e) { // end of file } } public static void main(String args[]) { Part2 p = new Part2(); p.read(); } }
#Java #Advent of Code #Programming