Skip to content

Commit 60707b4

Browse files
committed
Add day 23 solution
1 parent 698a08a commit 60707b4

File tree

14 files changed

+714
-0
lines changed

14 files changed

+714
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package eu.happycoders.adventofcode2022.day23;
2+
3+
import java.util.List;
4+
5+
/**
6+
* Advent of Code 2022 – Object-Oriented Solutions in Java.
7+
*
8+
* <p>Puzzle solver for day 23.
9+
*
10+
* @author <a href="mailto:sven@happycoders.eu">Sven Woltmann</a>
11+
*/
12+
class Day23Solver {
13+
14+
static int solveTask1(String input) {
15+
List<Position> elvesPositions = PuzzleInputParser.parse(input);
16+
ElvesProcess elvesProcess = new ElvesProcess(elvesPositions);
17+
for (int i = 0; i < 10; i++) {
18+
elvesProcess.playOneRound();
19+
}
20+
Rectangle smallestRectangle = elvesProcess.getSmallestRectangle();
21+
return smallestRectangle.area() - elvesPositions.size();
22+
}
23+
24+
static int solveTask2(String input) {
25+
List<Position> elvesPositions = PuzzleInputParser.parse(input);
26+
ElvesProcess elvesProcess = new ElvesProcess(elvesPositions);
27+
28+
boolean anyoneMoved;
29+
do {
30+
anyoneMoved = elvesProcess.playOneRound();
31+
} while (anyoneMoved);
32+
33+
return elvesProcess.getRound();
34+
}
35+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package eu.happycoders.adventofcode2022.day23;
2+
3+
/**
4+
* Advent of Code 2022 – Object-Oriented Solutions in Java.
5+
*
6+
* <p>The eight possible directions.
7+
*
8+
* @author <a href="mailto:sven@happycoders.eu">Sven Woltmann</a>
9+
*/
10+
enum Direction {
11+
NORTH,
12+
NORTH_EAST,
13+
EAST,
14+
SOUTH_EAST,
15+
SOUTH,
16+
SOUTH_WEST,
17+
WEST,
18+
NORTH_WEST
19+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package eu.happycoders.adventofcode2022.day23;
2+
3+
import static eu.happycoders.adventofcode2022.day23.Direction.EAST;
4+
import static eu.happycoders.adventofcode2022.day23.Direction.NORTH;
5+
import static eu.happycoders.adventofcode2022.day23.Direction.NORTH_EAST;
6+
import static eu.happycoders.adventofcode2022.day23.Direction.NORTH_WEST;
7+
import static eu.happycoders.adventofcode2022.day23.Direction.SOUTH;
8+
import static eu.happycoders.adventofcode2022.day23.Direction.SOUTH_EAST;
9+
import static eu.happycoders.adventofcode2022.day23.Direction.SOUTH_WEST;
10+
import static eu.happycoders.adventofcode2022.day23.Direction.WEST;
11+
12+
import java.util.List;
13+
14+
/**
15+
* Advent of Code 2022 – Object-Oriented Solutions in Java.
16+
*
17+
* <p>Contains the logic for which directions to look at in the various steps of the process.
18+
*
19+
* @author <a href="mailto:sven@happycoders.eu">Sven Woltmann</a>
20+
*/
21+
public class DirectionLogic {
22+
23+
private static final List<Direction> EAST_NORTH_SOUTH_WEST = List.of(EAST, NORTH, SOUTH, WEST);
24+
private static final List<Direction> NORTH_SOUTH_WEST_EAST = List.of(NORTH, SOUTH, WEST, EAST);
25+
private static final List<Direction> SOUTH_WEST_EAST_NORTH = List.of(SOUTH, WEST, EAST, NORTH);
26+
private static final List<Direction> WEST_EAST_NORTH_SOUTH = List.of(WEST, EAST, NORTH, SOUTH);
27+
28+
private static final List<Direction> N_NE_NW = List.of(NORTH, NORTH_EAST, NORTH_WEST);
29+
private static final List<Direction> S_SE_SW = List.of(SOUTH, SOUTH_EAST, SOUTH_WEST);
30+
private static final List<Direction> W_NW_SW = List.of(WEST, NORTH_WEST, SOUTH_WEST);
31+
private static final List<Direction> E_NE_SE = List.of(EAST, NORTH_EAST, SOUTH_EAST);
32+
33+
static List<Direction> getFourAdjacentDirectionsInOrderForRound(int round) {
34+
return switch (round % 4) {
35+
case 0 -> EAST_NORTH_SOUTH_WEST;
36+
case 1 -> NORTH_SOUTH_WEST_EAST;
37+
case 2 -> SOUTH_WEST_EAST_NORTH;
38+
case 3 -> WEST_EAST_NORTH_SOUTH;
39+
default -> throw new AssertionError("Invalid result of remainder operation");
40+
};
41+
}
42+
43+
static List<Direction> determineDirectionsToLookAt(Direction direction) {
44+
return switch (direction) {
45+
case NORTH -> N_NE_NW;
46+
case SOUTH -> S_SE_SW;
47+
case WEST -> W_NW_SW;
48+
case EAST -> E_NE_SE;
49+
default -> throw new IllegalArgumentException(
50+
"Invalid direction for this step: " + direction);
51+
};
52+
}
53+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package eu.happycoders.adventofcode2022.day23;
2+
3+
/**
4+
* Advent of Code 2022 – Object-Oriented Solutions in Java.
5+
*
6+
* <p>An elf with its position and proposed step for the second half of the round.
7+
*
8+
* @author <a href="mailto:sven@happycoders.eu">Sven Woltmann</a>
9+
*/
10+
class Elf {
11+
private Position position;
12+
private Direction proposedStep;
13+
14+
Elf(Position position) {
15+
this.position = position;
16+
}
17+
18+
void setPosition(Position position) {
19+
this.position = position;
20+
}
21+
22+
Position position() {
23+
return position;
24+
}
25+
26+
void setProposedStep(Direction proposedStep) {
27+
this.proposedStep = proposedStep;
28+
}
29+
30+
Direction proposedStep() {
31+
return proposedStep;
32+
}
33+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package eu.happycoders.adventofcode2022.day23;
2+
3+
import static eu.happycoders.adventofcode2022.day23.DirectionLogic.determineDirectionsToLookAt;
4+
import static eu.happycoders.adventofcode2022.day23.DirectionLogic.getFourAdjacentDirectionsInOrderForRound;
5+
6+
import java.util.HashSet;
7+
import java.util.List;
8+
import java.util.Set;
9+
import java.util.stream.Collectors;
10+
11+
/**
12+
* Advent of Code 2022 – Object-Oriented Solutions in Java.
13+
*
14+
* <p>The process to move the elves.
15+
*
16+
* @author <a href="mailto:sven@happycoders.eu">Sven Woltmann</a>
17+
*/
18+
class ElvesProcess {
19+
20+
private final List<Elf> elves;
21+
private Set<Position> elvesPositions;
22+
int round;
23+
24+
ElvesProcess(List<Position> positions) {
25+
this.elves = positions.stream().map(Elf::new).toList();
26+
this.elvesPositions = new HashSet<>(positions);
27+
}
28+
29+
List<Elf> getElves() {
30+
return List.copyOf(elves);
31+
}
32+
33+
boolean playOneRound() {
34+
boolean proposalsMade = playFirstHalf();
35+
if (!proposalsMade) {
36+
return false;
37+
}
38+
return playSecondHalf();
39+
}
40+
41+
boolean playFirstHalf() {
42+
round++;
43+
boolean proposalsMade = false;
44+
for (Elf elf : elves) {
45+
List<Position> adjacentPositions = elf.position().getEightAdjacentPositions();
46+
if (noElvesAreInOneThosePositions(adjacentPositions)) {
47+
continue;
48+
}
49+
50+
List<Direction> adjacentDirections = getFourAdjacentDirectionsInOrderForRound(round);
51+
Direction proposedStep = calculateProposedStep(elf.position(), adjacentDirections);
52+
proposalsMade |= proposedStep != null;
53+
elf.setProposedStep(proposedStep);
54+
}
55+
return proposalsMade;
56+
}
57+
58+
private Direction calculateProposedStep(Position position, List<Direction> directions) {
59+
for (Direction direction : directions) {
60+
List<Position> positions =
61+
determineDirectionsToLookAt(direction).stream().map(position::at).toList();
62+
if (noElvesAreInOneThosePositions(positions)) {
63+
return direction;
64+
}
65+
}
66+
return null;
67+
}
68+
69+
private boolean noElvesAreInOneThosePositions(List<Position> positions) {
70+
for (Position position : positions) {
71+
if (elvesPositions.contains(position)) {
72+
return false;
73+
}
74+
}
75+
return true;
76+
}
77+
78+
boolean playSecondHalf() {
79+
Set<Position> proposedDestinations = new HashSet<>();
80+
Set<Position> duplicates = new HashSet<>();
81+
82+
for (Elf elf : elves) {
83+
if (elf.proposedStep() != null) {
84+
Position position = elf.position().at(elf.proposedStep());
85+
if (proposedDestinations.contains(position)) {
86+
duplicates.add(position);
87+
} else {
88+
proposedDestinations.add(position);
89+
}
90+
}
91+
}
92+
93+
boolean anyoneMoved = false;
94+
for (Elf elf : elves) {
95+
if (elf.proposedStep() != null) {
96+
Position position = elf.position().at(elf.proposedStep());
97+
if (!duplicates.contains(position)) {
98+
anyoneMoved = true;
99+
elf.setPosition(position);
100+
}
101+
elf.setProposedStep(null);
102+
}
103+
}
104+
105+
if (anyoneMoved) {
106+
this.elvesPositions = elves.stream().map(Elf::position).collect(Collectors.toSet());
107+
}
108+
109+
return anyoneMoved;
110+
}
111+
112+
Rectangle getSmallestRectangle() {
113+
int minX = Integer.MAX_VALUE;
114+
int minY = Integer.MAX_VALUE;
115+
int maxX = Integer.MIN_VALUE;
116+
int maxY = Integer.MIN_VALUE;
117+
for (Position elvesPosition : elvesPositions) {
118+
minX = Math.min(minX, elvesPosition.x());
119+
maxX = Math.max(maxX, elvesPosition.x());
120+
minY = Math.min(minY, elvesPosition.y());
121+
maxY = Math.max(maxY, elvesPosition.y());
122+
}
123+
return new Rectangle(minX, minY, maxX, maxY);
124+
}
125+
126+
public int getRound() {
127+
return round;
128+
}
129+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package eu.happycoders.adventofcode2022.day23;
2+
3+
/**
4+
* Advent of Code 2022 – Object-Oriented Solutions in Java.
5+
*
6+
* <p>Main application for day 23.
7+
*
8+
* @author <a href="mailto:sven@happycoders.eu">Sven Woltmann</a>
9+
*/
10+
class Main23 {
11+
12+
private static final String INPUT =
13+
"""
14+
#..###...#..##.#####...#.##...####.###.#...##..##.#.#.#.#.#...##.......#
15+
..##.#.##..#.##..#.......######..#..###.###########.#.##..#..##.#...#..#
16+
##..#...###....####.##.#.##.##.....#.##....##..#..##.#.......##.#...###.
17+
##....#.#####...##....###..#....###..#.####..###.##....##....##.#...#.##
18+
.##.##..###.##..#.####.##.#.######....#....##.###..########..#.###..#.#.
19+
#..###.#.###.#...#.#.####.##..#####...#..###.....#.#.##..#.##.####.#####
20+
..##..##..####.###.##.#.#..####..#...##..##..#.##..###.#.#..#......##..#
21+
##.#....#....#.#...#....###.###.....##.#.#..####.#...##.#.#.#..#...###.#
22+
#..#.#.#.#.#.##.#...##.##...#..#..####.##....##.#..#....##.####..###..##
23+
###..#.#.#...#....######.####...#.##.#.......#.##.#....#..#######..#.###
24+
##.##.########.####..#....#...##..#....##.#..###.#.#......#..#.##.##..#.
25+
##.#.#..#.###.....#..##....###...####..##.##...#....##.######.##.#.#....
26+
###.#..###.#....#......#.####.#..####...#.##.####...#########......#.#.#
27+
.##.##..#.#..####.#....#.#.#..####.#..#.######....#####.#.#.##.###.....#
28+
###..##.....##.##.......#........#.......###...#........#####.##...####.
29+
.#.#..#.####...####....#.#..##.####..####.##......##.#.#.#..####.####...
30+
...####...###..#.##..#.##..####...##..##.##.#..###..#.##.##..####.##..##
31+
.##..#....#.#..########.#.#...#.#..#####.#.....#.##.#.#.#.#.#.....###.##
32+
###.#..##.#...#.##.###...##......##..#.###...#..####...###..###..#..#...
33+
.#.####.####...#.#..#####.....###......##..##....###.#.#.#..##.##.#.#..#
34+
.##.###....##..#.##.##.##..#####.#.##.#....###...#..#.##.#.#....#..#..##
35+
...##.###....##.###...#..####..##..#....##....#...#..##.#......##.#.....
36+
.##.#.#..#..#.#....#....####.##.#.###...###.#..#.#...#..#....###..##.##.
37+
#..###.##..###..#.#.#.##..###....#.#.#.##.............#.##.##..#..###.##
38+
.....#.#.....#....##.#.#....###.#.....#....##.###..#.#.#.#.###...#.#.#.#
39+
##....###.#.#.##.##.##.#.#...#..#.##....#...#.....###.#...#.##..##..##.#
40+
.#.....#.##.##.###.#.###....###...#..#.##.##..#.##....#.###......#.####.
41+
.#.#...#.##############...######..#........###.###.#...####...#...###..#
42+
##.#####....###....#..####.##.#..##.##.#.....#...#.###...#.#..#####....#
43+
##.###..#..####..###.###..####.#####.....###.#.###..##.#...#.#.##.##..##
44+
####..##.###.#...###.##.....#.#..#....###..##.##..##..###.##.#....#.####
45+
...#.####..#..#.#..##..#.##.#..#######...#...#...##.#..#.##..#.#.###.#.#
46+
.#.#..###.#..#...#.....#.####..####....##.##..##..#.#.#...#.###...##.##.
47+
..#####..#.#.#.#.########...##.#####.#..#....####..##..#######...#....#.
48+
.#.##..##.###..#######...#...#.#.##.......#....#####....##.....#.####.#.
49+
#..###.#######.#..#.##.##..###.####..#######.###...#.#.#.###..###.###.##
50+
#.#..#.##.#..###.#.#.#####.#.#.###...##.#...#####.#..##....#...#...#..##
51+
.#..#.....#.###..#.#..#...##.###...##..#..##.#....##.#.##.#.##...##..#..
52+
.###.####....#..#.#........#.####.....#.#...###.###.##..#..#...###..#...
53+
####...#...##..#..##.........#...###.#.####.#.##....#.##..#.#...########
54+
##.#.#..####..####..######..##...###.#.#..##.#.#.#....######..#####..###
55+
.##.##....#.##.###...##.##.....#.#.##...####.##...##.###...####...#.#..#
56+
.#..###..#...##.#.#...#######..##...###..##....##.###..##.#..#.###..#.#.
57+
.###..####..##...#...###.....##.#...###..#.#.##.....#.#..###.#####..####
58+
.#.#.#..##.##..#####.##..#.##.#.#...#.#.#..#..#.##..#...##.#....###.##.#
59+
.#...###.#..#####.#.....#####....####.###...####.#..###.#.##..#..##...##
60+
.##...#.#...####.##.#.##...##.######.###.##...##...#.#.###.#..#####.....
61+
.#....#...##.#..#..##...##..#.##...#..##.#.###.###..#.#..###.#.##.###...
62+
.#..###.#.##..#.#.###.#.###...#..###.#..####.#.#.###.#.###..#.###..##...
63+
#.####.##.##.#######.##.##..##.###.##.###.#.#..#.#.##....##.#..##.#.#.#.
64+
...####.#####.#..##..###...#..#.#.#####..##..####.#....###.#.###.#...##.
65+
.#######.##..###.....#..#.##..#.#.###.##.##...###.##...#.#.#.###.#.##.##
66+
.#.#.##.#..#.#..##.##.#..###....##....#.##......#.#####..####.###.#.##.#
67+
.##.#####....###...##.#..#..#..#.........#####..#.#....####.#....######.
68+
...#..#...###...##...#.#.#.#.###.#.#..####.#...###.####...###..###.###..
69+
.#...##.#....###......#####.....####.##.#.#.####..#...#..##....#####..##
70+
########..#..#.##..#.#..##.###.#...##.#.###....####.##..#..#.#.#.#..#...
71+
.#.#..#..#..#.#..######.#.#..##.......#...#..##...#.#.#..#..###....#...#
72+
....#####.#.#.###.##.#...#......#.###.#####..#####...#####.###.#.#..#.#.
73+
....####.#.#.#.##.###..##..#..#.##.#..###...#.##..#..#####..#....##....#
74+
..##.##.#..###..####...#.##....####.###...###.........#...#..##..#.###..
75+
....#.##...#.#.####.#.#......#..#.#.###.##....##.######....#.....#..#.#.
76+
#.....#.#..#....#.#.#.#..#####.###..######.#.#....#.####.#.##.....##.###
77+
...#.##..####.####.......##.#.#########...###.#####.##..#.#.#..#..#.#...
78+
.#.##..#.##.#.##.##..##.##...####.#.###...##.##.#......#....##..#..#..#.
79+
#..#...#...##.##..###.....#...########.#.###..###..##.##..#..##.####.###
80+
..###....##...#...#..##.###.###..#.###..#.#.......#.####.##.#..##..####.
81+
.###.#.###..#..#...#.#.##.##.#.#.#..#.#.#.#..##..#..#....##.##.##....#.#
82+
........#..##.#.#.#..######.##.#.#.###.#..#..#.#.....#.#.....#.##.##..#.
83+
#..#..##.#.#.####..#.#...#.#.###.###.##.#..#.##.####.#.##.#.#######.####
84+
......#.##.#..##.##....#.#.....##..#.#..#.##.....#.......#.#....#.##..#.
85+
..##.#.#.##.#...####........####.##....#.#...##....#...#.#...#..#.##.#..""";
86+
87+
public static void main(String[] args) {
88+
System.out.println(Day23Solver.solveTask1(INPUT));
89+
System.out.println(Day23Solver.solveTask2(INPUT));
90+
}
91+
}

0 commit comments

Comments
 (0)