add some comments

This commit is contained in:
Markus Brueckner 2024-12-03 21:50:14 +01:00
parent c292499076
commit 4a12b8bc56
4 changed files with 88 additions and 1 deletions

34
2024/day1/README.md Normal file
View file

@ -0,0 +1,34 @@
# Solution Day 1
## Tasks
(This is a technical summary of the tasks without the nice story behind it, so go the the website and look at it yourself for more details)
### Task 1
Basically load a CSV-file with two columns, sort the columns individually and sum up the resulting pairs.
### Task 2
Slight variation: instead of summing up the pairs, use the first column as a search key to count the occurencences in the second column and
then multiply each key with it's number of occurences, summing up the products.
Note: The "key" in the first column can occur multiple times and isn't therefore really a key at all.
## Solutions
Both solutions will fail if the format even slightly deviated from the one given in the example. Only numbers, no characters etc. Basically: production
code should get rid of the `unwrap()`s.
### Task 1
Straightforward. Will fail horribly at runtime, if the second column has fewer values, that the first. Also: Haskell gurus and other FP cracks
will probably haunt me for the use of `for .. in ..` and mutable variables instead of `fold()` (which Rust would have. Couldn't be bothered though).
Also I learned, that Rust's `Vec<T>` has an in-place sort like Javascript. Makes sense from the perspective of a memory-efficient language. Was
surprising to me anyway.
### Task 2
Arguably more robust than Task 1 because it doesn't assume anything about the size of column 2. Will fail at runtime, if the the number of occurences
of a key goes beyond `i32` (2^31, so well beyond the realm of the Advent of Code tests)

36
2024/day2/README.md Normal file
View file

@ -0,0 +1,36 @@
# Solution Day 2
Slightly upping the complexity, at least if you don't want to go the brute force route in task 2.
Again reading a CSV, this time without a specified fixed amount of columns. The interesting bit is,
that we're not so much working with the numbers, but rather their differences, so we're basically in
for a instance of the [fencepost error](https://en.wikipedia.org/wiki/Off-by-one_error) if we get it
wrong. Hooray, I guess...
## Task 1
Task 1 is reasonably easy: check all the differences, see whether the series either always goes up or down
and whether it doesn't do so too quickly (steps between 1 and 3, inclusive). Just don't get the off-by-one
wrong when calculating the differences and correct track, whether the series changes direction at any point.
## Task 2
This one felt reasonably tricky for the second day. Try removing one element from an invalid series from
task 1 to make it valid again. In th end I tried 4 approaches:
1. Try skipping an element if it makes the series invalid (e.g. too big a step or going in the wrong direction).
Misses things like `[3,2,5,7,9]`, where removing the `3` at the start would make the series valid. Since this
approach would only ever skip the second element of the pair (i.e. the one the made the "wrong" step from the
point of view of the rules), it would never ever remove the first element.
2. Check for each element, whether removing it makes a valid sequence. Basically the brute-force approach. Not
very efficient, but get's the job done. Since the input is small enough, it's OK and was my solution until...
3. ...my wife proposed to just combine solutions 1. and 2. and only check the _two_ elements, that make the
series invalid. Basically try removing either one and check whether it make a valid sequence. Works for the
sequence in solution 1, but fails to correctly solve `[3,2,3,4,5]` (basically because it notices an issue
at index `2` tries to remove it, which would make `[3,2,4,5]`, still invalid, or tries index `1, making
`[3,3,4,5]`, still invalid).
4. A slight variation of solution 3: instead of checking the invalid index and _one_ back, also check _two_ back (if possible).
This ensures, that we're catching this last corner-case. It catches all corner-cases in the given input (and I
can't think of a case it would miss) and it is more efficient than solution 2. Solution is _O(n*m)_ for _n_ being the number
of total series and _m_ being the average length of a series. This solution is _O(n)_, since it turns the element removal
step into an _O(1)_ operation.

14
2024/day3/README.md Normal file
View file

@ -0,0 +1,14 @@
# Solution Day 3
This one felt much easier. Some "parsing" (well, not really, but anyway), instead of parsing and manipulating CSV.
## Task 1
The initial (seemingly) stupid idea proved to actually work: just use regex! Even got the regex right on the first
attempt. The stars must've aligned today. Just run through the matches, extract and parse the capture groups, multiply
and sum up.
## Task 2
Two complications: more complex regex with 3 different cases (still easy enough and correct in the first attempt) and
some tracking of state (whether the multiplication is currently enabled or not). Still way easier than day 2.

View file

@ -5,3 +5,6 @@ This is my private collection of solutions for the [Advent of Code](https://adve
Solutions might be in different programming languages, might be more or less efficient/ridiculous and are generally unsupported by me once I've finished the task Solutions might be in different programming languages, might be more or less efficient/ridiculous and are generally unsupported by me once I've finished the task
for the day. What I'm saying is: basically this is a dump for my personal solutions and not a teaching instrument. Take from it what you will. Refrain from laughing for the day. What I'm saying is: basically this is a dump for my personal solutions and not a teaching instrument. Take from it what you will. Refrain from laughing
too loud in case they are ridiculous. too loud in case they are ridiculous.
Sometimes you might found a README in the individual solution folders with some of my notes regarding the algorithm, what I like, what I don't like, what could be
improved, if I could be bothered etc.