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
|
*.input
|
||||||
|
build
|
||||||
|
|
12
2021/2.ts
12
2021/2.ts
|
@ -1,11 +1,18 @@
|
||||||
import { collectArray, inputLines, measureDuration } from "./common.ts";
|
import { collectArray, inputLines, measureDuration } from "./common.ts";
|
||||||
const input = await collectArray(await inputLines("2"));
|
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 {
|
export function part1(input: string[]): number {
|
||||||
let x = 0;
|
let x = 0;
|
||||||
let y = 0;
|
let y = 0;
|
||||||
for (const line of input) {
|
for (const line of input) {
|
||||||
console.log(line);
|
|
||||||
if (line.startsWith("forward ")) {
|
if (line.startsWith("forward ")) {
|
||||||
x += parseInt(line.substr(8));
|
x += parseInt(line.substr(8));
|
||||||
} else if (line.startsWith("up ")) {
|
} else if (line.startsWith("up ")) {
|
||||||
|
@ -24,7 +31,6 @@ export function part2(input: string[]): number {
|
||||||
let y = 0;
|
let y = 0;
|
||||||
let aim = 0;
|
let aim = 0;
|
||||||
for (const line of input) {
|
for (const line of input) {
|
||||||
console.log(line);
|
|
||||||
if (line.startsWith("forward ")) {
|
if (line.startsWith("forward ")) {
|
||||||
const arg = parseInt(line.substr(8));
|
const arg = parseInt(line.substr(8));
|
||||||
x += arg;
|
x += arg;
|
||||||
|
@ -32,11 +38,9 @@ export function part2(input: string[]): number {
|
||||||
} else if (line.startsWith("up ")) {
|
} else if (line.startsWith("up ")) {
|
||||||
const arg = parseInt(line.substr(3));
|
const arg = parseInt(line.substr(3));
|
||||||
aim -= arg;
|
aim -= arg;
|
||||||
// y -= arg;
|
|
||||||
} else if (line.startsWith("down ")) {
|
} else if (line.startsWith("down ")) {
|
||||||
const arg = parseInt(line.substr(5));
|
const arg = parseInt(line.substr(5));
|
||||||
aim += arg;
|
aim += arg;
|
||||||
// y += arg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x * y;
|
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 =
|
proc countDepthIncreases(inputs: seq[int], dist=1): int =
|
||||||
var stream: FileStream = fmt"/home/daniel/.home/.config/aoc2021/{day}.input".openFileStream
|
for i in dist..<inputs.len():
|
||||||
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:
|
|
||||||
if inputs[i] > inputs[i-dist]: inc result
|
if inputs[i] > inputs[i-dist]: inc result
|
||||||
inc i
|
|
||||||
|
|
||||||
let dd1 = epochTime()
|
let input = 1.loadInput().toInts()
|
||||||
var input = collect(newSeq):
|
time("countDepthIncreases part 1"): echo input.countDepthIncreases()
|
||||||
for i in inputForDay(1): i
|
time("countDepthIncreases part 2"): echo input.countDepthIncreases(3)
|
||||||
|
|
||||||
let dd2 = epochTime()
|
when not defined(release):
|
||||||
echo &"{(dd2 - dd1) * 1000} ms (to load input)"
|
static:
|
||||||
echo "Part 1"
|
let testInputs = @[199, 200, 208, 210, 200, 207, 240, 269, 260, 263]
|
||||||
let d1 = epochTime()
|
doAssert testInputs.countDepthIncreases() == 7
|
||||||
echo part1(input)
|
doAssert testInputs.countDepthIncreases(3) == 5
|
||||||
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)"
|
|
||||||
|
|
|
@ -12,16 +12,34 @@ Specifically, here's my `deno --version` output:
|
||||||
|
|
||||||
Enjoy!
|
Enjoy!
|
||||||
|
|
||||||
|
**EDIT**: Since performance is not what I would like, it looks like I'm also doing some of these in nim.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Run these solutions like so:
|
Run these solutions like so:
|
||||||
|
|
||||||
deno run --unstable --allow-all $DAY.ts
|
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
|
# Days
|
||||||
|
|
||||||
- [x] [Day 1](./1.ts)
|
- [x] [Day 1](./1.ts)
|
||||||
- [ ] Day 2
|
- [x] [Day 2](./2.ts)
|
||||||
- [ ] Day 3
|
- [ ] Day 3
|
||||||
- [ ] Day 4
|
- [ ] Day 4
|
||||||
- [ ] Day 5
|
- [ ] 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