Skip to content

Commit

Permalink
day 18 solution, a bit hardcoded
Browse files Browse the repository at this point in the history
  • Loading branch information
Alessio Chessa committed Dec 18, 2024
1 parent 0a7de74 commit ceb064c
Show file tree
Hide file tree
Showing 7 changed files with 3,809 additions and 0 deletions.
128 changes: 128 additions & 0 deletions solutions/alessio/day18/day18.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package main

import (
"aoc18/graph"
"fmt"
"math"
"os"
"strings"
"time"
)

func check(e error) {
if e != nil {
panic(e)
}
}

type Pos struct {
r, c int
}

func checkInBounds(pos Pos, rows int, cols int) bool {
return pos.r >= 0 && pos.r < rows && pos.c >= 0 && pos.c < cols
}

var dirs []Pos = []Pos{{0, 1}, {0, -1}, {1, 0}, {-1, 0}} // E, W, S, N

func printGrid(obstacles map[Pos]bool, rows int, cols int) {
for r := 0; r < rows; r++ {
for c := 0; c < cols; c++ {
if obstacles[Pos{r, c}] {
fmt.Print("#")
} else {
fmt.Print(".")
}
}
fmt.Println()
}
fmt.Println()
}

func addGraphEdges(graph *graph.Graph[Pos], obstacles map[Pos]bool, rows int, cols int) {
for r := 0; r < rows; r++ {
for c := 0; c < cols; c++ {
for _, d := range dirs {
p := Pos{r + d.r, c + d.c}
if checkInBounds(p, rows, cols) && !obstacles[p] {
graph.AddEdge(Pos{r, c}, p, 1)
}
}
}
}
}

func addGraphNodes(g *graph.Graph[Pos], obstacles map[Pos]bool, rows int, cols int) {
for r := 0; r < rows; r++ {
for c := 0; c < cols; c++ {
if !obstacles[Pos{r, c}] {
g.AddNode(Pos{r, c})
}
}
}
}
func getGraph(obstacles map[Pos]bool, rows int, cols int) (*graph.Graph[Pos], Pos, Pos) {
g := graph.Graph[Pos]{}
g.Init(rows*cols, rows*cols)
start, end := Pos{0, 0}, Pos{rows - 1, cols - 1}
addGraphNodes(&g, obstacles, rows, cols)
addGraphEdges(&g, obstacles, rows, cols)
return &g, start, end
}

func getObstacles(bytes []string) map[Pos]bool {
obstacles := map[Pos]bool{}
for _, s := range bytes {
p := Pos{}
fmt.Sscanf(s, "%d,%d", &p.r, &p.c)
obstacles[p] = true
}
return obstacles
}

func solve(bytes []string, numFixedBytes int, size int) {
obstacles := getObstacles(bytes[:numFixedBytes])
g, start, end := getGraph(obstacles, size, size)
// printGrid(obstacles, size, size)
min := g.ShortestPath(start, end)
fmt.Println(min)
}

func part1(bytes []string) {
solve(bytes, 1024, 71)
// solve(bytes, 12, 7)
}

func part2(bytes []string) {
fixed, size := 2900, 71
obstacles := getObstacles(bytes[:fixed])
g, start, end := getGraph(obstacles, size, size)

i := 0
for fixed+i < len(bytes) {
fmt.Println(i)
newObstacle := Pos{}
fmt.Sscanf(bytes[fixed+i], "%d,%d", &newObstacle.r, &newObstacle.c)
obstacles[newObstacle] = true
g.RemoveNode(newObstacle)
if g.ShortestPath(start, end) == math.MaxInt {
fmt.Printf("%d,%d\n", newObstacle.r, newObstacle.c)
break
}
i++
}
}

func main() {
data, err := os.ReadFile("./input18_def.txt")
check(err)
dataStr := strings.ReplaceAll(string(data), "\r\n", "\n")
lines := strings.Split(strings.Trim(dataStr, "\n"), "\n")

start := time.Now()
part1(lines)
fmt.Printf("part1: %s\n", time.Since(start))
start = time.Now()
part2(lines)
fmt.Printf("part2: %s\n", time.Since(start))
}
10 changes: 10 additions & 0 deletions solutions/alessio/day18/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module aoc18

go 1.23

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.10.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
9 changes: 9 additions & 0 deletions solutions/alessio/day18/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
166 changes: 166 additions & 0 deletions solutions/alessio/day18/graph/graph.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package graph

import (
"fmt"
"math"
"slices"
)

type Graph[T comparable] struct {
Nodes []Node[T]
Edges []Edge[T]
AdjList map[T][]Edge[T]
}

type Node[T any] struct {
Val T
}

type Edge[T any] struct {
Weight int
From T
To *Node[T]
}

func (graph *Graph[T]) AddNode(val T) *Node[T] {
node := Node[T]{Val: val}
graph.Nodes = append(graph.Nodes, node)
return &node
}

func (graph *Graph[T]) RemoveNode(val T) {
delete(graph.AdjList, val)
for i, lst := range graph.AdjList {
idx := -1
for j, e := range lst {
if e.To.Val == val {
idx = j
break
}
}
if idx != -1 {
graph.AdjList[i] = slices.Concat(lst[:idx], lst[idx+1:])
}
}
}

func (graph *Graph[T]) AddEdge(from T, to T, weight int) *Edge[T] {
toNode := graph.GetNode(to)
if toNode == nil {
fmt.Println("Error: toNode is nil")
return nil
}
edge := Edge[T]{Weight: weight, To: toNode}
graph.Edges = append(graph.Edges, edge)
graph.AdjList[from] = append(graph.AdjList[from], edge)
return &edge
}

func (graph *Graph[T]) HasNode(val T) bool {
return slices.ContainsFunc(graph.Nodes, func(n Node[T]) bool { return n.Val == val })
}

func (graph *Graph[T]) HasEdge(from T, to T) bool {
for _, e := range graph.AdjList[from] {
if e.To.Val == to {
return true
}
}
return false
}

func (graph *Graph[T]) GetNode(val T) *Node[T] {
for _, n := range graph.Nodes {
if n.Val == val {
return &n
}
}
return nil
}

func (graph *Graph[T]) Init(nodes int, edges int) {
graph.Nodes = make([]Node[T], 0, nodes)
graph.Edges = make([]Edge[T], 0, edges)
graph.AdjList = make(map[T][]Edge[T], nodes)
}

func (graph *Graph[T]) ShortestPath(from T, to T) int {
start := graph.GetNode(from)
end := graph.GetNode(to)
dist := make(map[T]int, len(graph.Nodes))
path := map[T]bool{}
nodes := make([]T, 0, len(graph.Nodes))
for _, n := range graph.Nodes {
dist[n.Val] = math.MaxInt
nodes = append(nodes, n.Val)
}

dist[start.Val] = 0
for len(path) < len(nodes) {
curr := graph.getClosest(nodes, dist, path)
if curr == end.Val {
break
}
if path[curr] {
continue
}
path[curr] = true

if curr == end.Val {
return dist[curr]
}

for _, e := range graph.AdjList[curr] {
// relaxation on the edge
if !path[e.To.Val] && dist[curr]+e.Weight < dist[e.To.Val] {
dist[e.To.Val] = dist[curr] + e.Weight
}
}
}
return dist[end.Val]
}

func (graph *Graph[T]) getClosest(nodes []T, dist map[T]int, visited map[T]bool) T {
var minNode T
minDist := math.MaxInt

for _, n := range nodes {
if !visited[n] && dist[n] <= minDist {
minDist = dist[n]
minNode = n
}
}
return minNode
}

func (graph *Graph[T]) GetFullPathsEdges(start T, end T) []Edge[T] {
allEdges := []Edge[T]{}
min := math.MaxInt
graph.getBestPathsRec(start, &map[T]bool{}, []Edge[T]{}, &allEdges, end, 0, &min)
return allEdges
}

func (graph *Graph[T]) getBestPathsRec(currNode T, visited *map[T]bool, currPath []Edge[T], edges *[]Edge[T], end T, currVal int, currMin *int) {
if currNode == end {
fmt.Println("found path")
if currVal < *currMin {
*currMin = currVal
(*edges) = append([]Edge[T]{}, currPath...) // replace all
} else if currVal == *currMin {
(*edges) = append((*edges), currPath...)
}
return
}

(*visited)[currNode] = true
for _, e := range graph.AdjList[currNode] {
next := e.To.Val
if !(*visited)[next] {
e.From = currNode
if currVal+e.Weight <= *currMin {
graph.getBestPathsRec(next, visited, append(currPath, e), edges, end, currVal+e.Weight, currMin)
}
}
}
(*visited)[currNode] = false
}
25 changes: 25 additions & 0 deletions solutions/alessio/day18/input18.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
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
Loading

0 comments on commit ceb064c

Please sign in to comment.