adventofcode/2018/day22/day22.go

156 lines
2.5 KiB
Go

package main
import (
"bufio"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
)
var depth int
var target *Pos
func main() {
input := stdinToStringSlice()
reg, err := regexp.Compile("[^0-9]+")
if err != nil {
log.Fatal(err)
}
depth = Atoi(reg.ReplaceAllString(input[0], ""))
tgt := strings.Trim(input[1], "target: ")
tgtPts := strings.Split(tgt, ",")
target = NewPos(Atoi(tgtPts[0]), Atoi(tgtPts[1]), depth)
}
func part1() {
c := BuildCave(target)
var risk int
for y := 0; y <= target.y; y++ {
for x := 0; x <= target.x; x++ {
risk += c.risk(x, y, depth)
}
}
fmt.Println("= Part 1 =")
fmt.Println(risk)
}
func part2() {
// Find shortest path form 0,0 to target
// taking into account cost of changing gear
// when necessary
}
type Cave struct {
positions map[string]*Pos
}
func BuildCave(target *Pos) *Cave {
c := &Cave{
positions: make(map[string]*Pos),
}
c.addPos(target)
return c
}
func (c *Cave) addPos(p *Pos) {
c.positions[p.string()] = p
}
func (c *Cave) getPos(x, y, z int) *Pos {
var p *Pos
var ok bool
if p, ok = c.positions[c.buildKey(x, y, z)]; !ok {
p = NewPos(x, y, z)
c.addPos(p)
}
return p
}
func (c *Cave) buildKey(x, y, z int) string {
return fmt.Sprintf(
"(%d,%d,%d)",
x, y, z,
)
}
func (c *Cave) getGeoIndex(x, y, z int) int {
p := c.getPos(x, y, z)
if p.geo < 0 {
if x == 0 && y == 0 {
p.geo = 0
} else if x == target.x && y == target.y {
p.geo = 0
} else if y == 0 {
p.geo = x * 16807
} else if x == 0 {
p.geo = y * 48271
} else {
p.geo = c.erosion(x-1, y, z) * c.erosion(x, y-1, z)
}
}
return p.geo
}
func (c *Cave) erosion(x, y, z int) int {
p := c.getPos(x, y, z)
if p.erosion < 0 {
p.erosion = (c.getGeoIndex(x, y, z) + z) % 20183
}
return p.erosion
}
func (c *Cave) risk(x, y, z int) int {
return c.erosion(x, y, z) % 3
}
type Pos struct {
x, y, z int
geo, erosion int
}
func NewPos(x, y, z int) *Pos {
r := &Pos{
x: x,
y: y,
z: z,
geo: -1,
erosion: -1,
}
return r
}
func (p *Pos) equals(n *Pos) bool {
return p.x == n.x && p.y == n.y && p.z == n.z
}
func (p *Pos) string() string {
return fmt.Sprintf(
"(%d,%d,%d)",
p.x, p.y, p.z,
)
}
func stdinToStringSlice() []string {
var input []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input = append(input, scanner.Text())
}
return input
}
func Atoi(i string) int {
var ret int
var err error
if ret, err = strconv.Atoi(i); err != nil {
log.Fatal("Invalid Atoi: " + i)
}
return ret
}