advent_of_code_2025

My (attempted) solutions to the 2025 Advent of Code
git clone https://git.eamoncaddigan.net/advent_of_code_2025.git
Log | Files | Refs | README

day08.R (2477B)


      1 #!/usr/bin/env Rscript
      2 
      3 source("src/utils.R")
      4 
      5 test_input <- c(
      6   "162,817,812",
      7   "57,618,57",
      8   "906,360,560",
      9   "592,479,940",
     10   "352,342,300",
     11   "466,668,158",
     12   "542,29,236",
     13   "431,825,988",
     14   "739,650,466",
     15   "52,470,668",
     16   "216,146,977",
     17   "819,987,18",
     18   "117,168,530",
     19   "805,96,715",
     20   "346,949,466",
     21   "970,615,88",
     22   "941,993,340",
     23   "862,61,35",
     24   "984,92,344",
     25   "425,690,689"
     26 )
     27 puzzle_input <- aoc_input(8)
     28 
     29 parse_input <- function(input_lines) {
     30   input_lines |>
     31     strsplit(",") |>
     32     lapply(as.numeric) |>
     33     (\(x) do.call(rbind, x))()
     34 }
     35 
     36 order_distances <- function(distmat) {
     37   # Put the pairs from the distance matrix in increasing order
     38   which(lower.tri(distmat), arr.ind = TRUE)[order(distmat), ]
     39 }
     40 
     41 greedy_connect <- function(coords, max_steps = NULL) {
     42   # Circuit IDs for each junction box
     43   coord_circuits <- seq_len(nrow(coords))
     44   # Junction box (coordinate) IDs for each circuit
     45   circuit_coords <- as.list(seq_along(coord_circuits))
     46 
     47   pair_order <- coords |>
     48     dist() |>
     49     order_distances()
     50 
     51   max_steps <- min(max_steps, nrow(pair_order))
     52   for (i in seq_len(max_steps)) {
     53     c1 <- coord_circuits[pair_order[i, 1]]
     54     c2 <- coord_circuits[pair_order[i, 2]]
     55     if (c1 < c2) {
     56       coord_circuits[circuit_coords[[c2]]] <- c1
     57       circuit_coords[[c1]] <- union(circuit_coords[[c1]], circuit_coords[[c2]])
     58       circuit_coords[c2] <- list(NULL)
     59       if (length(circuit_coords[[c1]]) == nrow(coords)) break
     60     } else if (c1 > c2) {
     61       coord_circuits[circuit_coords[[c1]]] <- c2
     62       circuit_coords[[c2]] <- union(circuit_coords[[c1]], circuit_coords[[c2]])
     63       circuit_coords[c1] <- list(NULL)
     64       if (length(circuit_coords[[c2]]) == nrow(coords)) break
     65     }
     66   }
     67 
     68   list(circuits = circuit_coords, last_pair = pair_order[i, ])
     69 }
     70 
     71 part1 <- function(input_lines, steps) {
     72   input_lines |>
     73     parse_input() |>
     74     (\(x) greedy_connect(x, steps)$circuits)() |>
     75     vapply(length, integer(1)) |>
     76     sort(decreasing = TRUE) |>
     77     (\(x) prod(x[1:3]))()
     78 }
     79 
     80 test_part1 <- function() {
     81   stopifnot(part1(test_input, 10) == 40)
     82 }
     83 
     84 part2 <- function(input_lines) {
     85   coords <- parse_input(input_lines)
     86   last_pair <- greedy_connect(coords)$last_pair
     87 
     88   prod(coords[last_pair, ][, 1])
     89 }
     90 
     91 test_part2 <- function() {
     92   stopifnot(part2(test_input) == 25272)
     93 }
     94 
     95 main <- function() {
     96   test_part1()
     97   cat("Part 1 solution: ", part1(puzzle_input, 1000), "\n")
     98   test_part2()
     99   cat("Part 2 solution: ", part2(puzzle_input), "\n")
    100 }
    101 
    102 main()