|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
|
|
|
type maprange struct {
|
|
|
|
src uint64
|
|
|
|
dst uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
type mapval struct {
|
|
|
|
cunt uint64
|
|
|
|
rnge maprange
|
|
|
|
}
|
|
|
|
|
|
|
|
type mapping struct {
|
|
|
|
src string
|
|
|
|
dst string
|
|
|
|
val []mapval
|
|
|
|
}
|
|
|
|
|
|
|
|
func parse(f *os.File) (seeds []uint64, maps map[string]mapping) {
|
|
|
|
s := bufio.NewScanner(f)
|
|
|
|
|
|
|
|
maps = make(map[string]mapping)
|
|
|
|
inmap := false
|
|
|
|
var curmap mapping
|
|
|
|
for s.Scan() {
|
|
|
|
line := s.Text()
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(line, "seeds: "):
|
|
|
|
thing := strings.Split(line[7:], " ")
|
|
|
|
for _, v := range thing {
|
|
|
|
val, _ := strconv.ParseUint(v, 0, 64)
|
|
|
|
seeds = append(seeds, val)
|
|
|
|
}
|
|
|
|
|
|
|
|
case strings.HasSuffix(line, " map:"):
|
|
|
|
if inmap { maps[curmap.src] = curmap }
|
|
|
|
curmap = mapping{}
|
|
|
|
inmap = true
|
|
|
|
|
|
|
|
split1 := strings.Index(line, "-to-")
|
|
|
|
split2 := strings.Index(line, " ")
|
|
|
|
src := line[:split1]
|
|
|
|
dst := line[split1 + 4:split2]
|
|
|
|
curmap.src = src
|
|
|
|
curmap.dst = dst
|
|
|
|
|
|
|
|
case strings.Count(line, " ") >= 2 && inmap:
|
|
|
|
thing := strings.Split(line, " ")
|
|
|
|
var val mapval
|
|
|
|
val.rnge.dst, _ = strconv.ParseUint(thing[0], 0, 64)
|
|
|
|
val.rnge.src, _ = strconv.ParseUint(thing[1], 0, 64)
|
|
|
|
val.cunt, _ = strconv.ParseUint(thing[2], 0, 64)
|
|
|
|
curmap.val = append(curmap.val, val)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if inmap { maps[curmap.src] = curmap }
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func part1(init_seeds []uint64, maps map[string]mapping) uint64 {
|
|
|
|
seeds := append(make([]uint64, 0, len(init_seeds)), init_seeds...)
|
|
|
|
|
|
|
|
currency := "seed"
|
|
|
|
for currency != "location" {
|
|
|
|
map_cur := maps[currency]
|
|
|
|
currency = map_cur.dst
|
|
|
|
|
|
|
|
for i, v := range seeds {
|
|
|
|
for _, x := range map_cur.val {
|
|
|
|
tmp := v - x.rnge.src
|
|
|
|
if tmp > 0 && tmp < x.cunt {
|
|
|
|
v += x.rnge.dst - x.rnge.src
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
seeds[i] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
min := seeds[0]
|
|
|
|
for _, v := range seeds[1:] {
|
|
|
|
if v < min { min = v }
|
|
|
|
}
|
|
|
|
return min
|
|
|
|
}
|
|
|
|
|
|
|
|
func part2(init_seeds []uint64, maps map[string]mapping) uint64 {
|
|
|
|
seeds := make([]maprange, 0)
|
|
|
|
for i, _ := range init_seeds {
|
|
|
|
if i % 2 == 1 { continue }
|
|
|
|
var rnge maprange
|
|
|
|
rnge.src = init_seeds[i + 0]
|
|
|
|
rnge.dst = rnge.src + init_seeds[i + 1]
|
|
|
|
seeds = append(seeds, rnge)
|
|
|
|
}
|
|
|
|
|
|
|
|
currency := "seed"
|
|
|
|
for currency != "location" {
|
|
|
|
map_cur := maps[currency]
|
|
|
|
currency = map_cur.dst
|
|
|
|
|
|
|
|
newseedrnge := make([]maprange, 0)
|
|
|
|
for _, v := range seeds {
|
|
|
|
for _, x := range map_cur.val {
|
|
|
|
src := x.rnge.src
|
|
|
|
end := x.rnge.src + x.cunt
|
|
|
|
if src <= v.src && v.src < end && src <= v.dst && v.dst < end {
|
|
|
|
newseedrnge = append(newseedrnge, maprange{
|
|
|
|
src: v.src + x.rnge.dst - x.rnge.src,
|
|
|
|
dst: v.dst + x.rnge.dst - x.rnge.src,
|
|
|
|
})
|
|
|
|
v.src = v.dst
|
|
|
|
} else if src <= v.src && v.src < end {
|
|
|
|
newseedrnge = append(newseedrnge, maprange{
|
|
|
|
src: v.src + x.rnge.dst - x.rnge.src,
|
|
|
|
dst: x.rnge.dst + x.cunt,
|
|
|
|
})
|
|
|
|
v.src = end
|
|
|
|
} else if src <= v.dst && v.dst < end {
|
|
|
|
newseedrnge = append(newseedrnge, maprange{
|
|
|
|
src: x.rnge.dst,
|
|
|
|
dst: v.dst + x.rnge.dst - x.rnge.src,
|
|
|
|
})
|
|
|
|
v.dst = src
|
|
|
|
}
|
|
|
|
if v.src == v.dst { break }
|
|
|
|
}
|
|
|
|
if v.src != v.dst { newseedrnge = append(newseedrnge, v) }
|
|
|
|
}
|
|
|
|
seeds = newseedrnge
|
|
|
|
}
|
|
|
|
|
|
|
|
min := seeds[0].src
|
|
|
|
for _, v := range seeds[1:] {
|
|
|
|
if v.src < min { min = v.src }
|
|
|
|
}
|
|
|
|
return min
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
f, _ := os.Open(os.Args[1])
|
|
|
|
|
|
|
|
seeds, maps := parse(f)
|
|
|
|
fmt.Println(part1(seeds, maps))
|
|
|
|
fmt.Println(part2(seeds, maps))
|
|
|
|
}
|