diff --git a/AdventOfCodeData b/AdventOfCodeData index e54ed85..576bbc8 160000 --- a/AdventOfCodeData +++ b/AdventOfCodeData @@ -1 +1 @@ -Subproject commit e54ed856a1de0eb95b8afc00f0c2256b1b3892ee +Subproject commit 576bbc83b60aaebc010c3e6e520e0dc1ec9f8257 diff --git a/src/main/java/com/example/adventofcode/year2025/day09/MovieTheater.java b/src/main/java/com/example/adventofcode/year2025/day09/MovieTheater.java new file mode 100644 index 0000000..d2681f0 --- /dev/null +++ b/src/main/java/com/example/adventofcode/year2025/day09/MovieTheater.java @@ -0,0 +1,117 @@ +package com.example.adventofcode.year2025.day09; + +import java.awt.*; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static com.example.adventofcode.utils.FileUtils.readLines; + +public class MovieTheater { + private static final String FILENAME = "AdventOfCodeData/2025/day09/input"; + private static final String EXAMPLE_FILENAME = "AdventOfCodeData/2025/day09/example_input"; + + public static void main(String[] args) throws IOException { + System.out.println(calculateLargestAreaBruteForce(EXAMPLE_FILENAME)); + System.out.println(calculateLargestAreaBruteForce(FILENAME)); + System.out.println(calculateLargestArea(EXAMPLE_FILENAME)); + System.out.println(calculateLargestArea(FILENAME)); + System.out.println(calculateLargestAreaInsideOfPolygon(EXAMPLE_FILENAME)); + System.out.println(calculateLargestAreaInsideOfPolygon(FILENAME)); + } + + + record Point(int x, int y) { + } + + public static long calculateLargestAreaBruteForce(final String filename) throws IOException { + List lines = readLines(filename); + List points = parsePoints(lines); + + long maxArea = 0; + for (Point p1 : points) { + for (Point p2 : points) { + long area = (long) (Math.abs(p1.x - p2.x) + 1) * (Math.abs(p1.y - p2.y) + 1); + if (area > maxArea) { + maxArea = area; + } + } + } + + return maxArea; + } + + public static long calculateLargestArea(final String filename) throws IOException { + List lines = readLines(filename); + List points = parsePoints(lines); + + Set rectangles = calculateRectangles(points); + + long maxArea = 0; + for (Rectangle rectangle : rectangles) { + long area = (long) (rectangle.getHeight() + 1) * (long) (rectangle.getWidth() + 1); + if (area > maxArea) { + maxArea = area; + } + } + + return maxArea; + } + + public static long calculateLargestAreaInsideOfPolygon(final String filename) throws IOException { + List lines = readLines(filename); + List points = parsePoints(lines); + + Polygon polygon = calculatePolygon(points); + Set rectangles = calculateRectangles(points); + + long maxArea = 0; + for (Rectangle rectangle : rectangles) { + long area = (long) (rectangle.getHeight() + 1) * (long) (rectangle.getWidth() + 1); + + if (polygon.contains( + rectangle.getX() + 1, + rectangle.getY() + 1, + rectangle.getWidth() - 1, + rectangle.getHeight() - 1) && area > maxArea) { + maxArea = area; + } + } + + return maxArea; + } + + private static List parsePoints(List lines) { + List points = new ArrayList<>(); + for (String line : lines) { + String[] p = line.split(","); + points.add(new Point(Integer.parseInt(p[0]), Integer.parseInt(p[1]))); + } + return points; + } + + private static Set calculateRectangles(List points) { + Set rectangles = new HashSet<>(); + for (Point p1 : points) { + for (Point p2 : points) { + rectangles.add(new Rectangle( + Math.min(p1.x, p2.x), + Math.min(p1.y, p2.y), + Math.abs(p1.x - p2.x), + Math.abs(p1.y - p2.y) + )); + } + } + return rectangles; + } + + private static Polygon calculatePolygon(List points) { + Polygon polygon = new Polygon(); + for (Point p : points) { + polygon.addPoint(p.x, p.y); + } + return polygon; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/adventofcode/year2025/day11/Reactor.java b/src/main/java/com/example/adventofcode/year2025/day11/Reactor.java new file mode 100644 index 0000000..7a0de12 --- /dev/null +++ b/src/main/java/com/example/adventofcode/year2025/day11/Reactor.java @@ -0,0 +1,102 @@ +package com.example.adventofcode.year2025.day11; + +import java.io.IOException; +import java.util.*; + +import static com.example.adventofcode.utils.FileUtils.readLines; + +public class Reactor { + private static final String FILENAME = "AdventOfCodeData/2025/day11/input"; + private static final String EXAMPLE_FILENAME = "AdventOfCodeData/2025/day11/example_input"; + private static final String EXAMPLE_FILENAME2 = "AdventOfCodeData/2025/day11/example_input2"; + + public static void main(String[] args) throws IOException { + System.out.println(countWaysOut(EXAMPLE_FILENAME)); + System.out.println(countWaysOut(FILENAME)); + System.out.println(countWaysOutThroughNodesSubset(EXAMPLE_FILENAME2)); + System.out.println(countWaysOutThroughNodesSubset(FILENAME)); + } + + record NodeWithPaths(String next, List path) { + } + + record NodeCache(String next, boolean seenDac, boolean seenFft) { + } + + public static long countWaysOut(final String filename) throws IOException { + List lines = readLines(filename); + Map> nodes = parseNodes(lines); + + Deque queue = new ArrayDeque<>(); + for (String node : nodes.get("you")) { + queue.add(new NodeWithPaths(node, new ArrayList<>())); + } + + int count = 0; + while (!queue.isEmpty()) { + NodeWithPaths current = queue.poll(); + current.path.add(current.next); + + for (String neighbour : nodes.get(current.next)) { + if (neighbour.equals("out")) { + count++; + } else if (!current.path.contains(neighbour)) { + queue.add(new NodeWithPaths(neighbour, new ArrayList<>(current.path))); + } + } + } + + return count; + } + + public static long countWaysOutThroughNodesSubset(final String filename) throws IOException { + List lines = readLines(filename); + Map> nodes = parseNodes(lines); + + return countWaysOutThroughNodesSubset(new NodeCache("svr", false, false), nodes, new HashMap<>()); + } + + private static Map> parseNodes(List lines) { + Map> nodes = new HashMap<>(); + for (String line : lines) { + String[] targetingArray = line.split(":")[1].substring(1).split(" "); + List targeting = Arrays.asList(targetingArray); + + nodes.put(line.split(":")[0], targeting); + } + return nodes; + } + + private static long countWaysOutThroughNodesSubset(NodeCache node, Map> nodes, Map cache) { + String nodeName = node.next; + boolean seenDac = node.seenDac; + boolean seenFft = node.seenFft; + switch (nodeName) { + case "out" -> { + if (node.seenDac && node.seenFft) { + return 1; + } else { + return 0; + } + } + case "dac" -> seenDac = true; + case "fft" -> seenFft = true; + } + + long sumOut = 0; + for (String nextNode : nodes.get(nodeName)) { + sumOut += countWaysOutThroughNodesSubsetWithCache(new NodeCache(nextNode, seenDac, seenFft), nodes, cache); + } + return sumOut; + } + + private static long countWaysOutThroughNodesSubsetWithCache(NodeCache node, Map> nodes, Map cache) { + if (cache.containsKey(node)) { + return cache.get(node); + } + + long result = countWaysOutThroughNodesSubset(node, nodes, cache); + cache.put(node, result); + return result; + } +} diff --git a/src/test/java/com/example/adventofcode/year2025/day09/MovieTheaterTest.java b/src/test/java/com/example/adventofcode/year2025/day09/MovieTheaterTest.java new file mode 100644 index 0000000..1ab0936 --- /dev/null +++ b/src/test/java/com/example/adventofcode/year2025/day09/MovieTheaterTest.java @@ -0,0 +1,48 @@ +package com.example.adventofcode.year2025.day09; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MovieTheaterTest { + + private static Stream filepathsAndConnectionsAndExpectedLargestArea() { + return Stream.of( + Arguments.of("AdventOfCodeData/2025/day09/example_input", 50), + Arguments.of("AdventOfCodeData/2025/day09/input", 4769758290L) + ); + } + + @ParameterizedTest + @MethodSource("filepathsAndConnectionsAndExpectedLargestArea") + void calculateLargestAreaBruteForce(final String filename, + final long expectedLargestArea) throws IOException { + assertEquals(expectedLargestArea, MovieTheater.calculateLargestAreaBruteForce(filename)); + } + + @ParameterizedTest + @MethodSource("filepathsAndConnectionsAndExpectedLargestArea") + void calculateLargestArea(final String filename, + final long expectedLargestArea) throws IOException { + assertEquals(expectedLargestArea, MovieTheater.calculateLargestArea(filename)); + } + + private static Stream filepathsAndConnectionsAndExpectedLargestAreaInsideOfPolygon() { + return Stream.of( + Arguments.of("AdventOfCodeData/2025/day09/example_input", 24), + Arguments.of("AdventOfCodeData/2025/day09/input", 1588990708L) + ); + } + + @ParameterizedTest + @MethodSource("filepathsAndConnectionsAndExpectedLargestAreaInsideOfPolygon") + void calculateLargestAreaInsideOfPolygon(final String filename, + final long expectedLargestArea) throws IOException { + assertEquals(expectedLargestArea, MovieTheater.calculateLargestAreaInsideOfPolygon(filename)); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/adventofcode/year2025/day11/ReactorTest.java b/src/test/java/com/example/adventofcode/year2025/day11/ReactorTest.java new file mode 100644 index 0000000..cf32d31 --- /dev/null +++ b/src/test/java/com/example/adventofcode/year2025/day11/ReactorTest.java @@ -0,0 +1,41 @@ +package com.example.adventofcode.year2025.day11; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ReactorTest { + + private static Stream filepathsAndConnectionsAndExpectedWaysOut() { + return Stream.of( + Arguments.of("AdventOfCodeData/2025/day11/example_input", 5), + Arguments.of("AdventOfCodeData/2025/day11/input", 615) + ); + } + + @ParameterizedTest + @MethodSource("filepathsAndConnectionsAndExpectedWaysOut") + void countWaysOut(final String filename, + final long expectedWaysOut) throws IOException { + assertEquals(expectedWaysOut, Reactor.countWaysOut(filename)); + } + + private static Stream filepathsAndConnectionsAndExpectedWaysOutThroughNodesSubset() { + return Stream.of( + Arguments.of("AdventOfCodeData/2025/day11/example_input2", 2), + Arguments.of("AdventOfCodeData/2025/day11/input", 303012373210128L) + ); + } + + @ParameterizedTest + @MethodSource("filepathsAndConnectionsAndExpectedWaysOutThroughNodesSubset") + void countWaysOutThroughNodesSubset(final String filename, + final long expectedWaysOut) throws IOException { + assertEquals(expectedWaysOut, Reactor.countWaysOutThroughNodesSubset(filename)); + } +} \ No newline at end of file