← Back to list

Advent of Code Day 1 Part 1 Math Style

How important is Math in programming? Can it make solving day 1 part 1 of Advent of Code 2025 easier?

Roman Njoroge · 2025-12-11 19:49 · 16 claps · 3.5 min read
#programming #mathematics #advent-of-code #modulus #python
Open on Medium ↗
Wiki topics: 💻 · Programming 📐 · Mathematics 👗 · Fashion

Advent of Code Day 1 Part 1 Math Style

I recently watched a talk by Leslie Lamport on how programming isn’t just coding, that their should be more focus on designing algorithms than writing code. He also mentioned how math is the language of algorithms and that being fluent in math will make it easier to design algorithms that work.

Because of this, I decided to approach Advent of Code 2025 with a heavy focus on math to see how useful math knowledge is in programming!

THE PUZZLE

A summary of the problem is that we’re trying to get a password combination. The only thing we have is a safe and a list of rotations to make on the safe. Each rotation has a direction (either left or right) and a number for how many times to move the safe’s dial in that direction. The safe’s numbers start at 0 and go to 99. We’ve been given a list of rotations to make, and a clue that the password combination is the number of times the safe’s dial stops at zero after a rotation.

THE MATH

Our safe works like this:

simple version of safe

simple version of safe

We can see that as we rotate to the right the number the dial (arrow in the centre) is on increases but if we rotate to the left the number decreases. We can also see that whatever number we get is between 0 and 7 (for the dial in the problem its between 0 and 99). This is cause when the dial passes 7 it goes back to zero and if it goes below zero it goes back to 7.

This the same behaviour as finding the modulus of two numbers A and B. The modulus is the remainder of dividing A from B i.e. A / B = Q remainder R. We are looking for R when finding the modulus.

Finding the modulus can be visualized by looking at a clock. If we want to find A mod B, and A is a positive number, we’d move the hand of the clock forwards (clockwise) A steps from 0, and the number it lands on will be the modulus. If A is negative, we’d move the hand of the clock backwards (counter-clockwise) A steps from 0 and the number it lands on would be zero.

We can see that finding the modulus is the same as finding the number the safe’s dial will land on after a rotation, the only difference is that for the safe we can start the rotation from any number, not just zero.

To account for this, we can add the number the dial starts on to the rotation before getting the modulus i.e.

Number after right rotation = (original number + rotation) mod 100

Number after left rotation = (original number — rotation) mod 100

Why are we finding the modulus of 100 and not 99? When finding A mod B we see that the range of possible values is from 0 to B — 1. For example, if we were to find A mod 3 we’d know that the answer is either 0, 1 or 2. Since we want to find a number that’s between 0 and 99 the modulus must be 100 since 99 + 1 = 100!

THE CODE

Using this, we can solve the problem using the code below:

import pandas as pd

def right(original: int, rotation: int) -> int:
    """
    Do the right operation, which is meant to increase number
    in safe.
    """
    return (original + rotation) % 100

def left(original: int, rotation: int) -> int:
    """
    Do left operation, which is meant to decrease number in safe
    """

    return (original - rotation) % 100

def operation_from_string(original: int, operation: str) -> int :
    """
    Operations are represented as either LX or RX. 

    LX represents a left operation of X while RX represents
    a right operation of X

    Where X is an integer

    This function performs this operation on the original and returns
    the result

    original: number to perform operation on
    operation: operation and amount to perform it on
    """
    splitIndex = 1 # Location of where numbers start
    operation_type = operation[:splitIndex]
    number = int(operation[splitIndex:])

    if (operation_type == "L"):
        return left(original=original, rotation=number)
    elif (operation_type == "R"):
        return right(original=original, rotation=number)
    else:
        raise "None supported operation"

# Import operations from file
operations = pd.read_csv('input.txt', header=None)

# Go through all operations
num_time_at_zero = 0
current_step = 50
print(f"The dial starts at {current_step}")

for operation in operations[0]:
    # Update position
    current_step = operation_from_string(original=current_step, operation=operation)
    print(f"The dial is rotated {operation} to point at {current_step}")
    # If position = 0 update count
    if (current_step == 0):
        num_time_at_zero += 1

print(f"The code is {num_time_at_zero}")

CONCLUSION

The solution I’d have come up with if I focused more on coding than coming up with a proper algorithm would’ve most likely been much more complicated. This round has been won by Leslie Lamport!

Thanks for reading the article! If there’s a better way to solve this puzzle I’d love to read it in the comments


메타데이터
post_id
14a8e0e3a85a
slug
advent-of-code-day-1-part-1-math-style-14a8e0e3a85a
url
https://medium.com/@roman.njoroge.njuguna/advent-of-code-day-1-part-1-math-style-14a8e0e3a85a
canonical_url
https://medium.com/@roman.njoroge.njuguna/advent-of-code-day-1-part-1-math-style-14a8e0e3a85a
author_url
https://medium.com/@roman.njoroge.njuguna
status
ok
fetched_at
2026-08-04 09:17:15