day05
This commit is contained in:
		
							parent
							
								
									209f0ff0cc
								
							
						
					
					
						commit
						4bd4d1b4a1
					
				
					 1 changed files with 70 additions and 0 deletions
				
			
		
							
								
								
									
										70
									
								
								2023/day05.nim
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								2023/day05.nim
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,70 @@
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue