Cleanup and add day 8 part 2
This commit is contained in:
parent
b3bf458d3a
commit
b48d6aaa5f
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue