Advent of Code 2025 Day 1

Part 1

Read in a list of dialing instructions and use these to rotate a dial left or right, starting at 50. Count the number of times the dial is at 0 following a rotation.

As this is a dial, rotations can wrap around in either direction, i.e. from 99 to 0 (rotating right) and from 0 to 99 (rotating left).

Solution

First of all, we need a way of converting a dialling instruction into a data structure. We can parse the input string using a regular expression, and we represent the directions by constants for left (-1) and right (1). Defining the directions as +/- 1 means that we can later multiply the rotation by the direction to move the dial correctly (since multiplying by 1 will have no effect and -1 inverts the sign but leaves the number unchanged).

const (
	DIRECTION_LEFT  = -1
	DIRECTION_RIGHT = 1
)

type Dial struct {
	direction int
	rotation  int
}

func getDial(input string) (Dial, error) {
	dial := Dial{}
	input = strings.TrimSpace(input)

	dialRegex := regexp.MustCompile(`(L|R){1}([0-9]+)`)
	if dialRegex.MatchString(input) {
		matches := dialRegex.FindStringSubmatch(input)

		if matches[1] == "L" {
			dial.direction = DIRECTION_LEFT
		} else {
			dial.direction = DIRECTION_RIGHT
		}

		dial.rotation, _ = strconv.Atoi(matches[2])

		return dial, nil
	}

	return dial, errors.New("invalid dial input")
}

func getDials(input string) []Dial {
	dials := []Dial{}

	lines := strings.Split(input, "\n")

	for lineIndex := range lines {
		dial, err := getDial(lines[lineIndex])

		if err == nil {
			dials = append(dials, dial)
		}
	}

	return dials
}

We then need a function that takes a start position and rotates the dial by a given number of places and left / right. However, we also need to account for the fact that the numbers on the dial ‘wrap around’ in both directions, i.e. rotating left from 0 takes us to 99, and rotating right from 99 takes us to 0. This is effectively clock arithmetic (or modular arithmetic to use the generic mathematical term). Go already has a modulus operator, however it does not handle negative numbers the way we want:

func rotate(position int, direction int, rotation int) int {
	return (position + (direction * rotation)) % (highestPosition + 1)
}

If we rotate left from 0 one place, the above function will return -1 instead of 99. Not all programming languages work this way - the same code in Python would do what is required - but we can fix this with an extra step:

func rotate(position int, direction int, rotation int) int {
	positionCount := highestPosition + 1
	initialMod := (position + (direction * rotation)) % positionCount
	return (initialMod + positionCount) % positionCount
}

Now we need a function which rotates for a set of dials, and returns the final position:

func rotateDials(position int, dials []Dial) int {
	for d := range dials {
		position = rotate(position, dials[d].direction, dials[d].rotation)
	}

	return position
}

This works but doesn’t give us what we need, which is the number of times the dial stops on zero. We can tweak the function slightly to take a target position and keep a count:

func rotateDialsWithTarget(target int, position int, dials []Dial) int {
	targetCount := 0

	for d := range dials {
		position = rotate(position, dials[d].direction, dials[d].rotation)

		if position == target {
			targetCount++
		}
	}

	return targetCount
}

Part 2

Overall thoughts

As is to be expected from the first day, this was a very puzzle to solve.