Skip to content

Commit

Permalink
Year 2018: Day 07
Browse files Browse the repository at this point in the history
  • Loading branch information
joshleaves committed Dec 6, 2024
1 parent b0948e0 commit 60c362e
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 18 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ Of note:
- The changelog 2015.5.2 has been rewritten from each commit content.
- This file may be amended entirely in the future to adhere to the [GNU Changelog style](https://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html#Style-of-Change-Logs)

## Unversioned
## [2018.7.1]
### Added
- Solved [exercice for 2018, day 07](src/year_2018/07.rs).
### Changed
- Small fix to OS error outputs.
- Spelling in notes.

## [2018.6.3]
### Changed
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[package]
name = "advent-rs"
version = "2018.6.3"
version = "2018.7.1"
edition = "2021"
authors = ["Arnaud 'red' Rouyer"]
readme = "README.md"
Expand Down
16 changes: 8 additions & 8 deletions NOTES_2015.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ year_2015::day_03_v2/HashSet/8192
<details>
<summary>Ruby version comments</summary>

> The only thing to be wary of is on line 16: without the call to `#dup`, all of Santa's and Robo-Santa's positions will be overwritten, since Ruby's object model has a tendancy to pass references when you expect to pass values.
> The only thing to be wary of is on line 16: without the call to `#dup`, all of Santa's and Robo-Santa's positions will be overwritten, since Ruby's object model has a tendency to pass references when you expect to pass values.
>
> Passing by value or reference is a really wonky subject, but this [blog post](https://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/) got nice examples that will get you started.
</details>
Expand Down Expand Up @@ -180,7 +180,7 @@ year_2015::day_06/year_2015::day_06_v2
<details>
<summary>Ruby version comments</summary>

> This one actually gave me SOME trouble. My first solution was iterating on each element one by one and was clearly too long. Thanksfully, Ruby is really smart when it comes to replacing slices of an array.
> This one actually gave me SOME trouble. My first solution was iterating on each element one by one and was clearly too long. Thankfully, Ruby is really smart when it comes to replacing slices of an array.
>
> There is an even more beautiful solution for part 2 that consist of only tracking the total numbers of flicks on/off/toggle, but in the off chance that a light already off is turned off again, the results would become false.
>
Expand Down Expand Up @@ -217,7 +217,7 @@ year_2015::day_07/year_2015::day_07_v2
>
> The naive implementation, that works very well with the sample input, consists of interpreting each line one by one, storing the value of each wire every time. Unfortunately, not all inputs are indicated in a linear way.
>
> The answer lies in to store all wires, setting up operations with [lazy evaluation](https://betterprogramming.pub/how-lazy-evaluation-works-in-ruby-a90237e99ac3), and letting intepretation work itself all the way back.
> The answer lies in to store all wires, setting up operations with [lazy evaluation](https://betterprogramming.pub/how-lazy-evaluation-works-in-ruby-a90237e99ac3), and letting interpretation work itself all the way back.
</details>
This one was already complicated in Ruby, but it gets even worse when you have to deal with [Rust's lifetimes](https://doc.rust-lang.org/rust-by-example/scope/lifetime.html). The concept in itself is kinda okay to understand, but the way it has to be used sometimes makes no sense. I guess I'll get used to it with time. A [nice crate](https://docs.rs/advent-of-code/2022.0.66/src/advent_of_code/year2015/day07.rs.html) helped me see through it a bit more clearly.
Expand Down Expand Up @@ -246,7 +246,7 @@ year_2015::day_08/year_2015::day_08_v2

> Understanding how characters escaping works is a massive PAIN, and misunderstand the concept is a reason why [PHP MySQL injections](https://www.php.net/manual/en/security.database.sql-injection.php) were so infamous. Things get even more hairy when you have to work with MULTIPLE type of injections (paths, web, sql,...), or even multiple types of string that don't escape the same way,
>
> In that case, we are lucky, since Ruby already implements [dump](https://ruby-doc.org/3.2.2/String.html#method-i-dump) and [undump](https://ruby-doc.org/3.2.2/String.html#method-i-undump), which happens to work exactly as the exercise require. But since we're here to learn, the methods will alternate at runtime between the Ruby methods and the manual implementation.
> In that case, we are lucky, since Ruby already implements [dump](https://ruby-doc.org/3.2.2/String.html#method-i-dump) and [un-dump](https://ruby-doc.org/3.2.2/String.html#method-i-undump), which happens to work exactly as the exercise require. But since we're here to learn, the methods will alternate at runtime between the Ruby methods and the manual implementation.
</details>
This one was actually very funny. For a while, I thought it would be a pain to not be able to index strings, but extracting slices actually works better.
Expand All @@ -271,7 +271,7 @@ year_2015::day_09/year_2015::day_09_v2
<details>
<summary>Ruby version comments</summary>

> Any programming school worth its salt will one day ask of you the shortest path between many points. Often, the idea is that you'll use graph theory and implement [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). Sometimes, the school wants your brain for dinner and you'll be asked to further solve the [Travelling Salesman Problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem). Both are very interested concepts in themselves, and a good first approach to [PathFinding](https://en.wikipedia.org/wiki/Pathfinding).
> Any programming school worth its salt will one day ask of you the shortest path between many points. Often, the idea is that you'll use graph theory and implement [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). Sometimes, the school wants your brain for dinner and you'll be asked to further solve the [Traveling Salesman Problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem). Both are very interested concepts in themselves, and a good first approach to [PathFinding](https://en.wikipedia.org/wiki/Pathfinding).
>
> If you're not fond of graph transversal, the best answer is often to start using the [A* (A-Star)](https://en.wikipedia.org/wiki/A*_search_algorithm) algorithm to iterate through all possible paths.
>
Expand All @@ -282,7 +282,7 @@ year_2015::day_09/year_2015::day_09_v2
This one got me a bit closer to understand how lifetimes function.

While my [more experienced counterpart](https://docs.rs/advent-of-code/2022.0.66/src/advent_of_code/year2015/day09.rs.html) used a cleaner perform-all-permutations approach, I wanted to keep the recursivity of my original algorithm, if only to force myself to make lifetimes work across recursion.
While my [more experienced counterpart](https://docs.rs/advent-of-code/2022.0.66/src/advent_of_code/year2015/day09.rs.html) used a cleaner perform-all-permutations approach, I wanted to keep the recursion of my original algorithm, if only to force myself to make lifetimes work across recursion.

## Day 10: Elves Look, Elves Say

Expand Down Expand Up @@ -554,7 +554,7 @@ year_2015::day_19/year_2015::day_19_v2
<details>
<summary>Ruby version comments</summary>

> Part one is nothing to write home about. However, part two... First idea was the good ol' bruteforce approach, but when searching if there was an algorithm I didn't know, I stumbled upon a [very interesting Reddit comment](https://www.reddit.com/r/adventofcode/comments/3xflz8/day_19_solutions/cy4h7ji/)...
> Part one is nothing to write home about. However, part two... First idea was the good ol' brute-force approach, but when searching if there was an algorithm I didn't know, I stumbled upon a [very interesting Reddit comment](https://www.reddit.com/r/adventofcode/comments/3xflz8/day_19_solutions/cy4h7ji/)...
</details>
Okay, that was less painful than I remembered it, and my Rust code is actually clearer than my Ruby code.
Expand Down Expand Up @@ -684,7 +684,7 @@ year_2015::day_24/year_2015::day_24_v2
<details>
<summary>Ruby version comments</summary>

>While this looks like YABA (Yet Another Bruteforce Algorithm), Ruby's got a very useful [`#combination`](https://ruby-doc.org/3.2.2/Array.html#method-i-combination) method that will generate permutations around for you. And of course, knowing when to exit the loop at the best time is half the battle.
>While this looks like YABA (Yet Another Brute-force Algorithm), Ruby's got a very useful [`#combination`](https://ruby-doc.org/3.2.2/Array.html#method-i-combination) method that will generate permutations around for you. And of course, knowing when to exit the loop at the best time is half the battle.
</details>
Would you believe it? The `combinations(n)` method also exists in Rust!
Expand Down
4 changes: 2 additions & 2 deletions NOTES_2016.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Playing with specific types for closures can be a pain, but it's often very funn

## Day 07: Internet Protocol Version 7

Some iterators are annoying, but sometimes, like when calculating whethere there is an interesection of two sets, it's great to not generate the whole intersection and just peek at the first element.
Some iterators are annoying, but sometimes, like when calculating whether there is an intersection of two sets, it's great to not generate the whole intersection and just peek at the first element.

## Day 08: Two-Factor Authentication

Expand All @@ -49,7 +49,7 @@ Looking at it carefully proved very smart: both galenelias and me lost too much

## Day 10: Balance Bots

This exercise got me to face the worst part of Rust: iterating over a hashmap while mutating it.
This exercise got me to face the worst part of Rust: iterating over a hash map while mutating it.

## Day 11: Radioisotope Thermoelectric Generators

Expand Down
10 changes: 5 additions & 5 deletions NOTES_2017.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ Welcome to another year. First day isn't too complicated, and the only play here

Nothing too hard either, if you know how iterations work. In that case, it's FASTER to only iterate once and store the `min` and `max` as you go along, rather than iterating, collecting, and iterating again to gain the `min`, then iterating once more to gain the `max`.

As for part 2, it's better to use `filter_map()` instead of chaining `filter` then `map` since our verification is based on doing a (costy) calculation.
As for part 2, it's better to use `filter_map()` instead of chaining `filter` then `map` since our verification is based on doing a (costly) calculation.

## Day 03: Spiral Memory

Now we are getting somewhere!

Again, half the battle is knowing exactly what to really look for. While part 2 DOES force us to iterate through the field until we get to a result, part one can be solved by understaing you are faced with an [Ulam Spiral](https://en.wikipedia.org/wiki/Ulam_spiral). From there, a little Google can get you [prettY](https://oeis.org/A268038) [eXciting](https://oeis.org/A268038) [results](https://stackoverflow.com/a/61253346).
Again, half the battle is knowing exactly what to really look for. While part 2 DOES force us to iterate through the field until we get to a result, part one can be solved by understating you are faced with an [Ulam Spiral](https://en.wikipedia.org/wiki/Ulam_spiral). From there, a little Google can get you [prettY](https://oeis.org/A268038) [eXciting](https://oeis.org/A268038) [results](https://stackoverflow.com/a/61253346).

## Day 04: High-Entropy Passphrases

Expand All @@ -38,15 +38,15 @@ Since we only iterate once with no jumps, no need to save instructions.

## Day 09: Stream Processing

The usual: do your best to only iter every character once. Rust's pattern-matching is really good there.
The usual: do your best to only iterate every character once. Rust's pattern-matching is really good there.

## Day 10: Knot Hash

Funny exercise, the second part was A BIT confusing at first, but it got okay.

## Day 11: Hex Ed

Navigating hexagons is a pain. Naive approach is to start with "only change the Y value if we move up, not down", but this will fail you in the long run. What you can do, is treat each hexagone as "two squares": moving up means `Y minus 2` and moving down means `Y plus 2`, while all diagonals work the way they would with a regular grid.
Navigating hexagons is a pain. Naive approach is to start with "only change the Y value if we move up, not down", but this will fail you in the long run. What you can do, is treat each hexagon as "two squares": moving up means `Y minus 2` and moving down means `Y plus 2`, while all diagonals work the way they would with a regular grid.

## Day 12: Digital Plumber

Expand All @@ -62,7 +62,7 @@ I kinda liked this one.

## Day 15: Dueling Generators

The most interesting part of these exercises is often [all the obscure maths you can leanr about](https://www.reddit.com/r/adventofcode/comments/7jyz5x/2017_day_15_opportunities_for_optimization/drasfzr/?context=3), in that case [Mersenne prime](https://en.wikipedia.org/wiki/Mersenne_prime). But the peculiarities of the number used for the remainder [should have been obvious to people who wrote a lot of C](https://doc.rust-lang.org/std/i32/constant.MAX.html).
The most interesting part of these exercises is often [all the obscure maths you can learn about](https://www.reddit.com/r/adventofcode/comments/7jyz5x/2017_day_15_opportunities_for_optimization/drasfzr/?context=3), in that case [Mersenne prime](https://en.wikipedia.org/wiki/Mersenne_prime). But the peculiarities of the number used for the remainder [should have been obvious to people who wrote a lot of C](https://doc.rust-lang.org/std/i32/constant.MAX.html).

## Day 16: Permutation Promenade

Expand Down
4 changes: 4 additions & 0 deletions NOTES_2018.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ As a programmer, your MUST have used, at least once, the command [`man ascii`](h
## Day 06: Chronal Coordinates

At first, I felt like expanding each area one by one, until I realised that just calculating distances was just easier.

# Day 07: The Sum of Its Parts

I hate everything about time-advancing series calculations...
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ I'm also adding notes that may be useful if you're (like me) discovering Rust:
- [2015, complete!](NOTES_2015.md)
- [2016, complete!](NOTES_2016.md)
- [2017, complete!](NOTES_2017.md)
- [2018, up to day 06](NOTES_2018.md)
- [2018, up to day 07](NOTES_2018.md)

# Regarding style rules
I'm gonna use a mix of what `cargo fmt` does, with some stuff that feels more natural to me.
Expand Down
101 changes: 101 additions & 0 deletions inputs/year_2018/day_07_input
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
Step L must be finished before step M can begin.
Step B must be finished before step S can begin.
Step F must be finished before step M can begin.
Step C must be finished before step P can begin.
Step D must be finished before step V can begin.
Step T must be finished before step J can begin.
Step E must be finished before step S can begin.
Step Z must be finished before step V can begin.
Step X must be finished before step U can begin.
Step G must be finished before step I can begin.
Step V must be finished before step W can begin.
Step H must be finished before step O can begin.
Step M must be finished before step S can begin.
Step K must be finished before step I can begin.
Step I must be finished before step J can begin.
Step A must be finished before step W can begin.
Step J must be finished before step R can begin.
Step Q must be finished before step S can begin.
Step Y must be finished before step R can begin.
Step O must be finished before step W can begin.
Step R must be finished before step U can begin.
Step P must be finished before step U can begin.
Step S must be finished before step W can begin.
Step U must be finished before step N can begin.
Step W must be finished before step N can begin.
Step P must be finished before step W can begin.
Step J must be finished before step W can begin.
Step F must be finished before step G can begin.
Step U must be finished before step W can begin.
Step Y must be finished before step P can begin.
Step Z must be finished before step I can begin.
Step R must be finished before step W can begin.
Step T must be finished before step X can begin.
Step Q must be finished before step R can begin.
Step B must be finished before step P can begin.
Step Z must be finished before step U can begin.
Step H must be finished before step Y can begin.
Step G must be finished before step A can begin.
Step O must be finished before step P can begin.
Step F must be finished before step D can begin.
Step F must be finished before step Q can begin.
Step T must be finished before step U can begin.
Step I must be finished before step O can begin.
Step K must be finished before step R can begin.
Step E must be finished before step J can begin.
Step Z must be finished before step G can begin.
Step Y must be finished before step W can begin.
Step L must be finished before step V can begin.
Step E must be finished before step X can begin.
Step E must be finished before step U can begin.
Step A must be finished before step N can begin.
Step G must be finished before step N can begin.
Step B must be finished before step C can begin.
Step M must be finished before step U can begin.
Step G must be finished before step R can begin.
Step R must be finished before step N can begin.
Step M must be finished before step K can begin.
Step C must be finished before step E can begin.
Step B must be finished before step U can begin.
Step J must be finished before step Y can begin.
Step X must be finished before step H can begin.
Step E must be finished before step W can begin.
Step A must be finished before step Y can begin.
Step I must be finished before step A can begin.
Step D must be finished before step W can begin.
Step B must be finished before step I can begin.
Step H must be finished before step P can begin.
Step A must be finished before step S can begin.
Step P must be finished before step N can begin.
Step V must be finished before step J can begin.
Step L must be finished before step D can begin.
Step C must be finished before step R can begin.
Step Z must be finished before step Y can begin.
Step F must be finished before step S can begin.
Step O must be finished before step N can begin.
Step X must be finished before step R can begin.
Step E must be finished before step Q can begin.
Step L must be finished before step Z can begin.
Step D must be finished before step O can begin.
Step Y must be finished before step O can begin.
Step S must be finished before step N can begin.
Step D must be finished before step X can begin.
Step T must be finished before step A can begin.
Step Q must be finished before step Y can begin.
Step K must be finished before step J can begin.
Step C must be finished before step S can begin.
Step M must be finished before step P can begin.
Step O must be finished before step R can begin.
Step E must be finished before step Y can begin.
Step V must be finished before step O can begin.
Step D must be finished before step Q can begin.
Step D must be finished before step J can begin.
Step D must be finished before step R can begin.
Step R must be finished before step P can begin.
Step X must be finished before step O can begin.
Step C must be finished before step K can begin.
Step L must be finished before step R can begin.
Step Q must be finished before step U can begin.
Step G must be finished before step K can begin.
Step I must be finished before step S can begin.
Step L must be finished before step X can begin.
9 changes: 9 additions & 0 deletions src/year_2018.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod day_03;
pub mod day_04;
pub mod day_05;
pub mod day_06;
pub mod day_07;

pub fn solve(day: u8, part: u8, input: impl Into<String>) -> Option<String> {
if part > 2 {
Expand All @@ -21,6 +22,7 @@ pub fn solve(day: u8, part: u8, input: impl Into<String>) -> Option<String> {
4 => Some(day_04::day_04(part, input).to_string()),
5 => Some(day_05::day_05(part, input).to_string()),
6 => Some(day_06::day_06(part, input).to_string()),
7 => Some(day_07::day_07(part, input).to_string()),
_ => None,
}
}
Expand Down Expand Up @@ -70,4 +72,11 @@ mod tests {
assert_eq!(day_06::day_06_v1(input), 3_251);
assert_eq!(day_06::day_06_v2(input), 47_841);
}

#[test]
fn day_07() {
let input = include_str!("../inputs/year_2018/day_07_input");
assert_eq!(day_07::day_07_v1(input), "BCEFLDMQTXHZGKIASVJYORPUWN");
assert_eq!(day_07::day_07_v2(input), "987");
}
}
Loading

0 comments on commit 60c362e

Please sign in to comment.