70 lines
1.8 KiB
Nim
70 lines
1.8 KiB
Nim
import std/[sequtils, strutils, sugar, threadpool]
|
|
|
|
type
|
|
CatMap = seq[tuple[srcStart, dstStart, range: int]]
|
|
|
|
func get(catMap: CatMap, thing: int): int =
|
|
for m in catMap:
|
|
let
|
|
low = m.srcStart
|
|
high = m.srcStart + m.range - 1
|
|
if low <= thing and thing <= high:
|
|
return m.dstStart + (thing - m.srcStart)
|
|
return thing
|
|
|
|
func location(catMaps: seq[CatMap], thing: int): int =
|
|
result = thing
|
|
for catMap in catMaps:
|
|
result = catMap.get(result)
|
|
|
|
func catMaps(lines: seq[string]): CatMap =
|
|
for line in lines[1..^1]:
|
|
let
|
|
sp = line.split(' ')
|
|
ints = sp.map(parseInt)
|
|
md = (srcStart: ints[1], dstStart: ints[0], range: ints[2])
|
|
result.add(md)
|
|
|
|
func parseSeeds(s: string): seq[int] = s.split(' ')[1..^1].map(parseInt)
|
|
|
|
proc p1(input: string) =
|
|
let
|
|
parts = input.strip().split("\n\n")
|
|
seeds = parts[0].parseSeeds()
|
|
maps = parts[1..^1].mapIt(splitLines(it)).map(catMaps)
|
|
echo seeds.mapIt(location(maps, it)).min()
|
|
|
|
func seedRanges(ranges: seq[int]): seq[(int, int)] =
|
|
for i in countup(0, ranges.high, 2):
|
|
let
|
|
start = ranges[i]
|
|
stop = start + ranges[i+1] - 1
|
|
result.add (start, stop)
|
|
|
|
func lowest(maps: seq[CatMap], start, stop: int): int =
|
|
result = high(int)
|
|
for seed in start..stop:
|
|
let loc = maps.location(seed)
|
|
if loc < result:
|
|
result = loc
|
|
|
|
proc p2(input: string) =
|
|
let
|
|
parts = input.strip().split("\n\n")
|
|
ranges = parts[0].parseSeeds()
|
|
maps = parts[1..^1].mapIt(splitLines(it)).map(catMaps)
|
|
|
|
let responses: seq[FlowVar[int]] = collect:
|
|
for (start, stop) in seedRanges(ranges):
|
|
spawn lowest(maps, start, stop)
|
|
sync()
|
|
|
|
let locations = collect:
|
|
for r in responses:
|
|
^r
|
|
echo min(locations)
|
|
|
|
when isMainModule:
|
|
let input = stdin.readAll()
|
|
p1(input)
|
|
p2(input) # takes a minute or two.
|