From 9696371481166d9034ec5923825527d1b37c4d4e Mon Sep 17 00:00:00 2001 From: pareronia <49491686+pareronia@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:12:30 +0100 Subject: [PATCH] AoC 2024 Day 12 - java --- README.md | 2 +- src/main/java/AoC2024_12.java | 170 ++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 src/main/java/AoC2024_12.java diff --git a/README.md b/README.md index ce483ef3..a23225fa 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | | ---| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | python3 | [✓](src/main/python/AoC2024_01.py) | [✓](src/main/python/AoC2024_02.py) | [✓](src/main/python/AoC2024_03.py) | [✓](src/main/python/AoC2024_04.py) | [✓](src/main/python/AoC2024_05.py) | [✓](src/main/python/AoC2024_06.py) | [✓](src/main/python/AoC2024_07.py) | [✓](src/main/python/AoC2024_08.py) | [✓](src/main/python/AoC2024_09.py) | [✓](src/main/python/AoC2024_10.py) | [✓](src/main/python/AoC2024_11.py) | [✓](src/main/python/AoC2024_12.py) | | | | | | | | | | | | | | -| java | [✓](src/main/java/AoC2024_01.java) | [✓](src/main/java/AoC2024_02.java) | [✓](src/main/java/AoC2024_03.java) | [✓](src/main/java/AoC2024_04.java) | [✓](src/main/java/AoC2024_05.java) | [✓](src/main/java/AoC2024_06.java) | [✓](src/main/java/AoC2024_07.java) | [✓](src/main/java/AoC2024_08.java) | | [✓](src/main/java/AoC2024_10.java) | [✓](src/main/java/AoC2024_11.java) | | | | | | | | | | | | | | | +| java | [✓](src/main/java/AoC2024_01.java) | [✓](src/main/java/AoC2024_02.java) | [✓](src/main/java/AoC2024_03.java) | [✓](src/main/java/AoC2024_04.java) | [✓](src/main/java/AoC2024_05.java) | [✓](src/main/java/AoC2024_06.java) | [✓](src/main/java/AoC2024_07.java) | [✓](src/main/java/AoC2024_08.java) | | [✓](src/main/java/AoC2024_10.java) | [✓](src/main/java/AoC2024_11.java) | [✓](src/main/java/AoC2024_12.java) | | | | | | | | | | | | | | | rust | [✓](src/main/rust/AoC2024_01/src/main.rs) | [✓](src/main/rust/AoC2024_02/src/main.rs) | [✓](src/main/rust/AoC2024_03/src/main.rs) | [✓](src/main/rust/AoC2024_04/src/main.rs) | [✓](src/main/rust/AoC2024_05/src/main.rs) | [✓](src/main/rust/AoC2024_06/src/main.rs) | [✓](src/main/rust/AoC2024_07/src/main.rs) | [✓](src/main/rust/AoC2024_08/src/main.rs) | | | | | | | | | | | | | | | | | | diff --git a/src/main/java/AoC2024_12.java b/src/main/java/AoC2024_12.java new file mode 100644 index 00000000..f71288c1 --- /dev/null +++ b/src/main/java/AoC2024_12.java @@ -0,0 +1,170 @@ +import static com.github.pareronia.aoc.IntegerSequence.Range.range; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.ToIntBiFunction; + +import com.github.pareronia.aoc.Grid.Cell; +import com.github.pareronia.aoc.Utils; +import com.github.pareronia.aoc.geometry.Direction; +import com.github.pareronia.aoc.graph.BFS; +import com.github.pareronia.aoc.solution.Sample; +import com.github.pareronia.aoc.solution.Samples; +import com.github.pareronia.aoc.solution.SolutionBase; + +public final class AoC2024_12 extends SolutionBase, Integer, Integer> { + + private static final List> CORNER_DIRS = List.of( + List.of(Direction.LEFT_AND_UP, Direction.LEFT, Direction.UP), + List.of(Direction.RIGHT_AND_UP, Direction.RIGHT, Direction.UP), + List.of(Direction.RIGHT_AND_DOWN, Direction.RIGHT, Direction.DOWN), + List.of(Direction.LEFT_AND_DOWN, Direction.LEFT, Direction.DOWN) + ); + + private AoC2024_12(final boolean debug) { + super(debug); + } + + public static AoC2024_12 create() { + return new AoC2024_12(false); + } + + public static AoC2024_12 createDebug() { + return new AoC2024_12(true); + } + + @Override + protected List parseInput(final List inputs) { + return inputs; + } + + private int solve( + final List input, + final ToIntBiFunction> count + ) { + final Map> plotsByPlant = new HashMap<>(); + range(input.size()).forEach(r -> + range(input.get(r).length()).forEach(c -> + plotsByPlant + .computeIfAbsent(input.get(r).charAt(c), k -> new HashSet<>()) + .add(Cell.at(r, c)))); + final Iterator> regions = new Iterator<>() { + final Iterator keys = plotsByPlant.keySet().iterator(); + char key = keys.next(); + Set allPlotsWithPlant = plotsByPlant.get(key); + + @Override + public Set next() { + if (allPlotsWithPlant.isEmpty()) { + key = keys.next(); + allPlotsWithPlant = plotsByPlant.get(key); + } + final Set region = BFS.floodFill( + allPlotsWithPlant.iterator().next(), + cell -> cell.capitalNeighbours() + .filter(allPlotsWithPlant::contains)); + allPlotsWithPlant.removeAll(region); + return region; + } + + @Override + public boolean hasNext() { + return !allPlotsWithPlant.isEmpty() || keys.hasNext(); + } + }; + return Utils.stream(regions) + .mapToInt(region -> region.stream() + .mapToInt(plot -> count.applyAsInt(plot, region) * region.size()) + .sum()) + .sum(); + } + + @Override + public Integer solvePart1(final List input) { + final ToIntBiFunction> countEdges + = (plot, region) -> (4 - (int) plot.capitalNeighbours() + .filter(region::contains) + .count()); + return solve(input, countEdges); + } + + @Override + public Integer solvePart2(final List input) { + final Set matches = Set.of( + new int[] {0, 0, 0}, new int[] {1, 0, 0}, new int[] {0, 1, 1}); + final ToIntBiFunction> countCorners + = (plot, region) -> ((int) CORNER_DIRS.stream() + .filter(d -> { + final int[] test = range(3).intStream() + .map(i -> region.contains(plot.at(d.get(i))) ? 1 : 0) + .toArray(); + return matches.stream().anyMatch(m -> Arrays.equals(m, test)); + }) + .count()); + return solve(input, countCorners); + } + + @Override + @Samples({ + @Sample(method = "part1", input = TEST1, expected = "140"), + @Sample(method = "part1", input = TEST2, expected = "772"), + @Sample(method = "part1", input = TEST3, expected = "1930"), + @Sample(method = "part2", input = TEST1, expected = "80"), + @Sample(method = "part2", input = TEST2, expected = "436"), + @Sample(method = "part2", input = TEST3, expected = "1206"), + @Sample(method = "part2", input = TEST4, expected = "236"), + @Sample(method = "part2", input = TEST5, expected = "368"), + }) + public void samples() { + } + + public static void main(final String[] args) throws Exception { + AoC2024_12.create().run(); + } + + private static final String TEST1 = """ + AAAA + BBCD + BBCC + EEEC + """; + private static final String TEST2 = """ + OOOOO + OXOXO + OOOOO + OXOXO + OOOOO + """; + private static final String TEST3 = """ + RRRRIICCFF + RRRRIICCCF + VVRRRCCFFF + VVRCCCJFFF + VVVVCJJCFE + VVIVCCJJEE + VVIIICJJEE + MIIIIIJJEE + MIIISIJEEE + MMMISSJEEE + """; + private static final String TEST4 = """ + EEEEE + EXXXX + EEEEE + EXXXX + EEEEE + """; + private static final String TEST5 = """ + AAAAAA + AAABBA + AAABBA + ABBAAA + ABBAAA + AAAAAA + """; +} \ No newline at end of file