23 files changed, 126 insertions(+), 72 deletions(-)
D 1/day1
D 2/day2
D 3/day3
D 4/day4
D 5/day5
M README.md
A aoc
A aoc.nim
R 1/day1.nim => day1.nim
R 2/day2.nim => day2.nim
R 3/day3.nim => day3.nim
R 4/day4.nim => day4.nim
R 5/day5.nim => day5.nim
A helpers.nim
R 1/day1part1 => puzzles/day1.txt
R 2/day2puzzle => puzzles/day2.txt
R 3/puzzle => puzzles/day3.txt
R 4/puzzle => puzzles/day4.txt
R 5/puzzle => puzzles/day5.txt
R 1/day1sample => samples/day1.txt
R 2/day2sample => samples/day2.txt
R 3/sample => samples/day3.txt
R 4/sample => samples/day4.txt
D 1/day1 => 1/day1 +0 -0
D 2/day2 => 2/day2 +0 -0
D 3/day3 => 3/day3 +0 -0
D 4/day4 => 4/day4 +0 -0
D 5/day5 => 5/day5 +0 -0
M README.md => README.md +5 -1
@@ 1,3 1,7 @@
# aoc2020
-Advent of Code 2020 in Nim.>
\ No newline at end of file
+Advent of Code 2020 in Nim.
+
+## Usage
+
+Install [Nim](https://nim-lang.org/install.html). Run `nim compile --run aoc.nim 1`. Pass the desired day to execute. It will place the `aoc` binary in the current directio for subsequent runs with, e.g. `./aoc 1`.<
\ No newline at end of file
A aoc => aoc +0 -0
A aoc.nim => aoc.nim +56 -0
@@ 0,0 1,56 @@
+# This file is the main interface.
+import day1, day2, day3, day4, day5
+import os, strutils
+
+proc getDay(): int =
+ let params = commandLineParams()
+ if len(params) != 1:
+ stderr.writeLine("Usage: <aoc> X - please pass exactly one number. Pass 0 to run all")
+ quit(1)
+
+ parseInt(params[0])
+
+proc runDay(day: int) =
+ let min = 0
+ let max = 5
+ if day < min or day > max:
+ stderr.writeLine("Must pass day in ", min, " to ", max, " inclusive.")
+ quit(1)
+
+ case day:
+ of 0:
+ # TODO can this be automated? A macro, perhaps...
+ echo "Day 1:"
+ day1()
+ echo "\nDay 2:"
+ day2()
+ echo "\nDay 3:"
+ day3()
+ echo "\nDay 4:"
+ day4()
+ echo "\nDay 5:"
+ day5()
+ of 1:
+ day1()
+ of 2:
+ day2()
+ of 3:
+ day3()
+ of 4:
+ day4()
+ of 5:
+ day5()
+ else: echo "Unreachable..."
+
+proc main() =
+ echo "Advent of Code 2020!\n"
+ let day = getDay()
+ if day == 0:
+ echo "Running all days..."
+ else:
+ echo "Running day ", day, "..."
+ echo()
+ runDay(day)
+ quit(0)
+
+main()<
\ No newline at end of file
R 1/day1.nim => day1.nim +13 -23
@@ 1,15 1,5 @@
-import strutils
-
-proc readFile(name: string): seq[int] =
- let f = open(name)
- defer: f.close()
-
- var ret: seq[int] = @[]
-
- for line in f.lines:
- ret.add(parseInt(line))
-
- ret
+import helpers
+import sequtils, strutils
proc findPair(target: int, vals: openArray[int]): (int, int) =
for idx, x in vals:
@@ 34,16 24,16 @@ proc findThree(target: int, vals: openArray[int]): (int, int, int) =
# what on fail
(-1, -1, -1)
-proc part1() =
- let ret = readFile("day1part1")
- let (x, y) = findPair(2020, ret)
- echo "Results: ", x, " and ", y, ". Multiplied: ", x * y
-
-part1()
+proc part1(input: openArray[int]) =
+ let (x, y) = findPair(2020, input)
+ echo "Part 1: ", x, " and ", y, ". Multiplied: ", x * y
-proc part2() =
- let ret = readFile("day1part1")
- let (x, y, z) = findThree(2020, ret)
- echo "Results: ", x, ", ", y, ", and ", z, ". Multiplied: ", x * y * z
+proc part2(input: openArray[int]) =
+ let (x, y, z) = findThree(2020, input)
+ echo "Part 2: ", x, ", ", y, ", and ", z, ". Multiplied: ", x * y * z
-part2()>
\ No newline at end of file
+proc day1*() =
+ let raw = readLinesToStrSeq("puzzles/day1.txt")
+ let input = map(raw, proc(s: string): int = parseInt(s))
+ part1(input)
+ part2(input)<
\ No newline at end of file
R 2/day2.nim => day2.nim +12 -16
@@ 1,16 1,6 @@
+import helpers
import strutils
-proc readLines(name: string): seq[string] =
- let f = open(name)
- defer: f.close()
-
- var ret: seq[string] = @[]
-
- for line in f.lines:
- ret.add(line)
-
- ret
-
proc part1(str: string): bool =
# split into parts
# store min, max, char
@@ 64,8 54,14 @@ proc part2(str: string): bool =
if pos1res and pos2res: return false
pos1res or pos2res
-let lines = readLines("day2puzzle")
-var total = 0
-for line in lines:
- if part2(line): total += 1
-echo total>
\ No newline at end of file
+proc day2*() =
+ let lines = readLinesToStrSeq("puzzles/day2.txt")
+ var total = 0
+ for line in lines:
+ if part1(line): total += 1
+ echo "Part 1: ", total
+
+ total = 0
+ for line in lines:
+ if part2(line): total += 1
+ echo "Part 2: ", total<
\ No newline at end of file
R 3/day3.nim => day3.nim +12 -13
@@ 1,13 1,4 @@
-proc readLines(name: string): seq[string] =
- let f = open(name)
- defer: f.close()
-
- var ret: seq[string] = @[]
-
- for line in f.lines:
- ret.add(line)
-
- ret
+import helpers
type
Row = seq[bool]
@@ 42,7 33,7 @@ type
proc newMap(filename: string): Map =
Map(
- grid: inputToGrid(readLines(filename)),
+ grid: inputToGrid(readLinesToStrSeq(filename)),
position: (0, 0)
)
@@ 72,5 63,13 @@ proc traverse(map: Map, right: int, down: int): int =
proc tryAllSlopes(map: Map): int =
map.traverse(1, 1) * map.traverse(3, 1) * map.traverse(5, 1) * map.traverse(7, 1) * map.traverse(1, 2)
-var map = newMap("puzzle")
-echo map.tryAllSlopes()>
\ No newline at end of file
+proc part1(input: Map) =
+ echo "Part 1: ", input.traverse(3, 1)
+
+proc part2(input: Map) =
+ echo "Part 2: ", input.tryAllSlopes()
+
+proc day3*() =
+ var map = newMap("puzzles/day3.txt")
+ part1(map)
+ part2(map)<
\ No newline at end of file
R 4/day4.nim => day4.nim +13 -15
@@ 1,6 1,7 @@
import options, re, strutils
-proc readLines(name: string): seq[string] =
+# Don't use the helper for this one - different delimiiter.
+proc readLinesToSeqStr(name: string): seq[string] =
var ret: seq[string] = @[]
# Delimiter is two newlines for this
@@ 22,12 23,6 @@ type
pid: Option[string]
cid: Option[string]
-proc `$`(p: Passport): string =
- if p.pid.isSome:
- p.pid.get()
- else:
- "No ID"
-
proc newPassport(): Passport =
Passport(byr: none(string), iyr: none(string), eyr: none(string), hgt: none(
string), hcl: none(string), ecl: none(string), pid: none(string),
@@ 94,16 89,19 @@ proc isValidPartTwo(p: Passport): bool =
validateHcl(p.hcl) and validateEcl(p.ecl) and validatePid(p.pid)
proc generatePassports(filename: string): seq[Passport] =
- let strs = readLines(filename)
+ let strs = readLinesToSeqStr(filename)
var ret = newSeq[Passport]()
for str in strs:
ret.add(passportFromString(str))
ret
-let passports = generatePassports("puzzle")
-echo passports
-var res = 0
-for pass in passports:
- if pass.isValidPartTwo(): res += 1
-
-echo res
+proc day4*() =
+ let passports = generatePassports("puzzles/day4.txt")
+ var res = 0
+ for pass in passports:
+ if pass.isValidPartOne(): res += 1
+ echo "Part 1: ", res
+ res = 0
+ for pass in passports:
+ if pass.isValidPartTwo(): res += 1
+ echo "Part 2: ", res
R 5/day5.nim => day5.nim +5 -4
@@ 56,7 56,7 @@ proc findSeat(str: string): int =
proc getAllIds(): seq[int] =
- let allPasses = readLines("puzzle")
+ let allPasses = readLines("puzzles/day5.txt")
map(allPasses, proc(s: string): int = findSeat(s))
proc findHighest(allIds: openArray[int]): int =
@@ 68,9 68,10 @@ proc findMissing(allIds: seq[int]): int =
for idx, n in a:
if a[idx + 1] != n + 1: return n + 1
-var allIds = getAllIds()
-echo findHighest(allIds)
-echo findMissing(allIds)
+proc day5*() =
+ var allIds = getAllIds()
+ echo "Part 1: ", findHighest(allIds)
+ echo "Part 2: ", findMissing(allIds)
# echo findSeat("FBFBBFFRLR") # (44, 5) - 357
# echo findSeat("BFFFBBFRRR") # (70, 7) - 567
A helpers.nim => helpers.nim +10 -0
@@ 0,0 1,10 @@
+proc readLinesToStrSeq*(name: string): seq[string] =
+ let f = open(name)
+ defer: f.close()
+
+ var ret: seq[string] = @[]
+
+ for line in f.lines:
+ ret.add(line)
+
+ ret<
\ No newline at end of file
R 1/day1part1 => puzzles/day1.txt +0 -0
R 2/day2puzzle => puzzles/day2.txt +0 -0
R 3/puzzle => puzzles/day3.txt +0 -0
R 4/puzzle => puzzles/day4.txt +0 -0
R 5/puzzle => puzzles/day5.txt +0 -0
R 1/day1sample => samples/day1.txt +0 -0
R 2/day2sample => samples/day2.txt +0 -0
R 3/sample => samples/day3.txt +0 -0
R 4/sample => samples/day4.txt +0 -0