Day 17: Chronospatial Computer
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
14 Comments
hades@lemm.ee · 3 pts · 1y
SteveDinn@lemmy.ca · 3 pts · 1y
C#
This one is mostly thanks to reading @mykl@mykl@lemmy.world's code to understand WTF was going on for part 2, and then once I understood the basics, finally got to solving it myself. Instructions were read in as
longbecause I didn't want to deal withintvs.longall the time.Gobbel2000@programming.dev · 2 pts · 1y
Rust
First part was straightforward (the divisions are actually just right shifts), second part not so much. I made some assumptions about the input program, namely that in the end register 8 is divided by 8, then an output is made, then everything starts from the beginning again (if a isn't 0). I found that the output always depends on at most 10 bits of a, so I ran through all 10-bit numbers and grouped them by the first generated output. At that point it's just a matter of chaining these 10-bit numbers from the correct groups so that they overlap on 7 bits. The other 3 bits are consumed each round.
::: spoiler Solution
:::
Also on github
CameronDev@programming.dev · 3 pts · 1y
Your code helped me find my bug, thanks.
Wild that all the examples can be passed with an incorrect
cdvinstruction, I didnt read the last part properly and assumed it was C /= operand. :(gentooer@programming.dev · 2 pts · 1y
Haskell
Runs in 10 ms. I was stuck for most of the day on the bdv and cdv instructions, as I didn't read that the numerator was still register A. Once I got past that, it was pretty straight forward.
::: spoiler Code
:::
CameronDev@programming.dev · 3 pts · 1y
I did the same thing for BDV and CDV, wild that none of the test cases covered them.
VegOwOtenks@lemmy.world · 2 pts · 1y
Haskell
Part 2 was tricky, I tried executing the algorithm backwards, which worked fine for the example but not with the input program, because it uses one-way functions .-. Then I tried to write an algorithm that would try all valid combinations of powers of 8 and but I failed, I then did it by hand.
::: spoiler Solution Codeblock
sjmulder@lemmy.sdf.org · 2 pts · 1y
C
Was looking forward to a VM! Really took my leisure for part 1, writing a disassembler, tracing, all pretty.
Part 2 reminded me of 2021 day 24 where we also had to reverse an input. It's been on my mind recently and I was thinking if there would be a way to backfeed an output through a program, yielding a representation like: "the input plus 3498 is a multiple of 40, and divisible by a number that's 5 mod 8" (considering lossy functions like modulo and integer division).
Today's input didn't lend itself to that, however, but analysing it having the solution 'click' was very satisfying.
::: spoiler Code
:::
https://github.com/sjmulder/aoc/blob/master/2024/c/day17.c
lwhjp@lemmy.sdf.org · 2 pts · 1y
Haskell
Woah, that was suddenly a hard one: several tricky things combined. I'm not a big fan of the kind of problems like part 2 today, but eh - you can't please everyone.
::: spoiler Solution
:::
mykl@lemmy.world · 2 pts · 1y
Dart
Part one was an exercise in building a simple OpCode machine. Part two was trickier. It was clear that the
aregister was repeatedly being divided by 8, and testing a few values showed that each 3-bits of the initial value defined one entry in the output, so I built a recursive routine that brute-forced each one in turn. Only <1ms to run though, so not that brutal.(It's worth pointing out that at some stages multiple 3-bit values gave rise to the required value, causing a failure to resolve later on if not checked.)
(edit: for-loop in
buildQuinenow avoids using a0for the initial triplet, as this should not be a valid value, and if it turns out to generate the required digit of the quine, you will get an infinite recursion. Thanks to SteveDinn for bringing this to my attention.)SteveDinn@lemmy.ca · 3 pts · 1y
I'm confused reading the
buildQuine()method. It reads to me that when you call it from the top level withtop = true,A0will be set to 0, and then when we get to the 0 to 8 loop, the 'A' register will be0 * 8 + 0for the first iteration, and then recurse withtop = false, but witha0still ending up 0, causing infinite recursion.Am I missing something?
I got it to work with a check that avoids the recursion if the last state's A register value is the same as the new state's value.
mykl@lemmy.world · 3 pts · 1y
Oh, good catch. That's certainly the case if an initial value of 0 correctly generates the required value of the quine. As I'd already started running some code against the live data that's what I tested against, and so it's only when I just tested it against the example data that I saw the problem.
I have changed the for-loop to read
for (var a in (top ? 1 : 0).to(8))for maximum terseness :-)That still works for the example and my live data, and I don't think there should be a valid solution that relies on the first triplet being 0. Thanks for your reply!
CameronDev@programming.dev · 1 pts · 1y
Rust
Part 2 really broke me. I ended up converting the instructions into a pair of equations, that I then used to do DFS to find the A value. Then I realised the compute function already does this for me...
vole@lemmy.world · 1 pts · 1y
Raku
I spent way to much time tweaking the part 2 code to get a working solution. The solution itself is quite simple, though.
CameronDev@programming.dev · 1 pts · 1y
The one disappointing part of part 2 is that there seems to be only one way to do it, which makes it kinda boring from a solutions pov. It is a really nice one though, in the sense that it was (personally) quite hard, but also quite simple when it all clicked into place.