Steer network traffic to speed up part two computation#75
Conversation
|
This is the fastest I can get this day without breaking the black box. If we want to go even faster, it would be easy enough to add a peephole optimization to make the intcode do division much faster (right now, every x parameter to a node undergoes division using intcode's emulation of division, plus the final division node that divides by 1000000000). A bit more involved but even faster would be to go whole-hog and write software to scrape out the magic numbers from all 50 mini-machines to build up the cubic equation ourselves without actually executing intcode (at which point part 2 is obvious on construction and part 1 is found by f(x) using the magic number stored in node 0 at startup). |
Black-box analysis[1] of the day 23 program shows that each id uses a jump table to run a hard-coded machine that has several parameters: a number of input slots, a magic number used to address those slots, an operation (copy, add, multiply, or divide), and a number of fanouts that are triggered once the first -1 and all input slots have been read. Furthermore, the 50 ids are wired up in a DAG where exactly one machine outputs to 255 after all other machines have stabilized, and where every subsequent write to id 0 triggers a cascade of updates among the nodes to recompute the value of a cubic equation. Since the network computes f(x)=ax^3 + bx^2 + cx + d, and we are running the output f(x) back as the new input x for the next cycle, we are searching for a fixed point of the cubic. Running f(1) and inspecting b gives us the same answer with much less work. On my machine, this cuts runtime from 1.9ms to 750us. [1] https://www.reddit.com/r/adventofcode/comments/een9mk/2019_day_23_part_2_what_is_the_network_computing/
|
Intcode problems are interesting becuase the question is where do you draw the line on analysis of the program. At one end you have treating the program as a black box, the other end is peephole analysis of magic constants. My preference for 2019 is to treat the program as a black box. This is not always the fastest, but feels the most in the spirit of the challenge. Other folks can make the perfectly valid choice to analyse the program more. This is too far from a black box to fit in with the meta of these solutions. |
Description
Black-box analysis[1] of the day 23 program shows that each id uses a jump table to run a hard-coded machine that has several parameters: a number of input slots, a magic number used to address those slots, an operation (copy, add, multiply, or divide), and a number of fanouts that are triggered once the first -1 and all input slots have been read. Furthermore, the 50 ids are wired up in a DAG where exactly one machine outputs to 255 after all other machines have stabilized, and where every subsequent write to id 0 triggers a cascade of updates among the nodes to recompute the value of a cubic equation. Since the network computes f(x)=ax^3 + bx^2 + cx + d, and we are running the output f(x) back as the new input x for the next cycle, we are searching for a fixed point of the cubic. Running f(1) and inspecting b gives us the same answer with much less work.
On my machine, this cuts runtime from 1.9ms to 750us.
[1] https://www.reddit.com/r/adventofcode/comments/een9mk/2019_day_23_part_2_what_is_the_network_computing/
Type of change
Checklist
using the same naming conventions. Code should be portable, avoiding any
architecture-specific intrinsics.
cargo testcargo fmt -- `find . -name "*.rs"`cargo clippy --all-targets --all-featuresFormatting and linting also can be executed by running
just(if installed) on the command line at the project root.