Setup#
The challenge came with a Python-based ><> (Fish) interpreter and a one-line Fish program that checked the input against one huge constant.
The hint was the important part:
“there may be some issues with this if the collatz conjecture is disproven”
That line was enough to stop me from treating this like a generic esolang problem. The checker was clearly doing some arithmetic transform, and the Collatz reference suggested that the flag was being folded into a single integer rather than checked character by character.
First clue#
After translating the Fish program into normal logic, the checker reduced to two stages.
First, it turned the input string into one big integer by reading the bytes as a big-endian base-256 number:
$$ \text{acc} = \sum_{i=0}^{n} \text{ord}(c_i) \cdot 256^{n-i} $$So at that point the input was effectively:
| |
Then it ran a modified Collatz process and packed the parity decisions into another integer:
| |
The checker never compared the string directly. It only compared the final counter against a hardcoded target.
That mattered because it meant I did not need to emulate the Fish program forward. I only needed to invert the transform.
Turning the checker around#
The useful observation is that every loop iteration doubles counter, and the odd branch adds one on top of that. So if I start from the final target and walk backward, the parity of counter tells me which branch was taken.
- even
countermeans the forward step came from an even Collatz update - odd
countermeans the forward step came from the modified odd update
That gives a clean reverse procedure:
| |
Running that backward walk recovered the original big integer after 2999 steps.
That was the only real pivot in the challenge. Once the reverse direction was clear, the rest was just decoding bytes.
Recovering the flag#
After reconstructing acc, I converted it back to a byte string:
| |
That produced:
| |
Verification#
The recovered string matched the challenge theme exactly and includes the Collatz joke from the hint, which is a good sign that the reverse process is correct.
Final flag:
| |