generated from arol-polito/python-project-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Alessio Chessa
committed
Dec 18, 2024
1 parent
0a7de74
commit ceb064c
Showing
7 changed files
with
3,809 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.