diff --git a/2022/README.md b/2022/README.md index b0c0ae510fcdb07dd2c409d0ffc6b297f8a23ade..6f326789f82988261614294e40ced7b793e0dd02 100644 --- a/2022/README.md +++ b/2022/README.md @@ -258,7 +258,12 @@ Well... I'm going to take the part 2 code in a (very) slightly different directi ### Part 1 The subproblems are -- ... +- Determine whether the head and tail are touching +- Determine what direction the tail should move +- Both of the previous subproblems include the subproblem of finding the distance between the head and tail along each + dimension +- Track which locations the tail has visited +- Count those locations ### Part 2 diff --git a/2022/src/main/java/edu/unl/cse/bohn/year2022/Day9.java b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day9.java new file mode 100644 index 0000000000000000000000000000000000000000..ecb6ad8474b61b1cb8fad324417c92fdc5774e1d --- /dev/null +++ b/2022/src/main/java/edu/unl/cse/bohn/year2022/Day9.java @@ -0,0 +1,100 @@ +package edu.unl.cse.bohn.year2022; + +import edu.unl.cse.bohn.Puzzle; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.IntStream; + +@SuppressWarnings("unused") +public class Day9 extends Puzzle { + public Day9(boolean isProductionReady) { + super(isProductionReady); + sampleData = """ + R 4 + U 4 + L 3 + D 1 + R 4 + D 1 + L 5 + R 2"""; + } + + @Override + public long computePart1(List<String> data) { + List<Character> movements = extractIndividualMovements(data); + int totalDistanceTravelled = movements.size(); + boolean[][] visitedLocations = new boolean[2 * totalDistanceTravelled][2 * totalDistanceTravelled]; + Arrays.stream(visitedLocations).forEach(row -> Arrays.fill(row, false)); + Position head = new Position(totalDistanceTravelled, totalDistanceTravelled); + Position tail = new Position(totalDistanceTravelled, totalDistanceTravelled); + visitedLocations[tail.row][tail.column] = true; + for (Character movement : movements) { + head = switch (movement) { + case 'R' -> new Position(head.row, head.column + 1); + case 'L' -> new Position(head.row, head.column - 1); + case 'U' -> new Position(head.row + 1, head.column); + case 'D' -> new Position(head.row - 1, head.column); + default -> throw new IllegalStateException("Unrecognized movement: " + movement); + }; + tail = tail.moveToward(head); + visitedLocations[tail.row][tail.column] = true; + } + return countVisitedLocations(visitedLocations); + } + + @Override + public long computePart2(List<String> data) { + return 0; + } + + private record Position(int row, int column) { + public Position moveToward(Position destination) { + int rowDifference = destination.row - this.row; + int columnDifference = destination.column - this.column; + if (Math.abs(rowDifference) <= 1 && Math.abs(columnDifference) <= 1) { + return this; + } else if (rowDifference == 0) { + return new Position(row, (columnDifference > 0) ? column + 1 : column - 1); + } else if (columnDifference == 0) { + return new Position((rowDifference > 0) ? row + 1 : row - 1, column); + } else { + return new Position( + (rowDifference > 0) ? row + 1 : row - 1, + (columnDifference > 0) ? column + 1 : column - 1 + ); + } + } + } + + private List<Character> extractIndividualMovements(List<String> data) { + List<Character> movements = new LinkedList<>(); + for (String datum : data) { + char direction = datum.charAt(0); + int distance = Integer.parseInt(datum.substring(2)); + IntStream.range(0, distance).mapToObj(i -> direction).forEach(movements::add); + } + return movements; + } + + private long countVisitedLocations(boolean[][] visitedLocations) { + int numberOfVisitedLocations = 0; + for (boolean[] visitedRow : visitedLocations) { + for (boolean visitedLocation : visitedRow) { + numberOfVisitedLocations += visitedLocation ? 1 : 0; + } + } + return numberOfVisitedLocations; + } + + private void printLocations(boolean[][] locations) { + for (boolean[] row : locations) { + for (boolean location : row) { + System.out.print(location ? '#' : '.'); + } + System.out.println(); + } + } +}