From aa2ba61be0c3d9b07b0d67c3864a2e4f46f24011 Mon Sep 17 00:00:00 2001 From: pareronia <49491686+pareronia@users.noreply.github.com> Date: Fri, 22 Dec 2023 15:23:40 +0100 Subject: [PATCH] AoC 2023 Day 22 Part 2 - java --- README.md | 2 +- src/main/java/AoC2023_22.java | 159 +++++++++++++++++++++------------- 2 files changed, 101 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 7eb3d7ac..b067372f 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/AoC2023_01.py) | [✓](src/main/python/AoC2023_02.py) | [✓](src/main/python/AoC2023_03.py) | [✓](src/main/python/AoC2023_04.py) | [✓](src/main/python/AoC2023_05.py) | [✓](src/main/python/AoC2023_06.py) | [✓](src/main/python/AoC2023_07.py) | [✓](src/main/python/AoC2023_08.py) | [✓](src/main/python/AoC2023_09.py) | [✓](src/main/python/AoC2023_10.py) | [✓](src/main/python/AoC2023_11.py) | [✓](src/main/python/AoC2023_12.py) | [✓](src/main/python/AoC2023_13.py) | [✓](src/main/python/AoC2023_14.py) | [✓](src/main/python/AoC2023_15.py) | [✓](src/main/python/AoC2023_16.py) | [✓](src/main/python/AoC2023_17.py) | [✓](src/main/python/AoC2023_18.py) | [✓](src/main/python/AoC2023_19.py) | [✓](src/main/python/AoC2023_20.py) | [✓](src/main/python/AoC2023_21.py) | | | | | -| java | [✓](src/main/java/AoC2023_01.java) | [✓](src/main/java/AoC2023_02.java) | [✓](src/main/java/AoC2023_03.java) | [✓](src/main/java/AoC2023_04.java) | [✓](src/main/java/AoC2023_05.java) | [✓](src/main/java/AoC2023_06.java) | [✓](src/main/java/AoC2023_07.java) | [✓](src/main/java/AoC2023_08.java) | [✓](src/main/java/AoC2023_09.java) | [✓](src/main/java/AoC2023_10.java) | [✓](src/main/java/AoC2023_11.java) | [✓](src/main/java/AoC2023_12.java) | [✓](src/main/java/AoC2023_13.java) | [✓](src/main/java/AoC2023_14.java) | [✓](src/main/java/AoC2023_15.java) | [✓](src/main/java/AoC2023_16.java) | [✓](src/main/java/AoC2023_17.java) | [✓](src/main/java/AoC2023_18.java) | | [✓](src/main/java/AoC2023_20.java) | | | | | | +| java | [✓](src/main/java/AoC2023_01.java) | [✓](src/main/java/AoC2023_02.java) | [✓](src/main/java/AoC2023_03.java) | [✓](src/main/java/AoC2023_04.java) | [✓](src/main/java/AoC2023_05.java) | [✓](src/main/java/AoC2023_06.java) | [✓](src/main/java/AoC2023_07.java) | [✓](src/main/java/AoC2023_08.java) | [✓](src/main/java/AoC2023_09.java) | [✓](src/main/java/AoC2023_10.java) | [✓](src/main/java/AoC2023_11.java) | [✓](src/main/java/AoC2023_12.java) | [✓](src/main/java/AoC2023_13.java) | [✓](src/main/java/AoC2023_14.java) | [✓](src/main/java/AoC2023_15.java) | [✓](src/main/java/AoC2023_16.java) | [✓](src/main/java/AoC2023_17.java) | [✓](src/main/java/AoC2023_18.java) | | [✓](src/main/java/AoC2023_20.java) | | [✓](src/main/java/AoC2023_22.java) | | | | | rust | [✓](src/main/rust/AoC2023_01/src/main.rs) | [✓](src/main/rust/AoC2023_02/src/main.rs) | [✓](src/main/rust/AoC2023_03/src/main.rs) | [✓](src/main/rust/AoC2023_04/src/main.rs) | | [✓](src/main/rust/AoC2023_06/src/main.rs) | [✓](src/main/rust/AoC2023_07/src/main.rs) | [✓](src/main/rust/AoC2023_08/src/main.rs) | [✓](src/main/rust/AoC2023_09/src/main.rs) | | | | | | [✓](src/main/rust/AoC2023_15/src/main.rs) | [✓](src/main/rust/AoC2023_16/src/main.rs) | [✓](src/main/rust/AoC2023_17/src/main.rs) | [✓](src/main/rust/AoC2023_18/src/main.rs) | [✓](src/main/rust/AoC2023_19/src/main.rs) | | [✓](src/main/rust/AoC2023_21/src/main.rs) | | | | | diff --git a/src/main/java/AoC2023_22.java b/src/main/java/AoC2023_22.java index f10190a4..2b9489ae 100644 --- a/src/main/java/AoC2023_22.java +++ b/src/main/java/AoC2023_22.java @@ -1,10 +1,12 @@ -import static java.util.Comparator.comparing; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toSet; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -12,17 +14,14 @@ import com.github.pareronia.aoc.MutableBoolean; import com.github.pareronia.aoc.StringOps; import com.github.pareronia.aoc.StringOps.StringSplit; -import com.github.pareronia.aoc.geometry.Draw; import com.github.pareronia.aoc.geometry.Position; import com.github.pareronia.aoc.geometry3d.Cuboid; import com.github.pareronia.aoc.solution.Sample; import com.github.pareronia.aoc.solution.Samples; import com.github.pareronia.aoc.solution.SolutionBase; -import lombok.RequiredArgsConstructor; - public final class AoC2023_22 - extends SolutionBase, Integer, Integer> { + extends SolutionBase { private AoC2023_22(final boolean debug) { super(debug); @@ -37,40 +36,18 @@ public static AoC2023_22 createDebug() { } @Override - protected List parseInput(final List inputs) { - final ArrayList bricks = new ArrayList<>(); - for (final String line : inputs) { - final StringSplit split = StringOps.splitOnce(line, "~"); - final String[] xyz1 = split.left().split(","); - final String[] xyz2 = split.right().split(","); - bricks.add(new Cuboid( - Integer.parseInt(xyz1[0]), - Integer.parseInt(xyz2[0]), - Integer.parseInt(xyz1[1]), - Integer.parseInt(xyz2[1]), - Integer.parseInt(xyz1[2]), - Integer.parseInt(xyz2[2]) - )); - } - return bricks; + protected Stack parseInput(final List inputs) { + return Stack.fromInput(inputs); } @Override - public Integer solvePart1(final List bricks) { - final Stack stack = new Stack(bricks); - stack.sort(); - stack.display().forEach(this::log); - log(""); - Draw.draw(stack.getViewY(), '#', '.').forEach(this::log); - stack.stack(); - stack.sort(); - log(""); - Draw.draw(stack.getViewY(), '#', '.').forEach(this::log); + public Integer solvePart1(final Stack stack) { +// stack.display().forEach(this::log); +// log(""); +// Draw.draw(stack.getViewY(), '#', '.').forEach(this::log); + final Map> bricksByZ1 = stack.getBricksByZ1(); + final Map> bricksByZ2 = stack.getBricksByZ2(); int ans = 0; - final Map> bricksByZ1 = bricks.stream() - .collect(groupingBy(Cuboid::getZ1)); - final Map> bricksByZ2 = bricks.stream() - .collect(groupingBy(Cuboid::getZ2)); for (final int z : bricksByZ2.keySet()) { for (final Cuboid brick : bricksByZ2.get(z)) { final List supportees = bricksByZ1.getOrDefault(brick.getZ2() + 1, List.of()).stream() @@ -80,7 +57,6 @@ public Integer solvePart1(final List bricks) { ans++; continue; } -// System.out.println("hey"); boolean onlySupporter = false; for (final Cuboid supportee : supportees) { if (bricksByZ2.get(supportee.getZ1() - 1).stream() @@ -100,14 +76,51 @@ public Integer solvePart1(final List bricks) { } @Override - public Integer solvePart2(final List bricks) { - return 0; + public Integer solvePart2(final Stack stack) { + final Map> bricksByZ1 = stack.getBricksByZ1(); + final Map> bricksByZ2 = stack.getBricksByZ2(); + final Map> supportees = new HashMap<>(); + final Map> supporters = new HashMap<>(); + for (final Cuboid brick : stack.getBricks()) { + supportees.put(brick, bricksByZ1.getOrDefault(brick.getZ2() + 1, List.of()).stream() + .filter(b -> Cuboid.overlapX(b, brick) && Cuboid.overlapY(b, brick)) + .collect(toSet())); + log(() -> "%s supportees: %s".formatted(Stack.displayBrick(brick), Stack.displayBricks(supportees.get(brick)))); + supporters.put(brick, bricksByZ2.getOrDefault(brick.getZ1() - 1, List.of()).stream() + .filter(b -> Cuboid.overlapX(b, brick) && Cuboid.overlapY(b, brick)) + .collect(toSet())); + log(() -> "%s supporters: %s".formatted(Stack.displayBrick(brick), Stack.displayBricks(supporters.get(brick)))); + } + int ans = 0; + for (final Cuboid brick : stack.getBricks()) { + final Deque q = new ArrayDeque<>(); + final Set falling = new HashSet<>(); + falling.add(brick); + q.add(brick); + while (!q.isEmpty()) { + final Cuboid b = q.poll(); + log(() -> Stack.displayBrick(b)); + for (final Cuboid spee : supportees.get(b)) { + final Set sprs = supporters.get(spee); + if (!sprs.isEmpty() && sprs.stream().allMatch(s -> falling.contains(s))) { + if (!falling.contains(spee)) { + q.add(spee); + } + falling.add(spee); + } + } + log(() -> "Falling: %s".formatted(Stack.displayBricks(falling))); + } + falling.remove(brick); + ans += falling.size(); + } + return ans; } @Override @Samples({ @Sample(method = "part1", input = TEST, expected = "5"), -// @Sample(method = "part2", input = TEST, expected = "TODO"), + @Sample(method = "part2", input = TEST, expected = "7"), }) public void samples() { } @@ -116,18 +129,53 @@ public static void main(final String[] args) throws Exception { AoC2023_22.create().run(); } - @RequiredArgsConstructor - private final class Stack { + static final class Stack { private final List bricks; + + protected Stack(final List bricks) { + this.bricks = bricks; + } - public void sort() { - Collections.sort(bricks, - comparing(Cuboid::getZ1) - .thenComparing(comparing(Cuboid::getY1)) - .thenComparing(comparing(Cuboid::getX1)) - ); + public List getBricks() { + return bricks; + } + + public Map> getBricksByZ1() { + return bricks.stream().collect(groupingBy(Cuboid::getZ1)); + } + + public Map> getBricksByZ2() { + return bricks.stream().collect(groupingBy(Cuboid::getZ2)); + } + + public static Stack fromInput(final List inputs) { + final List bricks = new ArrayList<>(); + for (final String line : inputs) { + final StringSplit split = StringOps.splitOnce(line, "~"); + final String[] xyz1 = split.left().split(","); + final String[] xyz2 = split.right().split(","); + bricks.add(Cuboid.of( + Integer.parseInt(xyz1[0]), + Integer.parseInt(xyz2[0]), + Integer.parseInt(xyz1[1]), + Integer.parseInt(xyz2[1]), + Integer.parseInt(xyz1[2]), + Integer.parseInt(xyz2[2]) + )); + } + final Stack stack = new Stack(bricks); + stack.stack(); + return stack; } +// public void sort() { +// Collections.sort(bricks, +// comparing(Cuboid::getZ1) +// .thenComparing(comparing(Cuboid::getY1)) +// .thenComparing(comparing(Cuboid::getX1)) +// ); +// } +// public Set getViewY() { return bricks.stream() .flatMap(Cuboid::positions) @@ -143,7 +191,7 @@ private static Cuboid moveToZ(final Cuboid block, final int dz) { ); } - public boolean overlapsXY(final Collection cuboids,final Cuboid brick) { + private boolean overlapsXY(final Collection cuboids,final Cuboid brick) { return cuboids.stream() .anyMatch(c -> Cuboid.overlapX(c, brick) && Cuboid.overlapY(c, brick)); } @@ -160,14 +208,12 @@ public void stack() { .sorted() .filter(z -> z > 1) .forEach(z -> { -// log("z: %d".formatted(z)); final List list = new ArrayList<>(bricksByZ1.get(z)); for (final Cuboid brick : list) { if (!overlapsXY(bricksByZ2.getOrDefault(z - 1, List.of()), brick)) { bricksByZ1.getOrDefault(brick.getZ1(), new ArrayList<>()).remove(brick); bricksByZ2.getOrDefault(brick.getZ2(), new ArrayList<>()).remove(brick); final Cuboid m = moveToZ(brick, -1); -// log("move: %s -> %s".formatted(displayBrick(brick), displayBrick(m))); bricksByZ1.computeIfAbsent(m.getZ1(), k -> new ArrayList<>()).add(m); bricksByZ2.computeIfAbsent(m.getZ2(), k -> new ArrayList<>()).add(m); moved.setTrue(); @@ -180,26 +226,21 @@ public void stack() { } public List display() { - return Stack.displayBricks(bricks); + return displayBricks(bricks); } - private static List displayBricks(final Collection bricks) { + public static List displayBricks(final Collection bricks) { return bricks.stream() .map(Stack::displayBrick) .toList(); } - private static String displayBrick(final Cuboid brick) { + public static String displayBrick(final Cuboid brick) { return "%d,%d,%d->%d,%d,%d".formatted( brick.getX1(), brick.getY1(), brick.getZ1(), brick.getX2(), brick.getY2(), brick.getZ2() ); } - - @SuppressWarnings("unused") - private void log(final Object obj) { - AoC2023_22.this.log(obj); - } } private static final String TEST = """