Skip to content

Commit

Permalink
day18
Browse files Browse the repository at this point in the history
  • Loading branch information
gamersi committed Dec 18, 2024
1 parent 6160a0b commit adb0db6
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 0 deletions.
82 changes: 82 additions & 0 deletions day18p1/solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package day18p1

import (
"fmt"
"io"

"aoc/utils"
)

func Solve(r io.Reader) any {
lines := utils.ReadLines(r)

isTest := len(lines) < 30

numSimulated := 12
if !isTest {
numSimulated = 1024
}
size := 6
if !isTest {
size = 70
}

corrupted := make(map[utils.Point]bool)
bytes := make([]utils.Point, 0)
for _, line := range lines {
x, y := 0, 0
fmt.Sscanf(line, "%d,%d", &x, &y)
bytes = append(bytes, utils.Point{X: x, Y: y})
}
for i := 0; i < numSimulated; i++ {
corrupted[bytes[i]] = true
}

return steps(corrupted, size)
}

func steps(corrupted map[utils.Point]bool, size int) int {
type state struct {
pos utils.Point
steps int
}
queue := make([]state, 0)
visited := make(map[utils.Point]bool)
end := utils.Point{X: size, Y: size}
var enqueue = func(p utils.Point, s int) {
for i := 0; i < len(queue); i++ {
if queue[i].steps > s {
queue = append(queue[:i], append([]state{{pos: p, steps: s}}, queue[i:]...)...)
return
}
}
queue = append(queue, state{pos: p, steps: s})
}
var dequeue = func() state {
current := queue[0]
queue = queue[1:]
return current
}
enqueue(utils.Point{X: 0, Y: 0}, 0)
for len(queue) > 0 {
current := dequeue()
if current.pos == end {
return current.steps
}
if visited[current.pos] {
continue
}
visited[current.pos] = true
for _, dir := range utils.Directions {
next := current.pos.Add(dir)
if next.X < 0 || next.Y < 0 || next.X > size || next.Y > size {
continue
}
if corrupted[next] {
continue
}
enqueue(next, current.steps+1)
}
}
return -1
}
57 changes: 57 additions & 0 deletions day18p1/solution_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package day18p1

import (
"strings"
"testing"

"aoc/utils"
)

var testInput = `5,4
4,2
4,5
3,0
2,1
6,3
2,4
1,5
0,6
3,3
2,6
5,1
1,2
5,5
2,5
6,5
1,4
0,4
6,4
1,1
6,1
1,0
0,5
1,6
2,0`

func TestSolve(t *testing.T) {
tests := []struct {
input string
answer int
}{
{testInput, 22},
}

if testing.Verbose() {
utils.Verbose = true
}

for _, test := range tests {
r := strings.NewReader(test.input)

result := Solve(r).(int)

if result != test.answer {
t.Errorf("Expected %d, got %d", test.answer, result)
}
}
}
89 changes: 89 additions & 0 deletions day18p2/solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package day18p2

import (
"fmt"
"io"
"strconv"

"aoc/utils"
)

func Solve(r io.Reader) any {
lines := utils.ReadLines(r)

isTest := len(lines) < 30

numSimulated := 12
if !isTest {
numSimulated = 1024
}
size := 6
if !isTest {
size = 70
}

corrupted := make(map[utils.Point]bool)
bytes := make([]utils.Point, 0)
for _, line := range lines {
x, y := 0, 0
fmt.Sscanf(line, "%d,%d", &x, &y)
bytes = append(bytes, utils.Point{X: x, Y: y})
}
for i := 0; i < numSimulated; i++ {
corrupted[bytes[i]] = true
}
for i := size; i < len(bytes); i++ {
corrupted[bytes[i]] = true
if steps(corrupted, size) == -1 {
return strconv.Itoa(bytes[i].X) + "," + strconv.Itoa(bytes[i].Y)
}
}

return ""
}

func steps(corrupted map[utils.Point]bool, size int) int {
type state struct {
pos utils.Point
steps int
}
queue := make([]state, 0)
visited := make(map[utils.Point]bool)
end := utils.Point{X: size, Y: size}
var enqueue = func(p utils.Point, s int) {
for i := 0; i < len(queue); i++ {
if queue[i].steps > s {
queue = append(queue[:i], append([]state{{pos: p, steps: s}}, queue[i:]...)...)
return
}
}
queue = append(queue, state{pos: p, steps: s})
}
var dequeue = func() state {
current := queue[0]
queue = queue[1:]
return current
}
enqueue(utils.Point{X: 0, Y: 0}, 0)
for len(queue) > 0 {
current := dequeue()
if current.pos == end {
return current.steps
}
if visited[current.pos] {
continue
}
visited[current.pos] = true
for _, dir := range utils.Directions {
next := current.pos.Add(dir)
if next.X < 0 || next.Y < 0 || next.X > size || next.Y > size {
continue
}
if corrupted[next] {
continue
}
enqueue(next, current.steps+1)
}
}
return -1
}
57 changes: 57 additions & 0 deletions day18p2/solution_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package day18p2

import (
"strings"
"testing"

"aoc/utils"
)

var testInput = `5,4
4,2
4,5
3,0
2,1
6,3
2,4
1,5
0,6
3,3
2,6
5,1
1,2
5,5
2,5
6,5
1,4
0,4
6,4
1,1
6,1
1,0
0,5
1,6
2,0`

func TestSolve(t *testing.T) {
tests := []struct {
input string
answer string
}{
{testInput, "6,1"},
}

if testing.Verbose() {
utils.Verbose = true
}

for _, test := range tests {
r := strings.NewReader(test.input)

result := Solve(r).(string)

if result != test.answer {
t.Errorf("Expected %s, got %s", test.answer, result)
}
}
}

0 comments on commit adb0db6

Please sign in to comment.