2023 Day 19 Part 1
This commit is contained in:
parent
7cb7dc5b7a
commit
c60d0b9ee7
1 changed files with 150 additions and 0 deletions
150
2023/day19.nim
Normal file
150
2023/day19.nim
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
import std/algorithm
|
||||
import std/bitops
|
||||
import std/deques
|
||||
import std/enumerate
|
||||
import std/heapqueue
|
||||
import std/math
|
||||
import std/options
|
||||
import std/sequtils
|
||||
import std/sets
|
||||
import std/strscans
|
||||
import std/strutils
|
||||
import std/sugar
|
||||
import std/tables
|
||||
import std/terminal
|
||||
import std/times
|
||||
|
||||
proc dbg[T](v: T): T = (echo(v); v)
|
||||
|
||||
func empty[T](v: seq[T]): bool = v.len == 0
|
||||
|
||||
proc split[T](v: seq[T], pred: proc(elt: T): bool {.noSideEffect.}): seq[seq[T]] =
|
||||
var current: seq[T]
|
||||
for elt in v:
|
||||
if pred(elt):
|
||||
result.add current
|
||||
current = @[]
|
||||
else:
|
||||
current.add elt
|
||||
result.add current
|
||||
|
||||
func join[T](parts: seq[seq[T]], sep: T): seq[T] =
|
||||
if parts.len > 0:
|
||||
result &= parts[0]
|
||||
|
||||
for part in parts[1..^1]:
|
||||
result.add sep
|
||||
result &= part
|
||||
|
||||
###################
|
||||
|
||||
type Op = enum
|
||||
None
|
||||
Lt
|
||||
Gt
|
||||
|
||||
func parseOp(c: char): Op =
|
||||
case c:
|
||||
of '<': Lt
|
||||
of '>': Gt
|
||||
else: raise newException(ValueError, $c)
|
||||
|
||||
type Step = tuple
|
||||
attr: char
|
||||
op: Op
|
||||
val: int
|
||||
dest: string
|
||||
|
||||
func parseStep(text: string): Step =
|
||||
var op: char
|
||||
if scanf(text, "$c$c$i:$+$.", result.attr, op, result.val, result.dest):
|
||||
result.op = op.parseOp
|
||||
return
|
||||
|
||||
if scanf(text, "$w$.", result.dest):
|
||||
result.op = None
|
||||
return
|
||||
|
||||
raise newException(ValueError, text)
|
||||
|
||||
type Workflow = tuple
|
||||
name: string
|
||||
steps: seq[Step]
|
||||
|
||||
func parseWorkflow(text: string): Workflow =
|
||||
var steps: string
|
||||
if not scanf(text, "$+{$+}$.", result.name, steps):
|
||||
raise newException(ValueError, text)
|
||||
result.steps = steps.split(',').map(parseStep)
|
||||
|
||||
type Part = tuple
|
||||
attrs: Table[char, int]
|
||||
|
||||
func parseAttr(text: string): (char, int) =
|
||||
if not scanf(text, "$c=$i$.", result[0], result[1]):
|
||||
raise newException(ValueError, text)
|
||||
|
||||
func parseAttrs(text: string): Table[char, int] =
|
||||
for (a, v) in text.split(',').map(parseAttr):
|
||||
result[a] = v
|
||||
|
||||
func parsePart(line: string): Part =
|
||||
var attrs: string
|
||||
if not scanf(line, "{$+}$.", attrs):
|
||||
raise newException(ValueError, line)
|
||||
result.attrs = attrs.parseAttrs
|
||||
|
||||
type System = tuple
|
||||
workflows: Table[string, Workflow]
|
||||
parts: seq[Part]
|
||||
|
||||
func parseSystem(text: string): System =
|
||||
let sections = text.split("\n\n")
|
||||
assert sections.len == 2
|
||||
|
||||
for w in sections[0].strip.splitLines.map(parseWorkflow):
|
||||
result.workflows[w.name] = w
|
||||
|
||||
result.parts = sections[1].strip.splitLines.map(parsePart)
|
||||
|
||||
func apply(w: Workflow, p: Part): string =
|
||||
for s in w.steps:
|
||||
case s.op:
|
||||
of None:
|
||||
return s.dest
|
||||
of Lt:
|
||||
if p.attrs[s.attr] < s.val:
|
||||
return s.dest
|
||||
of Gt:
|
||||
if p.attrs[s.attr] > s.val:
|
||||
return s.dest
|
||||
|
||||
func accepted(sys: System, part: Part): bool =
|
||||
var w = "in"
|
||||
while w != "R" and w != "A":
|
||||
w = sys.workflows[w].apply(part)
|
||||
w == "A"
|
||||
|
||||
func rating(p: Part): int =
|
||||
for v in p.attrs.values:
|
||||
result.inc v
|
||||
|
||||
proc part1(input: string): int =
|
||||
let text = readFile(input)
|
||||
let system = parseSystem(text)
|
||||
|
||||
for part in system.parts:
|
||||
if system.accepted(part):
|
||||
result.inc part.rating
|
||||
|
||||
###################
|
||||
|
||||
proc timed[T](f: () -> T): T =
|
||||
let start = cpuTime()
|
||||
result = f()
|
||||
echo "Time :", cpuTime() - start
|
||||
|
||||
echo timed(proc(): int = part1("input/test.txt"))
|
||||
echo timed(proc(): int = part1("input/day19.txt"))
|
||||
# echo timed(proc(): int = part2("input/test.txt"))
|
||||
# echo timed(proc(): int = part2("input/day19.txt"))
|
||||
Loading…
Reference in a new issue