Advent of Code 2025 Day 1
Part 1
Round and round we go!
Let's dive straight in to this one.
The challenge models a number line from 0 to 99 - 100 numbers.
Moving past 0 - to the left - should be equivalent to looping back to 99 and counting down.
The example given is:
L5 from 0 lands you on 95
How might I accomplish that with computer code?
Well:
-
0 - 5is-5 - If the number is negative...
- Calculate
100minus the absolute value of that number - So,
100 - (+5)or100 - 5or95
Another example is:
R5 from 99 lands you on 4
How might I accomplish that with computer code?
Well:
-
99 + 5is104 - If the number is greater than 100...
- Calculate the number
modulo100 - dividing the number by 100 and keeping the remainder - So,
104 % 100is4
An example of a large rotation from my input is:
L888 from, say, 42, lands you on 54
How might I accomplish that with computer code?
Well:
- A combination of both techniques above
- First performing the
moduloon888to get:88- each additional 100 rotations will result in the same landing spot - Calculating
42 - 88as-46 - Calculating
100 - (+46)as54
I can use the modulo technique any time the rotation is greater than 99.
I'm ready to turn all this logic into working computer code.
Writing my algorithm
Setting up variables:
input = input.split('\n')
let cursor = 50
let password = 0
Parsing each instruction:
input.forEach(rotation => {
let dir = rotation[0]
let amt = +rotation.slice(1) % 100
})
Writing the conditional logic:
input.forEach(rotation => {
let dir = rotation[0]
let amt = +rotation.slice(1) % 100
switch (dir) {
case "R":
cursor = (cursor + amt) % 100
break;
case "L":
cursor = (cursor - amt < 0) ? 100 - Math.abs(cursor - amt) : cursor - amt
break;
}
if (cursor == 0) {
password++
}
})
I forgot about the use case of a L instruction that doesn't result in a negative number.
That took a few minutes of debugging, and resulted in the ternary operation shown above.
After testing on the example input, it works as expected.
Will it work correctly on my puzzle input, though?
Testing on my puzzle input
Running...
Submitting...
Correct!
Woohoo!!!
Part 2
Of course, now number of rotations is critical
I now am forced to care about the numbers I was modulo-ing away in Part 1.
Use cases I have to identify:
- An
Rinstruction that passes99 - An
Linstruction that passes0 - Any instructions greater than
99 - Instructions perfectly divisible by 100 when the cursor is
0
Updating my algorithm
I went straight to it.
Here's what I wrote:
input.forEach(rotation => {
let dir = rotation[0]
let amt = +rotation.slice(1)
if (amt.toString().length > 2) {
let temp = amt.toString()
password += +temp.slice(0, amt.length - 2)
amt = amt % 100
}
let next
switch (dir) {
case "R":
next = (cursor + amt) % 100
if (next < cursor) {
password++
}
cursor = next
break;
case "L":
next = (cursor - amt < 0) ? 100 - Math.abs(cursor - amt) : cursor - amt
if (next > cursor) {
password++
}
cursor = next
break;
}
})
- First, I handle rotation amounts over
99 - Then, in each
case, I determine where the cursor will end up, and update the password if it has crossed0
Testing my algorithm
It generates the correct answer for the example puzzle input.
It generates an answer that is twice what I Part 1 answer was. That seems low.
Still, it could be right.
Submitting...
Wrong answer. Too low.
Am I overthinking things?
Upon inspecting my input:
- Nearly 800 instructions rotate the cursor more than 100 notches, meaning at least pass across
0 - No rotations of
0notches, which could have been an edge case I didn't account for - No rotations that are perfectly divisible by
100, which I think my code still accounts for
So, I have two sets of instructions:
- A number less than
100resulting in0-1passes across0 - A number greater than
100resulting in1+passes across0
Time to re-think and step through my algorithm.
Fixing my mistakes one by one
- Wrong condition logic
- Wrong variable used
- Missing part of condition
Man, I really overlooked some critical details.
Thankfully, the example input helped me see my final glaring error.
Alas, this is the algorithm that allowed me to generate the correct answer:
input.forEach(rotation => {
let dir = rotation[0]
let amt = +rotation.slice(1)
if (amt.toString().length > 2) {
let temp = amt.toString()
password += +temp.slice(0, amt.toString().length - 2)
amt = amt % 100
}
let next
switch (dir) {
case "R":
next = cursor + amt
if (next >= 100) {
password++
}
cursor = (next >= 100) ? next - 100 : next
break;
case "L":
next = cursor - amt
if (cursor > 0 && next <= 0) {
password++
}
cursor = (next < 0) ? 100 - Math.abs(cursor - amt) : next
break;
}
})
- I correctly increment the password for each hundred in large instructions
- For
Lrotations, I correctly only increment password when the cursor is at a position higher than0 - For
Lrotations, I correctly update the cursor's value when it crosses0
This was the most I've had to troubleshoot a Day 1 Part 2 algorithm.
I have only myself to blame. I simply overlooked a lot of important subtleties.
Thankfully, I come away with two gold stars!
The year is off to a great start!
Top comments (0)