day 8, part 2 (final solution), updated readme

main
Inga 🏳‍🌈 11 months ago
parent 47acfe1cf6
commit 36e238b64a
  1. 56
      day08-hard/README.md

@ -10,6 +10,8 @@ Transitions are periodic; since successor of every state is clearly defined, and
this means that no matter at what state we start, we will eventually find ourselves in a loop with the length lower than 200k. this means that no matter at what state we start, we will eventually find ourselves in a loop with the length lower than 200k.
There might be several non-intersecting loops. There might be several non-intersecting loops.
## Solving with brute force
One way to solve the problem would be to use some complicated math in order to compute the result. One way to solve the problem would be to use some complicated math in order to compute the result.
Another, to brute force the result naively, by doing what the puzzle describes: Another, to brute force the result naively, by doing what the puzzle describes:
running several "ghosts", one from each starting state, and on every step checking if all the current states are "ending". running several "ghosts", one from each starting state, and on every step checking if all the current states are "ending".
@ -43,12 +45,12 @@ So ultimately, every step is just six bitwise-ands, one comparison
(which is only true once we found the result, meaning that there is no performance penalty for branch misprediction), (which is only true once we found the result, meaning that there is no performance penalty for branch misprediction),
and six dereferences and assignments. and six dereferences and assignments.
The resulting performance is over 100 million steps per second (single-threaded), The resulting performance (single-threaded) on my laptop is
meaning that we get to ~250 billion steps in just half an hour. over 100 million steps per second, or 500 billions per hour.
The correct result for the puzzle input I got is around 15 trillion, I got it in ~30 hours.
Unfortunately, the result it produces (around ~250 billion) is apparently incorrect; ## Solving with math
it is not accepted by AoC website.
Must be some bug somewhere, even though it works correctly on the (modified) sample input.
Another option, with math, would be to iterate over all possible direction numbers, Another option, with math, would be to iterate over all possible direction numbers,
and for every direction number (out of 270), and for each permutation of final nodes (6^6~=47k) compute: and for every direction number (out of 270), and for each permutation of final nodes (6^6~=47k) compute:
@ -66,4 +68,46 @@ With A being the first time when we reach this configuration.
And then we would just need to find the smallest A for all ~10 million configurations. And then we would just need to find the smallest A for all ~10 million configurations.
But I can't be bothered to do this now. But I can't be bothered to do this now.
## Solving as everybody else did
It seems that most people computed "steps to the first xxZ" for every starting xxA position,
and then just computed lowest common multiple of these six numbers.
Such an answer would only be correct if all of the following assumptions hold:
1. From any xxA point, only one xxZ point can be reached
(counterexample, even with a single direction: `AAA -> XXZ -> YYZ -> XXZ`);
2. From that Z point, time until next entry into this point does not depend on the current step number
(i.e. we always return to that point in `N` steps for some `N`, and never return to it in less than `N`);
3. Number of steps between Z points is the same as number of steps from A point to Z point
(counterexamples, even with a single direction: `AAA -> BBB -> CCC -> ZZZ -> CCC -> ZZZ`;
`AAA -> BBB -> ZZZ -> CCC -> AAA -> BBB -> ZZZ`).
Turns out that all puzzle inputs are carefully crafted in such a way that all three assumptions hold,
so that a naive "lowest common multiple" answer happens to be correct for these inputs.
Yet nowhere does the text of the puzzle say that this should be the case.
And it seems that a lot of people did not even explicitly made these assumptions.
They just had an incorrect idea that LCM should be the solution, without understanding why...
and this incorrect idea just happened to produce the correct answer for this specific input.
I don't like making assumptions like these, and I prefer to make more or less universal solutions,
those that work on everybody's input (and even if my input had these magic properties,
there is no guarantee other inputs do).
The only assumptions I made in my solution are:
1. That there is an answer;
2. That the puzzle input contains at most 270 directions, at most 896 lines, and at most six entry points;
3. That the answer is below ~100 trillions (the most dangerous assumption).
That said, attempting to solve the task "with math" (as described above)
would quickly result in understanding that instead of 6^6 possible "start nodes -> end nodes" combinations,
only one is possible, meaning that only 270 configurations (instead of 10 millions) should be checked,
and only 3300 values (instead of 20k) have to be precomputed, with ~400k operations for each.
That would be the assumption 1 listed above ("from any xxA point, only one xxZ point can be reached"),
which is also the one easiest to check.

Loading…
Cancel
Save