Last active
December 28, 2025 01:42
-
-
Save jac18281828/d9e51c7a47d693d9fbb6f4ef1d0a5139 to your computer and use it in GitHub Desktop.
Advent of Code 2025 Day 1 Example MMIX
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| DIAL_INCREMENTS IS 100 | |
| LOC #100 | |
| % Entry point | |
| GREG @ | |
| InputPtr GREG 0 % global register for input pointer | |
| Main LDA InputPtr,MyInput % initialize pointer | |
| SETI $10,50 % dial setting - current dial pointer (starts at 50) | |
| SETI $11,0 % count number of operations handled | |
| SETI $12,0 % hit count - how many times the dial got set to 0 | |
| TokenLoop | |
| LDBI $1,InputPtr,0 % check if at end BEFORE parsing | |
| BZ $1,Done % null terminator, done | |
| PUSHJ $0,ParseRotations | |
| PUSHJ $0,HandleRotation | |
| ADDUI $11,$11,1 % increment operations processed | |
| JMP TokenLoop | |
| % ---------------------------------------------------- | |
| % HandleRotation | |
| % ---------------------------------------------------- | |
| HandleRotation | |
| % operation = direction * magnitude | |
| MUL $5,$2,$3 % apply direction to value | |
| % temp = dial + operation | |
| ADD $0,$10,$5 % move dial in direction of vector | |
| % temp = temp.mod_euclid(DIAL_INCREMENTS) | |
| SETI $1,DIAL_INCREMENTS | |
| PUSHJ $4,RemEuclid | |
| % dial = temp | |
| SET $10,$0 | |
| % if dial == 0? | |
| BNZ $10,SkipCount | |
| % if dial is zero increment the number of hits | |
| ADDI $12,$12,1 | |
| SkipCount | |
| POP 0,0 | |
| % ------------------------------------------------------------ | |
| % RemEuclid: $0 := ($0 rem_euclid $1), with $1 > 0 | |
| % Input: $0 = dividend, $1 = divisor (must be > 0) | |
| % Output: $0 = remainder in range [0, $1) | |
| % Uses: $2, $3 | |
| % ------------------------------------------------------------ | |
| RemEuclid DIV $2, $0, $1 % q = trunc(a/m) | |
| MUL $3, $2, $1 % q*m | |
| SUB $0, $0, $3 % r = a - q*m (can be negative) | |
| BNN $0, RemDone % if r >= 0, we're done | |
| ADD $0, $0, $1 % r += m | |
| RemDone POP 1,0 | |
| % ---------------------------------------------------- | |
| % ParseRotations - Parse ONE rotation from input string | |
| % Input: InputPtr = pointer to current position in string (global) | |
| % Returns: $2 = direction (-1 or +1), $3 = value, InputPtr = updated pointer | |
| % Uses: $1 = current char, $5/$6 = digit scratch | |
| ParseRotations | |
| LDBI $1,InputPtr,0 % load first char | |
| BZ $1,ParseEnd % null terminator | |
| CMPI $2,$1,'L' % check if 'L' | |
| BZ $2,ParseL | |
| CMPI $2,$1,'R' | |
| BZ $2,ParseR | |
| ADDUI InputPtr,InputPtr,1 % skip unknown char | |
| POP 0,0 % return early | |
| ParseL SETI $2,-1 % direction = -1 for left | |
| JMP ParseNumber | |
| ParseR SETI $2,1 % direction = +1 for right | |
| ParseNumber | |
| ADDUI InputPtr,InputPtr,1 % skip L/R char | |
| SETI $3,0 % value accumulator | |
| DigitLoop | |
| LDBI $1,InputPtr,0 % load next char | |
| SUBI $5,$1,'0' % convert to digit | |
| BN $5,EndNumber % < '0' | |
| CMPI $6,$5,10 | |
| BNN $6,EndNumber % >= 10 | |
| MULI $3,$3,10 % value *= 10 | |
| ADD $3,$3,$5 % value += digit | |
| ADDUI InputPtr,InputPtr,1 | |
| JMP DigitLoop | |
| EndNumber | |
| ADDUI InputPtr,InputPtr,1 % skip newline/delimiter | |
| ParseEnd | |
| POP 0,0 | |
| Done TRAP 0,Halt,0 | |
| LOC Data_Segment | |
| MyInput BYTE "L68", '\n', "L30", '\n', "R48", '\n' | |
| BYTE "L5", '\n', "R60", '\n' | |
| BYTE "L55", '\n', "L1", '\n', "L99", '\n' | |
| BYTE "R14", '\n', "L82", '\n', 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| DIAL_INCREMENTS IS 100 | |
| LOC #100 | |
| % Entry point | |
| GREG @ | |
| InputPtr GREG 0 % global register for input pointer | |
| Main LDA InputPtr,MyInput % initialize pointer | |
| SETI $10,50 % dial setting - current dial pointer (starts at 50) | |
| SETI $11,0 % count number of operations handled | |
| SETI $12,0 % hit count - how many times the dial got set to 0 | |
| SETI $13,0 % number of zero crossings | |
| TokenLoop | |
| LDBI $1,InputPtr,0 % check if at end BEFORE parsing | |
| BZ $1,Done % null terminator, done | |
| PUSHJ $0,ParseRotations | |
| PUSHJ $0,HandleRotation | |
| ADDUI $11,$11,1 % increment operations processed | |
| JMP TokenLoop | |
| % ---------------------------------------------------- | |
| % HandleRotation | |
| % ---------------------------------------------------- | |
| HandleRotation | |
| SET $20,$10 % old dial | |
| % turns from raw magnitude | |
| DIVI $21,$3,DIAL_INCREMENTS | |
| ADDU $13,$13,$21 | |
| % k = mag rem_euclid 100 | |
| SET $0,$3 | |
| SETI $1,DIAL_INCREMENTS | |
| PUSHJ $4,RemEuclid | |
| SET $22,$0 % k | |
| % dial update using k | |
| MUL $5,$2,$22 | |
| ADD $0,$10,$5 | |
| SETI $1,DIAL_INCREMENTS | |
| PUSHJ $4,RemEuclid | |
| SET $10,$0 | |
| % partial wrap using k (and signed left) | |
| BNN $2,CrossAbove | |
| BN $2,CrossBelow | |
| JMP CrossyEnd | |
| CrossAbove | |
| BZ $22,CrossyEnd | |
| ADDU $254,$20,$22 | |
| CMPI $0,$254,DIAL_INCREMENTS | |
| BN $0,CrossyEnd | |
| ADDI $13,$13,1 | |
| JMP CrossyEnd | |
| CrossBelow | |
| BZ $22,CrossyEnd | |
| SUB $254,$20,$22 | |
| BNN $254,CrossyEnd | |
| ADDI $13,$13,1 | |
| CrossyEnd | |
| BNZ $10,SkipCount | |
| ADDI $12,$12,1 | |
| SkipCount | |
| POP 0,0 | |
| % ------------------------------------------------------------ | |
| % RemEuclid: $0 := ($0 rem_euclid $1), with $1 > 0 | |
| % Input: $0 = dividend, $1 = divisor (must be > 0) | |
| % Output: $0 = remainder in range [0, $1) | |
| % Uses: $2, $3 | |
| % ------------------------------------------------------------ | |
| RemEuclid DIV $2, $0, $1 % q = trunc(a/m) | |
| MUL $3, $2, $1 % q*m | |
| SUB $0, $0, $3 % r = a - q*m (can be negative) | |
| BNN $0, RemDone % if r >= 0, we're done | |
| ADD $0, $0, $1 % r += m | |
| RemDone POP 1,0 | |
| % ---------------------------------------------------- | |
| % ParseRotations - Parse ONE rotation from input string | |
| % Input: InputPtr = pointer to current position in string (global) | |
| % Returns: $2 = direction (-1 or +1), $3 = value, InputPtr = updated pointer | |
| % Uses: $1 = current char, $5/$6 = digit scratch | |
| ParseRotations | |
| LDBI $1,InputPtr,0 % load first char | |
| BZ $1,ParseEnd % null terminator | |
| CMPI $2,$1,'L' % check if 'L' | |
| BZ $2,ParseL | |
| CMPI $2,$1,'R' | |
| BZ $2,ParseR | |
| ADDUI InputPtr,InputPtr,1 % skip unknown char | |
| POP 0,0 % return early | |
| ParseL SETI $2,-1 % direction = -1 for left | |
| JMP ParseNumber | |
| ParseR SETI $2,1 % direction = +1 for right | |
| ParseNumber | |
| ADDUI InputPtr,InputPtr,1 % skip L/R char | |
| SETI $3,0 % value accumulator | |
| DigitLoop | |
| LDBI $1,InputPtr,0 % load next char | |
| SUBI $5,$1,'0' % convert to digit | |
| BN $5,EndNumber % < '0' | |
| CMPI $6,$5,10 | |
| BNN $6,EndNumber % >= 10 | |
| MULI $3,$3,10 % value *= 10 | |
| ADD $3,$3,$5 % value += digit | |
| ADDUI InputPtr,InputPtr,1 | |
| JMP DigitLoop | |
| EndNumber | |
| ADDUI InputPtr,InputPtr,1 % skip newline/delimiter | |
| ParseEnd | |
| POP 0,0 | |
| Done TRAP 0,Halt,0 | |
| LOC Data_Segment | |
| MyInput BYTE "L68", '\n', "L30", '\n', "R48", '\n' | |
| BYTE "L5", '\n', "R60", '\n' | |
| BYTE "L55", '\n', "L1", '\n', "L99", '\n' | |
| BYTE "R14", '\n', "L82", '\n', 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # cheater - python implementation to confirm the correct answer | |
| # MMIX is correct! ✅ | |
| MOD = 100 | |
| dial = 50 | |
| cross = 0 | |
| with open("/mnt/data/input.txt") as f: | |
| for s in map(str.strip, f): | |
| if not s: | |
| continue | |
| dir_ = 1 if s[0] == "R" else -1 | |
| mag = int(s[1:]) | |
| cross += mag // MOD | |
| k = mag % MOD | |
| old = dial | |
| dial = (dial + dir_ * k) % MOD | |
| if k: | |
| if dir_ > 0 and old + k >= MOD: | |
| cross += 1 | |
| if dir_ < 0 and old - k < 0: | |
| cross += 1 | |
| print(cross, dial) | |
| # -> 6580 25 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment