input <- readLines("test_input.txt")Advent of Code: 2025 Day 1 in R
See the puzzle instructions here.
Part 1
Solution
We first read in the instructions. In this case it’s very simple to just read the input txt file.
We then need to parse the instruction:
get_instructions <- function(steps) {
# Get a list of all steps with characters split
split_steps <- strsplit(steps, "")
# Initialize empty vectors for direction markers and digits
direction_vector <- character(length(steps))
digits_vector <- integer(length(steps))
# Iterate over the split strings
for (i in seq_along(split_steps)) {
# Extract the direction and assign it to the vector
direction_vector[i] <- split_steps[[i]][1]
# Get the remaining characters and convert them to integer,
# then assign to the vector
digits <- split_steps[[i]][2:length(split_steps[[i]])]
digits_vector[i] <- as.integer(paste0(digits, collapse = ""))
}
# Return a dataframe with the steps
data.frame(direction = direction_vector, digits = digits_vector)
}Next, we define a function to move the dial. It is a circular dial from 0 to 99, which means that it will roll back over to 0 when it passes 99. To account for this, we need to take the modulo of 100.
move_dial <- function(position, instruction) {
if (instruction$direction == "L") {
return((position - instruction$digits) %% 100)
} else if (instruction$direction == "R") {
return((position + instruction$digits) %% 100)
} else {
stop("Invalid input")
}
}I’ll create a function to iterate over the rows of the dataframe and execute move_dial(), logging each time the dial lands on 0.
solve_part_1 <- function(input) {
# Start at position = 50
position <- 50
# Initialize a variable for the number of times we land on 0
lands_on_zero <- 0
# Parse the input
instructions <- get_instructions(input)
# Iterate over the rows
for (i in seq_len(nrow(instructions))) {
position <- move_dial(position, instructions[i, ])
if (position == 0) {
lands_on_zero <- lands_on_zero + 1
}
}
lands_on_zero
}We can then test it out:
test_input <- readLines("test_input.txt")
solve_part_1(test_input)[1] 3
That’s what we’re supposed to get! Now for the real data
real_input <- readLines("input.txt")
solve_part_1(real_input)[1] 1177
And that’s the correct answer!
Part 2
Solution
I’m going to attempt a brute force solution and hope it isn’t dreadfully slow. Instead of moving the dial all x steps at once, I will use a loop to increment it one step at a time for the prescribed number of steps, and any time it lands on zero I will add to the running total.
move_dial <- function(position, instructions) {
# Initialize a variable to count when it hits zero
zero_count <- 0
# First iterate over all rows of the instructions dataframe
for (i in seq_len(nrow(instructions))) {
# Then iterate again, this time counting up to the number listed in `digits`
for (j in seq_len(instructions$digits[i])) {
# If "L", subtract, if "R", add, still modulo 100
if (instructions$direction[i] == "L") {
position <- (position - 1) %% 100
} else if (instructions$direction[i] == "R") {
position <- (position + 1) %% 100
} else {
stop("Invalid input")
}
# If it is ever equal to 0, increment the counter
if (position == 0) {
zero_count <- zero_count + 1
}
}
}
zero_count
}
# Put it together with `get_instructions()`
solve_part_2 <- function(input) {
instructions <- get_instructions(input)
move_dial(50, instructions)
}Let’s try it with the test input:
solve_part_2(test_input)[1] 6
That’s correct!
Now let’s see how slow it goes with the full real input:
solve_part_2(real_input)[1] 6768
That’s correct, and not all that slow! Challenge complete, declare victory.