Skip to content

Commit 16bd44f

Browse files
committed
Year 2022 Day 23
1 parent a521eec commit 16bd44f

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ The minimal SBT project provides:
5353
| 20 | [Grove Positioning System](https://adventofcode.com/2022/day/20) | [Source](src/main/scala/AdventOfCode2022/Day20.scala) |
5454
| 21 | [Monkey Math](https://adventofcode.com/2022/day/21) | [Source](src/main/scala/AdventOfCode2022/Day21.scala) |
5555
| 22 | [Monkey Map](https://adventofcode.com/2022/day/22) | [Source](src/main/scala/AdventOfCode2022/Day22.scala) |
56+
| 23 | [Unstable Diffusion](https://adventofcode.com/2022/day/23) | [Source](src/main/scala/AdventOfCode2022/Day23.scala) |
5657

5758
## 2021
5859

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
....#.#.#.##.....###.....##..####..#.#...####..####.#...##..###.##.....
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+
##.#.###...##.#..#.....##.#..#.#..##..#..#.###.#.#.######..#.#....##..#
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package AdventOfCode2022
2+
3+
object Day23:
4+
val adjacent = Seq(Point(-1, -1), Point(0, -1), Point(1, -1), Point(-1, 0), Point(1, 0), Point(-1, 1), Point(0, 1), Point(1, 1))
5+
val (north, south, west, east) = (Point(0, -1), Point(0, 1), Point(-1, 0), Point(1, 0))
6+
val order = Seq(north, south, west, east)
7+
8+
case class Point(x: Int, y: Int):
9+
def +(other: Point): Point = Point(x + other.x, y + other.y)
10+
11+
case class State(elves: Set[Point], moves: Seq[Point], stuck: Boolean)
12+
13+
def parse(input: Seq[String]): Set[Point] =
14+
val points = for y <- input.indices; x <- input.head.indices if input(y)(x) != '.' yield Point(x, y)
15+
points.toSet
16+
17+
def step(state: State): State =
18+
val State(elves, moves, _) = state
19+
20+
val proposals = elves.map(elf => elf -> propose(elves, moves, elf))
21+
val occurrences = proposals.toSeq.flatMap(_._2).groupMapReduce(identity)(_ => 1)(_ + _)
22+
val valid = occurrences.filter((_, total) => total == 1).keySet
23+
val next = proposals.map { (elf, proposal) =>
24+
proposal.map(move => if valid.contains(move) then move else elf).getOrElse(elf)
25+
}
26+
27+
State(next, moves.tail :+ moves.head, elves == next)
28+
end step
29+
30+
def propose(elves: Set[Point], order: Seq[Point], elf: Point): Option[Point] =
31+
val checks = adjacent.map(_ + elf).map(elves.contains)
32+
val Seq(nw, n, ne, w, e, sw, s, se) = checks
33+
34+
if checks.exists(identity) then
35+
order.find {
36+
case `north` => !(nw || n || ne)
37+
case `south` => !(sw || s || se)
38+
case `west` => !(nw || w || sw)
39+
case `east` => !(ne || e || se)
40+
}
41+
.map(_ + elf)
42+
else None
43+
end propose
44+
45+
def part1(input: Seq[String]): Int =
46+
val start = State(parse(input), order, false)
47+
val elves = Iterator.iterate(start)(step).drop(10).next.elves
48+
49+
val minX = elves.map(_.x).min
50+
val maxX = elves.map(_.x).max
51+
val minY = elves.map(_.y).min
52+
val maxY = elves.map(_.y).max
53+
54+
val points = for x <- minX to maxX; y <- minY to maxY yield Point(x, y)
55+
points.filterNot(elves.contains).size
56+
end part1
57+
58+
def part2(input: Seq[String]): Int =
59+
val start = State(parse(input), order, false)
60+
Iterator.iterate(start)(step).indexWhere(_.stuck == true)
61+
62+
def main(args: Array[String]): Unit =
63+
val data = io.Source.fromResource("AdventOfCode2022/Day23.txt").getLines().toSeq
64+
println(part1(data))
65+
println(part2(data))
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package AdventOfCode2022
2+
3+
import org.scalatest.funsuite.AnyFunSuite
4+
5+
class Day23Suite extends AnyFunSuite:
6+
val sample = Seq(
7+
"....#..",
8+
"..###.#",
9+
"#...#.#",
10+
".#...##",
11+
"#.###..",
12+
"##.#.##",
13+
".#..#..")
14+
15+
test("Part 1 should handle sample input correctly") {
16+
assert(Day23.part1(sample) == 110)
17+
}
18+
19+
test("Part 2 should handle sample input correctly") {
20+
assert(Day23.part2(sample) == 20)
21+
}

0 commit comments

Comments
 (0)