67 lines
1.7 KiB
Nim
67 lines
1.7 KiB
Nim
import std/[math, strutils]
|
|
|
|
type
|
|
Number = object
|
|
x1, x2, y: int
|
|
value: int
|
|
|
|
Symbol = object
|
|
x, y: int
|
|
symbol: char
|
|
|
|
Schematic = object
|
|
numbers: seq[Number]
|
|
symbols: seq[Symbol]
|
|
|
|
func parse(input: string): Schematic =
|
|
let lines = input.splitLines()
|
|
for y, line in lines:
|
|
var nums: string
|
|
for x, ch in line:
|
|
if ch.isDigit():
|
|
nums = nums & ch
|
|
if nums.len > 0:
|
|
if x+1 == line.len or not line[x+1].isDigit():
|
|
let number = Number(x1: x-nums.len+1, x2: x, y: y,
|
|
value: nums.parseInt())
|
|
result.numbers.add(number)
|
|
nums = ""
|
|
continue
|
|
if ch != '.':
|
|
let symbol = Symbol(x: x, y: y, symbol: ch)
|
|
result.symbols.add(symbol)
|
|
|
|
func isAdjacent(n: Number, s: Symbol): bool =
|
|
(n.y - 1 <= s.y and s.y <= n.y + 1 and
|
|
n.x1 - 1 <= s.x and s.x <= n.x2 + 1)
|
|
|
|
func partNumbers(schematic: Schematic): seq[int] =
|
|
for number in schematic.numbers:
|
|
for symbol in schematic.symbols:
|
|
if number.isAdjacent(symbol):
|
|
result.add(number.value)
|
|
|
|
func gearRatios(schematic: Schematic): seq[int] =
|
|
for symbol in schematic.symbols:
|
|
if symbol.symbol != '*':
|
|
continue
|
|
block findNumbers:
|
|
var partNumbers: seq[int]
|
|
for number in schematic.numbers:
|
|
if number.isAdjacent(symbol):
|
|
partNumbers.add(number.value)
|
|
if partNumbers.len > 2:
|
|
break findNumbers
|
|
if partNumbers.len == 2:
|
|
result.add(partNumbers[0] * partNumbers[1])
|
|
|
|
proc p1(input: string) =
|
|
echo parse(input).partNumbers().sum()
|
|
|
|
proc p2(input: string) =
|
|
echo parse(input).gearRatios().sum()
|
|
|
|
when isMainModule:
|
|
let input = stdin.readAll()
|
|
p1(input)
|
|
p2(input)
|