add 2020 and some cleanup

This commit is contained in:
2021-11-30 17:09:36 -08:00
parent efd1fa7e57
commit 804d6b6b92
41 changed files with 658 additions and 13309 deletions

20
2020/lib/loader.nim Normal file
View File

@ -0,0 +1,20 @@
import streams, strutils
func getFileName(daynum: int, suffix: string = ""): string =
if daynum < 10:
result = "0"
result = "data/" & result & $daynum & suffix & ".txt"
proc loadStrings*(daynum: int, suffix: string = ""): seq[string] =
var s = openFileStream(getFileName(daynum, suffix))
for line in s.lines():
result.add(line)
proc loadInts*(daynum: int): seq[int] =
var s = openFileStream(getFileName(daynum))
for line in s.lines():
let n = parseInt(line)
result.add(n)

44
2020/lib/util.nim Normal file
View File

@ -0,0 +1,44 @@
import std/macros
macro `<-`*(lhs: untyped, rhs: untyped): untyped =
# ensure that the left-hand side is a valid bracket expression e.g. [a, b, c]
let errmsg = "Invalid syntax for unpack operator: " & lhs.toStrLit().strVal()
if lhs.kind != nnkBracket:
error(errmsg, lhs)
for name in lhs:
if name.kind != nnkIdent:
error(errmsg, lhs)
# the result will be a check to ensure no index defects, followed by assignment statements
result = newNimNode(nnkStmtList, lineInfoFrom = lhs)
# first add a check to ensure that the container being unpacked has enough values
# this has to be done at runtime, since it's potentially unknown at compile time
let numIdents = lhs.len
let strRepr = lhs.toStrLit().strVal() & " <- " & rhs.toStrLit().strVal()
let lenCheck = quote do:
if `rhs`.len < `numIdents`:
raise newException(ValueError, "Not enough values to unpack: \"" & `strRepr` & "\"")
result.add(lenCheck)
var assign_from = rhs
# if the right-hand side is an expression, it might
# be expensive, so we save it to a temp variable
if rhs.kind != nnkIdent:
# repoint assign_src so that we end up using a temp variable
# instead of repeating the original expression a bunch of times
assign_from = ident("unpack_tmp_src")
# e.g. "let unpack_tmp_src = somestring.split()"
let declare_assign_src = newLetStmt(assign_from, rhs)
result.add(declare_assign_src)
# finally, inject the actual assignments
for i, name in lhs:
let assignment = quote do:
# expanded to e.g. "let a = someseq[0]"
let `name` = `assign_from`[`i`]
result.add(assignment)
proc showAddr*[T](x: T) = echo cast[uint64](unsafeAddr x)