Skip to content

Commit 3b6949b

Browse files
committed
23th day
1 parent 5a0f703 commit 3b6949b

File tree

3 files changed

+173
-0
lines changed

3 files changed

+173
-0
lines changed

day23/day23.go

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
. "majcn.si/advent-of-code-2022/util"
8+
)
9+
10+
type DataType Set[Location]
11+
12+
func parseData(data string) DataType {
13+
dataSplit := strings.Split(data, "\n")
14+
15+
result := make(Set[Location])
16+
for y, line := range dataSplit {
17+
for x, v := range line {
18+
if v == '#' {
19+
result.Add(Location{X: x, Y: y})
20+
}
21+
}
22+
}
23+
24+
return DataType(result)
25+
}
26+
27+
func getNextLocation(elfs Set[Location], elf Location, priorities []byte) Location {
28+
hasNoNeighbours := true
29+
for _, neighbour := range GetNeighbours8() {
30+
newLocation := elf.Add(neighbour)
31+
if elfs.Contains(newLocation) {
32+
hasNoNeighbours = false
33+
break
34+
}
35+
}
36+
37+
if hasNoNeighbours {
38+
return elf
39+
}
40+
41+
for _, priority := range priorities {
42+
switch priority {
43+
case 'N':
44+
if !elfs.Contains(elf.Add(Location{X: -1, Y: -1})) && !elfs.Contains(elf.Add(Location{X: 0, Y: -1})) && !elfs.Contains(elf.Add(Location{X: 1, Y: -1})) {
45+
return elf.Add(Location{X: 0, Y: -1})
46+
}
47+
case 'S':
48+
if !elfs.Contains(elf.Add(Location{X: -1, Y: 1})) && !elfs.Contains(elf.Add(Location{X: 0, Y: 1})) && !elfs.Contains(elf.Add(Location{X: 1, Y: 1})) {
49+
return elf.Add(Location{X: 0, Y: 1})
50+
}
51+
case 'W':
52+
if !elfs.Contains(elf.Add(Location{X: -1, Y: -1})) && !elfs.Contains(elf.Add(Location{X: -1, Y: 0})) && !elfs.Contains(elf.Add(Location{X: -1, Y: 1})) {
53+
return elf.Add(Location{X: -1, Y: 0})
54+
}
55+
case 'E':
56+
if !elfs.Contains(elf.Add(Location{X: 1, Y: -1})) && !elfs.Contains(elf.Add(Location{X: 1, Y: 0})) && !elfs.Contains(elf.Add(Location{X: 1, Y: 1})) {
57+
return elf.Add(Location{X: 1, Y: 0})
58+
}
59+
}
60+
}
61+
62+
return elf
63+
}
64+
65+
func solvePartX(data DataType, goal func(int, bool) bool) (int, Set[Location]) {
66+
priorities := [][]byte{
67+
{'N', 'S', 'W', 'E'},
68+
{'S', 'W', 'E', 'N'},
69+
{'W', 'E', 'N', 'S'},
70+
{'E', 'N', 'S', 'W'},
71+
}
72+
73+
elfs := make(Set[Location], len(data))
74+
for el := range data {
75+
elfs.Add(el)
76+
}
77+
78+
for i := 0; ; i++ {
79+
blockedLocationsSet := make(Set[Location])
80+
nextLocations := make(map[Location]Location)
81+
for elf := range elfs {
82+
nextElfLocation := getNextLocation(elfs, elf, priorities[i%4])
83+
if elf == nextElfLocation {
84+
continue
85+
}
86+
87+
if blockedLocationsSet.Contains(nextElfLocation) {
88+
continue
89+
}
90+
91+
if _, ok := nextLocations[nextElfLocation]; ok {
92+
blockedLocationsSet.Add(nextElfLocation)
93+
delete(nextLocations, nextElfLocation)
94+
continue
95+
}
96+
97+
nextLocations[nextElfLocation] = elf
98+
}
99+
100+
for nextLocation, prevLocation := range nextLocations {
101+
elfs.Remove(prevLocation)
102+
elfs.Add(nextLocation)
103+
}
104+
105+
if goal(i+1, len(nextLocations) == 0) {
106+
return i + 1, elfs
107+
}
108+
}
109+
}
110+
111+
func solvePart1(data DataType) (rc int) {
112+
_, elfs := solvePartX(data, func(i int, _ bool) bool { return i == 10 })
113+
114+
minx, maxx, miny, maxy := MaxInt, 0, MaxInt, 0
115+
for elf := range elfs {
116+
minx = Min(minx, elf.X)
117+
maxx = Max(maxx, elf.X)
118+
miny = Min(miny, elf.Y)
119+
maxy = Max(maxy, elf.Y)
120+
}
121+
122+
return (maxy-miny+1)*(maxx-minx+1) - len(elfs)
123+
}
124+
125+
func solvePart2(data DataType) (rc int) {
126+
rc, _ = solvePartX(data, func(_ int, nothingHappens bool) bool { return nothingHappens })
127+
128+
return
129+
}
130+
131+
func main() {
132+
data := parseData(FetchInputData(23))
133+
fmt.Println(solvePart1(data))
134+
fmt.Println(solvePart2(data))
135+
}

day23/day23_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
. "majcn.si/advent-of-code-2022/util"
8+
)
9+
10+
func ExpectedPart1() int {
11+
return 110
12+
}
13+
14+
func ExpectedPart2() int {
15+
return 20
16+
}
17+
18+
var data DataType
19+
20+
func init() {
21+
input, _ := os.ReadFile("../examples/23.txt")
22+
data = parseData(string(input))
23+
}
24+
25+
func TestPart1(t *testing.T) {
26+
AssertTestPartX(t, ExpectedPart1(), solvePart1(data))
27+
}
28+
29+
func TestPart2(t *testing.T) {
30+
AssertTestPartX(t, ExpectedPart2(), solvePart2(data))
31+
}

examples/23.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
....#..
2+
..###.#
3+
#...#.#
4+
.#...##
5+
#.###..
6+
##.#.##
7+
.#..#..

0 commit comments

Comments
 (0)