bobgeis / aoc2021

Solutions to Advent of Code 2021 in Nim.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Advent of Code 2021

This repo contains soluations for Advent of Code 2021 written in nim.

Links

Nim References

repo

Generic setup. Using vscode with nim and indent-rainbow extensions. Plus other not nim-specific ones.

For nimble packages, the stint package is vital for dealing with very large ints. memo and itertools are sometimes very helpful and convenient.

I have a large 'lib' of helper code from previous years that I may re-use this year. aocutils is for working in the repo (eg finding data files for each day). bedrock has misc utilities that don't import anything else from the repo; it's the 'bottom'. vecna has a bunch of convenience utilities for working with coordinates (x,y,etc), which happens a lot in aoc. graphwalk is an implementation of bfs and Dijkstra's algorithm, because they come up a lot. shenanigans is for experimentation and causing trouble.

There are a number of scripts in config.nims. nim dr 01 will compile and run day 1 with the default input. nim dt 01 will compile and run with performance optimizations. Specific input files can be passed like nim dr 01 i t1, where i represents the default input, t1 represents the first test input, etc.




SPOILERS BELOW




all

The day/all.nim program exists to sequentially run all the days on their default input and check that the answers are still correct. The timing below is not a scientific benchmark, but should give on a ballpark on which days are slow/fast.

$ nim dt all
nim c  -d:fast day/all.nim
time out/run
Advent of Code 2021. All days at #b6c2b6b
Day 01:     0.395 ms
Day 02:     0.350 ms
Day 03:     0.620 ms
Day 04:     5.141 ms
Day 05:    53.535 ms
Day 06:     9.636 ms
Day 07:     5.353 ms
Day 08:     3.079 ms
Day 09:     7.232 ms

real    0m0.094s
user    0m0.070s
sys     0m0.011s

d00

day 0 is a template for each day. It has stubs for part0 (work common to part 1 and part 2) and part1 and part 2. It also has calls to part1is and part2is for test and input paths, which are used to verify that refactoring doesn't break something we know works.


d01

Link

The first task is pretty straightfoward arithmetic. It's mostly a chance for people to make sure their setup is working.

There's a little bit of a trick to part 2: it says to compare the sums, but you can skip the sums and just compare input values 3 offsets apart.


d02

Link

This is another pretty straightforward task, but requires some string parsing. I used scanf. I expect lots of solutions will use regex or peg though.

I had forgotten that scanTuple was introduced in nim 1.6, and have switched to use that (it just makes things more concise).

There is also a clever include trick used by pietroppeter that embeds the input in the compiled program. This is pretty neat, and allows us to treat the input itself as code. (Note: I'm not going to do use this here because I'm considering the run time performance, but the not compile time. If you use the input at compile time, you could make the run time arbitrarily short.)


d03

Link

Part 2 was a bit confusing at first. Tidying up, and seeing what some other people had done, I saw something useful: if you are making a var copy of an immutable arg, you can just declare that arg as sink. This will use the arg "as is" if it's the last use, or make a full copy if not, potentially saving you from having to copy.


d04

Link

Bingo! I found it convenient to define a type for this one.


d05

Link

My implementation of day 5 is very slow compared to the other days so far. I should come back to this with a mind to improve it.


d06

Link

Part 2 of day 6 was the first time so far where the naive brute force approach was too slow. Thinking for a bit, one notices that the order of the fix in the list is not actually important, and just keeping count of the number of fish at each number is sufficient. This makes things much faster.


d07

Link

Naive brute force approach worked: loop from the leftmost crab to the rightmost one, finding the cost at each position, then take the minimum cost.


d08

Link

If you treat the encoded numbers as sets of characters, you can pretty quickly decode everything by doing set differences and comparing set sizes. There's probably a better way than what I did, but it worked well enough.


d09

Link

Did brute force for both part 1 and part 2.


About

Solutions to Advent of Code 2021 in Nim.


Languages

Language:Nim 100.0%