diff --git a/2023/17/common.go b/2023/17/common.go new file mode 100644 index 00000000..d3c43fe7 --- /dev/null +++ b/2023/17/common.go @@ -0,0 +1,36 @@ +package main + +import ( + "bufio" + "os" +) + +type Dir uint8 + +const ( + N Dir = iota + E + S + W +) + +func (d Dir) Clock() Dir { + return (d + 1) % 4 +} + +func (d Dir) CounterClock() Dir { + return (d - 1 + 4) % 4 +} + +func parseInput() map[P]int { + m := map[P]int{} + + scanner := bufio.NewScanner(os.Stdin) + for i := 0; scanner.Scan(); i++ { + line := scanner.Text() + for j, ch := range line { + m[P{i, j}] = int(ch - '0') + } + } + return m +} diff --git a/2023/17/example b/2023/17/example new file mode 100644 index 00000000..f400d6e0 --- /dev/null +++ b/2023/17/example @@ -0,0 +1,13 @@ +2413432311323 +3215453535623 +3255245654254 +3446585845452 +4546657867536 +1438598798454 +4457876987766 +3637877979653 +4654967986887 +4564679986453 +1224686865563 +2546548887735 +4322674655533 diff --git a/2023/17/main1.go b/2023/17/main1.go new file mode 100644 index 00000000..1759dc33 --- /dev/null +++ b/2023/17/main1.go @@ -0,0 +1,98 @@ +package main + +import ( + "container/heap" + "fmt" +) + +// const Size = 141 +const Size = 13 + +var ( + Start = P{0, 0} + End = P{12, 12} +) + +func main() { + m := parseInput() + fmt.Println(Dijkstra(m, Start, End)) +} + +type P struct{ x, y int } + +type Node struct { + P + Dir +} + +func Dijkstra(m map[P]int, start, goal P) int { + parent := map[P]P{} + startNode := Node{start, E} + heats := map[Node]int{startNode: 0} + + pq := &priorityQueue{} + heap.Init(pq) + heap.Push(pq, pqNode{startNode, 0}) + + for pq.Len() > 0 { + + curr := heap.Pop(pq).(pqNode) + + // we reached the end + if curr.Node.P == goal { + + for x := goal; x != start; x = parent[x] { + + } + + return curr.Heat + } + + for _, n := range neighbours(m, curr) { + + if _, ok := heats[n.Node]; !ok || n.Heat <= heats[n.Node] { + parent[n.P] = parent[n.Node], curr.Node + heats[n.Node] = n.Heat + heap.Push(pq, n) + } + } + } + panic("no path found") +} + +var Delta = map[Dir]P{ + N: {-1, 0}, + S: {1, 0}, + W: {0, -1}, + E: {0, 1}, +} + +func neighbours(m map[P]int, node pqNode) []pqNode { + var neighbs []pqNode + + for _, d := range []Dir{node.Dir.Clock(), node.Dir.CounterClock()} { + delta := Delta[d] + heat := node.Heat + for i := 0; i < 3; i++ { + next := P{node.Node.x + i*delta.x, node.Node.y + i*delta.y} + + if next.x < 0 || next.x >= Size { + continue + } + if next.y < 0 || next.y >= Size { + continue + } + + heat += m[next] + neighbs = append(neighbs, + pqNode{ + Node: Node{ + P: next, + Dir: d, + }, + Heat: node.Heat + m[next], + }) + } + } + return neighbs +} diff --git a/2023/17/main2.go b/2023/17/main2.go new file mode 100644 index 00000000..e5dbd698 --- /dev/null +++ b/2023/17/main2.go @@ -0,0 +1,18 @@ +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + scanner := bufio.NewScanner(os.Stdin) + + for scanner.Scan() { + line := scanner.Text() + + } + + fmt.Println() +} \ No newline at end of file diff --git a/2023/17/priority_queue.go b/2023/17/priority_queue.go new file mode 100644 index 00000000..01548c9e --- /dev/null +++ b/2023/17/priority_queue.go @@ -0,0 +1,32 @@ +package main + +type pqNode struct { + Node + Heat int +} + +type priorityQueue []pqNode + +func (n priorityQueue) Len() int { + return len(n) +} + +func (n priorityQueue) Less(i, j int) bool { + return n[i].Heat < n[j].Heat +} + +func (n priorityQueue) Swap(i, j int) { + n[i], n[j] = n[j], n[i] +} + +func (n *priorityQueue) Push(x any) { + *n = append(*n, x.(pqNode)) +} + +func (n *priorityQueue) Pop() any { + old := *n + l := len(old) + x := old[l-1] + *n = old[0 : l-1] + return x +} diff --git a/2023/24/Makefile b/2023/24/Makefile new file mode 100644 index 00000000..4b3e4471 --- /dev/null +++ b/2023/24/Makefile @@ -0,0 +1,19 @@ +input: + http "https://adventofcode.com/2023/day/24/input" "Cookie:session=${AOC_SESSION};" >input + +main1: + go build -o main1 main1.go common.go + +main2: + go build -o main2 main2.go common.go + +.PHONY: run1 run2 clean + +run1: main1 input + ./main1 = xMin && point <= xMax + + case 'y': + return point >= yMin && point <= yMax + + case 'z': + return true + } + + return false +} + +func collide(h1, h2 Hail) bool { + + fmt.Println() + fmt.Println(h1) + fmt.Println(h2) + + whereX, cX := collideAxis('x', h1, h2) + if cX { + if inside('x', whereX) { + log.Printf("x intersects at %.2f, inside", whereX) + whereY, cY := collideAxis('y', h1, h2) + if cY { + if inside('y', whereY) { + log.Printf("y intersects at %.2f, inside", whereY) + return true + } else { + log.Printf("y intersects at %.2f, outside", whereY) + return false + } + } else { + log.Println("y does not intersect") + return false + } + } else { + log.Printf("x intersects at %.2f, outside", whereX) + return false + } + } else { + log.Println("x does not intersect") + return false + } +} + +//// h1 func +//// x = x0 + vx*t +//// y = y0 + vy*t +// +//// h2 func +//// x = x0 + vx*t +//// y = y0 + vy*t +// +//// { x = h1.vx*t + h1.x0 +//// { x = h2.vx*t + h2.x0 +//// --------------------- +//// 0 = t * (h1.vx-h2.vx) + h1.x0 - h2.x0 +//// t = h2.x0 - h1.x0 +//// ------------- +//// h1.vx - h2.vx +// +//var tx, ty int +// +//if h1.Vel.x == h2.Vel.x { +// if h1.Pos.x != h2.Pos.x { +// log.Printf("On x, Same velocity, different starting position: %d@%d vs %d@%d", h1.Pos.x, h1.Vel.x, h2.Pos.x, h2.Vel.x) +// return P{}, false +// } +// log.Printf("On x, Same velocity, same starting position: %d@%d vs %d@%d", h1.Pos.x, h1.Vel.x, h2.Pos.x, h2.Vel.x) +// log.Fatal("1") +//} else { +// tx = (h2.Pos.x - h1.Pos.x) / (h1.Vel.x - h2.Vel.x) +// if tx < 0 { +// return P{}, false +// } +//} +// +//if h1.Vel.y == h2.Vel.y { +// if h1.Pos.y != h2.Pos.y { +// log.Printf("On y, Same velocity, different starting position: %d@%d vs %d@%d", h1.Pos.y, h1.Vel.y, h2.Pos.y, h2.Vel.y) +// return P{}, false +// } +// log.Printf("On y, Same velocity, same starting position: %d@%d vs %d@%d", h1.Pos.y, h1.Vel.y, h2.Pos.y, h2.Vel.y) +// log.Fatal("2") +//} else { +// ty = (h2.Pos.y - h1.Pos.y) / (h1.Vel.y - h2.Vel.y) +// if ty < 0 { +// return P{}, false +// } +//} +// +//return tx == ty + +func collideAxis(axis byte, h1 Hail, h2 Hail) (float64, bool) { + var p1, p2 int + var v1, v2 int + + switch axis { + case 'x': + p1, v1 = h1.Pos.x, h1.Vel.x + p2, v2 = h2.Pos.x, h2.Vel.x + + case 'y': + p1, v1 = h1.Pos.y, h1.Vel.y + p2, v2 = h2.Pos.y, h2.Vel.y + + case 'z': + p1, v1 = h1.Pos.z, h1.Vel.z + p2, v2 = h2.Pos.z, h2.Vel.z + } + + // x = p1+v1*t + // x = p2+v2*t + // p1 +v1*t = p2 +v2*t + // t(v1-v2) = p2-p1 + // t = (p2-p1) / (v1-v2) + // + + // x + // x = p1 + v1*t + // x = p2 + v2*t + // 0 = p1-p2 + (v1-v2)t + // t = (p2-p1) / (v1-v2) + if v1 == v2 { + if p1 == p2 { + log.Printf("parallel, always intersecting") + return float64(p1), true + } + log.Printf("parallel, never intersecting") + return 0, false + } + + t := float64(p2-p1) / float64(v1-v2) + log.Printf("collide %s at t=%.2f", string(axis), t) + return float64(p1) + float64(v1)*t, true +} diff --git a/2023/24/main2.go b/2023/24/main2.go new file mode 100644 index 00000000..e5dbd698 --- /dev/null +++ b/2023/24/main2.go @@ -0,0 +1,18 @@ +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + scanner := bufio.NewScanner(os.Stdin) + + for scanner.Scan() { + line := scanner.Text() + + } + + fmt.Println() +} \ No newline at end of file diff --git a/README.md b/README.md index 32f03685..6a1c1032 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,4 @@ | 2021 | [![2021](https://img.shields.io/badge/stars%20⭐-50-yellow)](https://adventofcode.com/2021/stats) | | 2022 | [![2022](https://img.shields.io/badge/stars%20⭐-50-yellow)](https://adventofcode.com/2022/stats) | | 2023 | [![2023](https://img.shields.io/badge/stars%20⭐-41-yellow)](https://adventofcode.com/2023/stats) | -| 2024 | [![2024](https://img.shields.io/badge/stars%20⭐-48-yellow)](https://adventofcode.com/2024/stats) | +| 2024 | [![2024](https://img.shields.io/badge/stars%20⭐-50-yellow)](https://adventofcode.com/2024/stats) |