Cleanup and add day 8 part 2

This commit is contained in:
Daniel Flanagan 2020-12-08 06:55:34 -06:00
parent b3bf458d3a
commit b48d6aaa5f
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
3 changed files with 52 additions and 36 deletions

View file

@ -8,5 +8,5 @@ proc solve_for_day(n: int) {.used.} =
echo solvers[n]() echo solvers[n]()
when isMainModule: when isMainModule:
# solve_all() solve_all()
solve_for_day(8) # solve_for_day(8)

View file

@ -7,6 +7,7 @@ nc <- {\d} ' ' c ' bag' 's'? ', '?
c <- {\ident ' ' \ident} c <- {\ident ' ' \ident}
""" """
let target = "shiny gold"
iterator asParsed(s: Stream): (string, seq[string]) = iterator asParsed(s: Stream): (string, seq[string]) =
for l in s.lines: for l in s.lines:
if l =~ parser: if l =~ parser:
@ -17,10 +18,8 @@ iterator asParsed(s: Stream): (string, seq[string]) =
proc walkUp(t: TableRef[string, HashSet[string]], tar: string): HashSet[string] = proc walkUp(t: TableRef[string, HashSet[string]], tar: string): HashSet[string] =
if t.contains(tar): if t.contains(tar):
let parents = t[tar] let parents = t[tar]
echo parents
result = parents result = parents
for p in parents: for p in parents:
echo p
result = result + t.walkUp(p) result = result + t.walkUp(p)
proc part1*(s: Stream): int = proc part1*(s: Stream): int =
@ -30,7 +29,7 @@ proc part1*(s: Stream): int =
for p in parents: for p in parents:
if t.contains(p): t[p].incl(key) if t.contains(p): t[p].incl(key)
else: t[p] = [key].toHashSet() else: t[p] = [key].toHashSet()
t.walkUp("shiny gold").len t.walkUp(target).len
proc walkDown(t: TableRef[string, TableRef[string, int]], tar: string): int = proc walkDown(t: TableRef[string, TableRef[string, int]], tar: string): int =
let children = t[tar] let children = t[tar]
@ -43,9 +42,8 @@ iterator asPairChunks(s: seq[string]): (string, int) =
proc part2*(s: Stream): int = proc part2*(s: Stream): int =
var t = newTable[string, TableRef[string, int]]() var t = newTable[string, TableRef[string, int]]()
for (key, parsed) in s.asParsed: for (key, parsed) in s.asParsed:
echo key, parsed
var innert = newTable[string, int]() var innert = newTable[string, int]()
for (innerkey, n) in parsed.asPairChunks: for (innerkey, n) in parsed.asPairChunks:
innert[innerkey] = n innert[innerkey] = n
t[key] = innert t[key] = innert
t.walkDown "shiny gold" t.walkDown target

View file

@ -1,4 +1,4 @@
import streams, strutils, sequtils, sets import streams, strutils, sequtils, sets, options, strformat, tables
type type
InstructionType = enum nop acc jmp InstructionType = enum nop acc jmp
@ -9,48 +9,66 @@ type
bootcode: seq[Instruction] bootcode: seq[Instruction]
acc: int acc: int
pointer: int pointer: int
running: bool
proc newHandheld(bootcode: seq[Instruction], acc = 0, pointer = 0, running = true): HandheldState = proc `$`(i: Instruction): string = return fmt"{i.instruction} {i.arg}"
HandheldState(bootcode: bootcode, acc: acc, pointer: pointer, running: running) proc `$`(h: HandheldState): string = return fmt"@{h.pointer} ({h.acc}): {h.bootcode}"
proc statusString(h: HandheldState): string =
let i = h.bootcode[h.pointer]
fmt"{h.pointer}: {i.instruction} {i.arg} ({h.acc})"
proc newHandheld(bootcode: seq[Instruction], acc = 0, pointer = 0): HandheldState =
HandheldState(bootcode: bootcode, acc: acc, pointer: pointer)
proc instructions(s: Stream): seq[Instruction] = proc instructions(s: Stream): seq[Instruction] =
toSeq(s.lines).mapIt(it.split).mapIt(Instruction(instruction: parseEnum[InstructionType](it[0]), arg: parseInt(it[1].replace("+")))) toSeq(s.lines).mapIt(it.split).mapIt(Instruction(instruction: parseEnum[InstructionType](it[0]), arg: parseInt(it[1].replace("+"))))
proc stepHandheld(state: var HandheldState) = proc stepHandheld(state: var HandheldState): bool =
if state.pointer >= state.bootcode.len: if state.pointer >= state.bootcode.len: return true
echo "Reached end of instructions"
state.running = false
let i = state.bootcode[state.pointer] let i = state.bootcode[state.pointer]
case i.instruction: case i.instruction:
of acc: inc state.acc, i.arg of acc: inc state.acc, i.arg
of jmp: inc state.pointer, i.arg; return of jmp: inc state.pointer, i.arg; return false
else: discard else: discard
inc state.pointer inc state.pointer
proc bootHandheld(h: var HandheldState): bool =
var hasRun = initHashSet[int]()
while h.pointer <= h.bootcode.len:
if h.stepHandheld(): return true
if hasRun.contains h.pointer: return false
hasRun.incl h.pointer
true
proc part1*(s: Stream): int = proc part1*(s: Stream): int =
var hasRun = initHashSet[int]() var h = s.instructions.newHandheld
var handheld = newHandheld(s.instructions) if not h.bootHandheld: return h.acc
while handheld.running:
stepHandheld handheld
if hasRun.contains handheld.pointer: return handheld.acc
hasRun.incl handheld.pointer
proc correctingHandheld(state: var HandheldState) = proc flipped(h: var HandheldState): HandheldState =
if state.pointer >= state.bootcode.len: var nbc = h.bootcode.deepCopy
echo "Reached end of instructions" case h.bootcode[h.pointer].instruction:
state.running = false of nop: nbc[h.pointer].instruction = jmp
let i = state.bootcode[state.pointer] of jmp: nbc[h.pointer].instruction = nop
case i.instruction:
of acc: inc state.acc, i.arg
of jmp: inc state.pointer, i.arg; return
else: discard else: discard
inc state.pointer nbc.newHandheld
proc altHandheld(h: var HandheldState): Option[HandheldState] =
case h.bootcode[h.pointer].instruction:
of acc: return none(HandheldState)
of jmp, nop: some(h.flipped)
proc part2*(s: Stream): int = proc part2*(s: Stream): int =
var alts = initTable[int, HandheldState]()
var h = s.instructions.newHandheld
var hasRun = initHashSet[int]() var hasRun = initHashSet[int]()
var handheld = newHandheld(s.instructions) while h.pointer <= h.bootcode.len:
while handheld.running: var alt = h.altHandheld
stepHandheld handheld if alt.isSome: alts[h.pointer] = alt.get
if hasRun.contains handheld.pointer: return handheld.acc discard h.stepHandheld()
hasRun.incl handheld.pointer if hasRun.contains h.pointer: break
hasRun.incl h.pointer
#for i in 1..<alts.len:
var c = 0
for k,v in alts.pairs:
var ah = alts[k]
if ah.bootHandheld: return ah.acc
inc c