Code of the Advent kind, maybe in Go this year
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

176 lines
4.6 KiB

package main
import (
"bufio"
"fmt"
"os"
"strings"
"strconv"
)
type maprange struct {
src uint64
dst uint64
}
type mapdir struct {
src string
dst string
}
type mapval struct {
cunt uint64
rnge maprange
}
type mapping struct {
dir mapdir
val []mapval
}
func parse(f *os.File) (seeds []uint64, maps []mapping) {
s := bufio.NewScanner(f)
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 = append(maps, curmap) }
curmap = mapping{}
inmap = true
split1 := strings.Index(line, "-to-")
split2 := strings.Index(line, " ")
src := line[:split1]
dst := line[split1 + 4:split2]
curmap.dir.src = src
curmap.dir.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 = append(maps, curmap) }
return
}
func part1(init_seeds []uint64, maps []mapping) uint64 {
seeds := append(make([]uint64, 0, len(init_seeds)), init_seeds...)
currency := "seed"
for currency != "location" {
var map_cur mapping
map_found := false
for _, v := range maps {
if v.dir.src == currency {
map_cur = v
map_found = true
break
}
}
if !map_found { break }
currency = map_cur.dir.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 []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" {
var map_cur mapping
map_found := false
for _, v := range maps {
if v.dir.src == currency {
map_cur = v
map_found = true
break
}
}
if !map_found { break }
currency = map_cur.dir.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
}
minrnge := seeds[0].src
for _, v := range seeds[1:] {
if v.src < minrnge { minrnge = v.src }
}
return minrnge
}
func main() {
f, _ := os.Open(os.Args[1])
seeds, maps := parse(f)
fmt.Println(part1(seeds, maps))
fmt.Println(part2(seeds, maps))
}