adventofcode/2018/day22/day22.go

80 lines
1.6 KiB
Go

package main
import (
"bufio"
"container/heap"
"fmt"
"os"
)
const bailFactor = 8
func main() {
inp := StdinToStringSlice()
fmt.Printf("# Part 1\nRisk level: %d\n", RiskLevel(inp))
fmt.Printf("# Part 2\nRescue minutes: %d\n", Rescue(inp))
}
func RiskLevel(input []string) int {
m := NewMap(input)
sum := 0
for y := 0; y <= m.target.y; y++ {
for x := 0; x <= m.target.x; x++ {
sum += m.Type(x, y)
}
}
return sum
}
func Rescue(input []string) int {
m := NewMap(input)
queue := PriorityQueue{
&Item{pos: coord{0, 0}, time: 0, equip: ToolTorch},
}
heap.Init(&queue)
type step struct {
coord coord
equip int
}
distances := map[step]int{
step{coord: coord{0, 0}, equip: ToolTorch}: 0,
}
for len(queue) > 0 {
item := (heap.Pop(&queue)).(*Item)
if item.pos.x == m.target.x && item.pos.y == m.target.y && item.equip == ToolTorch {
return item.time
}
// Check if we're wandering too far away
if item.pos.x > bailFactor*m.target.x || item.pos.y > bailFactor*m.target.y {
continue
}
if t, ok := distances[step{coord: item.pos, equip: item.equip}]; ok && t < item.time {
continue
}
for _, n := range m.Neighbors(item.pos, item.equip) {
d := step{coord: n.pos, equip: n.equip}
if t, ok := distances[step{coord: n.pos, equip: n.equip}]; !ok || item.time+n.time < t {
distances[d] = item.time + n.time
heap.Push(&queue, &Item{pos: n.pos, time: item.time + n.time, equip: n.equip})
}
}
}
return 0
}
func StdinToStringSlice() []string {
var input []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input = append(input, scanner.Text())
}
return input
}