2025

— R Day 9 Part 1 —

solve_day9_part1 <- function(input) {
  coords <- read.table(text = input, sep = ",", col.names = c("row", "col"))
  coords <- as.matrix(coords)

  n_corners <- NROW(coords)
  pairs <- combn(n_corners, 2L)

  row_dist <- abs(coords[pairs[1, ], "row"] - coords[pairs[2, ], "row"]) + 1
  col_dist <- abs(coords[pairs[1, ], "col"] - coords[pairs[2, ], "col"]) + 1

  area <- row_dist * col_dist
  max(area)
}
Run
aoc_source(day = 9, part = 1)

input = aoc_read(day = 9)

aoc_run(solve_day9_part1(input))
Elapsed: 0.076 seconds
Memory:  9820 KB

— R Day 9 Part 2 —

solve_day9_part2 <- function(input) {
  coords <- read.table(text = input, sep = ",", col.names = c("row", "col"))
  coords <- as.matrix(coords)

  # Rectangle pairs ----
  n_corners <- NROW(coords)
  pairs <- t(combn(n_corners, 2L))
  n_pairs <- NROW(pairs)

  row_dist <- abs(coords[pairs[, 1], "row"] - coords[pairs[, 2], "row"]) + 1
  col_dist <- abs(coords[pairs[, 1], "col"] - coords[pairs[, 2], "col"]) + 1
  area <- row_dist * col_dist

  area_order <- order(area, decreasing = TRUE)
  area <- area[area_order]
  pairs <- pairs[area_order, ]

  # Rectangles bounds ----
  row_1 <- coords[pairs[, 1], "row"]
  col_1 <- coords[pairs[, 1], "col"]
  row_2 <- coords[pairs[, 2], "row"]
  col_2 <- coords[pairs[, 2], "col"]

  rects <- data.frame(
    min_row = pmin(row_1, row_2),
    max_row = pmax(row_1, row_2),
    min_col = pmin(col_1, col_2),
    max_col = pmax(col_1, col_2)
  )

  # Intersection check ----

  # Check each rect against each polygon edge for intersection
  # not a true polygon intersection but works
  # based on visual look at shape with plot(coords)
  for (rect_i in seq_len(n_pairs)) {
    rect <- rects[rect_i, ]
    rect_is_valid <- TRUE

    for (edge_i in seq_len(n_corners)) {
      point_1 <- coords[edge_i, ]

      if (edge_i == n_corners) {
        # last edge back to start
        edge_j <- 1
      } else {
        edge_j <- edge_i + 1
      }

      point_2 <- coords[edge_j, ]

      intersects <- edge_intersects_rect(rect, point_1, point_2)

      if (intersects) {
        rect_is_valid <- FALSE
        break
      }
    }

    if (rect_is_valid) {
      return(area[rect_i])
    }
  }
}

edge_intersects_rect <- function(rect, point_1, point_2) {
  row_1 <- point_1["row"]
  col_1 <- point_1["col"]
  row_2 <- point_2["row"]
  col_2 <- point_2["col"]

  # Horizontal edge
  if (row_1 == row_2) {
    edge_row  <- row_1
    edge_cmin <- min(col_1, col_2)
    edge_cmax <- max(col_1, col_2)

    if (edge_row <= rect$min_row || edge_row >= rect$max_row) {
      return(FALSE)
    }

    return(edge_cmax > rect$min_col && edge_cmin < rect$max_col)
  }

  # Vertical edge
  if (col_1 == col_2) {
    edge_col  <- col_1
    edge_rmin <- min(row_1, row_2)
    edge_rmax <- max(row_1, row_2)

    if (edge_col <= rect$min_col || edge_col >= rect$max_col) {
      return(FALSE)
    }

    return(edge_rmax > rect$min_row && edge_rmin < rect$max_row)
  }

  stop("not a straight edge")
}
Run
aoc_source(day = 9, part = 2)

input = aoc_read(day = 9)

aoc_run(solve_day9_part2(input))
Elapsed: 60.763 seconds
Memory:  21188 KB

— Python Day 9 Part 1 —

from shapely import box

def solve_day9_part1(text):
    coords = [line.split(",") for line in text]
    coords = [[int(num) for num in coord] for coord in coords]
    n_corners = len(coords)
    max_area = 0

    for i in range(n_corners):
        for j in range(n_corners):
            if i < j:
                r1, c1 = coords[i]
                r2, c2 = coords[j]
                rmin, rmax = sorted([r1, r2])
                cmin, cmax = sorted([c1, c2])

                rect = box(rmin, cmin, rmax, cmax)
                area = rect.area

                if area > max_area:
                    max_area = area

    return(int(max_area))
Run
aoc_source(day = 9, part = 1)

input = aoc_read(day = 9)

result = aoc_run("solve_day9_part1(input)")
Elapsed: 5.578 seconds
Memory:  212 KB

— Python Day 9 Part 2 —

from shapely import Polygon, box

def solve_day9_part2(text):
    coords = [line.split(",") for line in text]
    coords = [[int(num) for num in coord] for coord in coords]
    n_corners = len(coords)

    rects = []
    areas = []
    for i in range(n_corners):
        for j in range(n_corners):
            if i < j:
                r1, c1 = coords[i]
                r2, c2 = coords[j]
                rmin, rmax = sorted([r1, r2])
                cmin, cmax = sorted([c1, c2])

                rect = box(rmin, cmin, rmax, cmax)
                rects += [[rect, rect.area]]

    rects.sort(key = lambda x: x[1], reverse = True)
    rects, areas = zip(*rects)

    polygon = Polygon(coords)

    for i in range(len(areas)):
        if not polygon.covers(rects[i]):
            return(int(areas[i]))
Run
aoc_source(day = 9, part = 2)

input = aoc_read(day = 9)

result = aoc_run("solve_day9_part2(input)")
Elapsed: 6.601 seconds
Memory:  28887 KB
Back to top