Lots of cleanup for nim solutions and day 2 solutions in nim
This commit is contained in:
parent
ff44a85cce
commit
ea0a467b5c
1
2021/.gitignore
vendored
1
2021/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
*.input
|
||||
build
|
||||
|
|
12
2021/2.ts
12
2021/2.ts
|
@ -1,11 +1,18 @@
|
|||
import { collectArray, inputLines, measureDuration } from "./common.ts";
|
||||
const input = await collectArray(await inputLines("2"));
|
||||
|
||||
type SubmarineCommand = ["forward", number] | ["up", number] | ["down", number];
|
||||
|
||||
// function parseSubmarineCommand(command: string): SubmarineCommand {
|
||||
// let [cmd, arg] = command.split(" ", 2);
|
||||
// cmd = ["forward", "up", "down"].includes(cmd) ? cmd : "up";
|
||||
// return [cmd, parseInt(arg)];
|
||||
// }
|
||||
|
||||
export function part1(input: string[]): number {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
for (const line of input) {
|
||||
console.log(line);
|
||||
if (line.startsWith("forward ")) {
|
||||
x += parseInt(line.substr(8));
|
||||
} else if (line.startsWith("up ")) {
|
||||
|
@ -24,7 +31,6 @@ export function part2(input: string[]): number {
|
|||
let y = 0;
|
||||
let aim = 0;
|
||||
for (const line of input) {
|
||||
console.log(line);
|
||||
if (line.startsWith("forward ")) {
|
||||
const arg = parseInt(line.substr(8));
|
||||
x += arg;
|
||||
|
@ -32,11 +38,9 @@ export function part2(input: string[]): number {
|
|||
} else if (line.startsWith("up ")) {
|
||||
const arg = parseInt(line.substr(3));
|
||||
aim -= arg;
|
||||
// y -= arg;
|
||||
} else if (line.startsWith("down ")) {
|
||||
const arg = parseInt(line.substr(5));
|
||||
aim += arg;
|
||||
// y += arg;
|
||||
}
|
||||
}
|
||||
return x * y;
|
||||
|
|
35
2021/common.nim
Normal file
35
2021/common.nim
Normal file
|
@ -0,0 +1,35 @@
|
|||
import std/[streams, sequtils, strutils, sugar, strformat, times, httpclient, os]
|
||||
|
||||
const YEAR = getEnv("AOC_YEAR", "2021").parseInt()
|
||||
proc getCookie(): string = "~/.advent-of-code-auth-cookie".expandTilde().readFile()
|
||||
proc getCacheDir(): string = joinPath(expandTilde("~/.cache"), fmt"/aoc{YEAR}")
|
||||
proc inputFilePath(day: int): string = joinPath(getCacheDir(), fmt"{day}.input")
|
||||
|
||||
proc fetchInput(day: int, filePath: string): StringStream =
|
||||
let client = newHttpClient()
|
||||
client.headers = {"cookie": getCookie()}.newHttpHeaders()
|
||||
let content = client.getContent(fmt"https://adventofcode.com/{YEAR}/day/{day}/input")
|
||||
filePath.writeFile(content)
|
||||
content.newStringStream()
|
||||
|
||||
proc inputStream*(day: int): Stream =
|
||||
getCacheDir().createDir()
|
||||
let cachedFile = day.inputFilePath()
|
||||
if not cachedFile.fileExists(): day.fetchInput(cachedFile)
|
||||
else: openFileStream(cachedFile)
|
||||
|
||||
proc toInts*(s: seq[string]): seq[int] = s.map(parseInt)
|
||||
|
||||
proc loadInput*(day: int): seq[string] =
|
||||
result = collect:
|
||||
for l in day.inputStream().lines(): l
|
||||
|
||||
template time*(i: string, body: untyped): untyped =
|
||||
let start = cpuTime()
|
||||
body
|
||||
let stop = cpuTime()
|
||||
let diff = $((stop - start) * 1000)
|
||||
echo i & " took " & diff & "ms to calculate solution"
|
||||
when not defined(release):
|
||||
echo "NOTE: This is not a real measurement of performance. Compile in release mode with -d:release for best performance."
|
||||
# jkp: {(stop - start) * 1000} ms to calculate solution: {result}"
|
38
2021/one.nim
38
2021/one.nim
|
@ -1,31 +1,15 @@
|
|||
import std/[streams, strutils, sugar, strformat, times]
|
||||
import ./common
|
||||
|
||||
iterator inputForDay(day: int): int =
|
||||
var stream: FileStream = fmt"/home/daniel/.home/.config/aoc2021/{day}.input".openFileStream
|
||||
for s in stream.lines():
|
||||
yield s.parseInt
|
||||
|
||||
proc part1(inputs: seq[int], dist=1): int =
|
||||
result = 0
|
||||
var i = dist
|
||||
var x = inputs.len()-1
|
||||
while i <= x:
|
||||
proc countDepthIncreases(inputs: seq[int], dist=1): int =
|
||||
for i in dist..<inputs.len():
|
||||
if inputs[i] > inputs[i-dist]: inc result
|
||||
inc i
|
||||
|
||||
let dd1 = epochTime()
|
||||
var input = collect(newSeq):
|
||||
for i in inputForDay(1): i
|
||||
let input = 1.loadInput().toInts()
|
||||
time("countDepthIncreases part 1"): echo input.countDepthIncreases()
|
||||
time("countDepthIncreases part 2"): echo input.countDepthIncreases(3)
|
||||
|
||||
let dd2 = epochTime()
|
||||
echo &"{(dd2 - dd1) * 1000} ms (to load input)"
|
||||
echo "Part 1"
|
||||
let d1 = epochTime()
|
||||
echo part1(input)
|
||||
let d2 = epochTime()
|
||||
echo &"{(d2 - d1) * 1000} ms (to calculate solution)"
|
||||
echo "Part 2"
|
||||
let d21 = epochTime()
|
||||
echo part1(input,3)
|
||||
let d22 = epochTime()
|
||||
echo &"{(d22 - d21) * 1000} ms (to calculate solution)"
|
||||
when not defined(release):
|
||||
static:
|
||||
let testInputs = @[199, 200, 208, 210, 200, 207, 240, 269, 260, 263]
|
||||
doAssert testInputs.countDepthIncreases() == 7
|
||||
doAssert testInputs.countDepthIncreases(3) == 5
|
||||
|
|
|
@ -12,16 +12,34 @@ Specifically, here's my `deno --version` output:
|
|||
|
||||
Enjoy!
|
||||
|
||||
**EDIT**: Since performance is not what I would like, it looks like I'm also doing some of these in nim.
|
||||
|
||||
## Usage
|
||||
|
||||
Run these solutions like so:
|
||||
|
||||
deno run --unstable --allow-all $DAY.ts
|
||||
|
||||
And the nim ones like so:
|
||||
|
||||
nim c -d:release -d:ssl --run $DAYMODULE.nim
|
||||
|
||||
And if you want to measure memory usage:
|
||||
|
||||
mkdir -p build
|
||||
deno compile --output build/$DAY --unstable --allow-all $DAY.ts
|
||||
/usr/bin/time -v ./build/$DAY
|
||||
|
||||
Or
|
||||
|
||||
mkdir -p build
|
||||
nim c -d:release -d:ssl --outdir:build $DAYMODULE.nim
|
||||
/usr/bin/time -v ./$DAYMODULE
|
||||
|
||||
# Days
|
||||
|
||||
- [x] [Day 1](./1.ts)
|
||||
- [ ] Day 2
|
||||
- [x] [Day 2](./2.ts)
|
||||
- [ ] Day 3
|
||||
- [ ] Day 4
|
||||
- [ ] Day 5
|
||||
|
|
53
2021/two.nim
Normal file
53
2021/two.nim
Normal file
|
@ -0,0 +1,53 @@
|
|||
import std/[strutils, sequtils]
|
||||
import ./common
|
||||
|
||||
type SubmarineCommand = enum
|
||||
Forward, Up, Down
|
||||
|
||||
proc parseArg(c: char): int = c.int() - 48
|
||||
|
||||
proc parseSubmarineCommand(l: string): (SubmarineCommand, int) =
|
||||
case l[0]:
|
||||
# since each arg is only one char, we can use this much faster method to
|
||||
# convert to an integer
|
||||
of 'd': return (Down, l[5].parseArg())
|
||||
of 'u': return (Up, l[3].parseArg())
|
||||
else: return (Forward, l[8].parseArg())
|
||||
|
||||
proc submarineCommands(inputs: seq[string]): int =
|
||||
var x, y = 0
|
||||
for (cmd, arg) in inputs.map(parseSubmarineCommand):
|
||||
case cmd:
|
||||
of Up: y -= arg
|
||||
of Down: y += arg
|
||||
of Forward: x += arg
|
||||
x * y
|
||||
|
||||
proc submarineCommandsWithAim(inputs: seq[string]): int =
|
||||
var x, y, aim = 0
|
||||
for (cmd, arg) in inputs.map(parseSubmarineCommand):
|
||||
case cmd:
|
||||
of Up: aim -= arg
|
||||
of Down: aim += arg
|
||||
of Forward:
|
||||
x += arg
|
||||
y += aim * arg
|
||||
x * y
|
||||
|
||||
let input = 2.loadInput()
|
||||
time("submarineCommands part 1"): echo input.submarineCommands()
|
||||
time("submarineCommandsWithAim part 2"): echo input.submarineCommandsWithAim()
|
||||
|
||||
when not defined(release):
|
||||
static:
|
||||
let testInput = @[
|
||||
"forward 5",
|
||||
"down 5",
|
||||
"forward 8",
|
||||
"up 3",
|
||||
"down 8",
|
||||
"forward 2",
|
||||
]
|
||||
doAssert testInput.submarineCommands() == 150
|
||||
doAssert testInput.submarineCommandsWithAim() == 900
|
||||
|
Loading…
Reference in a new issue