Snippet

advent_of_code/2024_12.rb
Code:
# Advent of Code 2024, Day 12: Garden Groups

# https://adventofcode.com/2024/day/12

require_relative './helpers.rb'

@seen = []

def crawl(grid, point)
  @seen.include?(point) ? (return [[], 0]) : (@seen << point)
  v, area, perimeter = get_grid(grid, point), [point], 0
  [[1, 0], [-1, 0], [0, 1], [0, -1]].each do |x, y|
    n_point = [point.x + x, point.y + y].to_p
    if get_grid(grid, n_point) == v
      crawl(grid, n_point).as { |a, p| area, perimeter = area + a, perimeter + p }
    else
      perimeter += 1
    end
  end
  return [area, perimeter]
end

def part_one(regions)
  regions.map { |area, perimeter| area.size * perimeter }.sum
end

def part_two(grid, regions)
  regions.map { |area, _|
    area.map { |point| [
        [[ 0, -1], [-1, -1], [-1,  0]], [[-1,  0], [-1,  1], [ 0,  1]],
        [[ 0,  1], [ 1,  1], [ 1,  0]], [[ 1,  0], [ 1, -1], [ 0, -1]],
      ].map { |c| c.map { |x, y| [point.x + x, point.y + y].to_p } }.map { |c|
        c.map { |n| area.include?(n) }.as { |i, j, k| ((i == k) && (!i || !j)) ? 1 : 0 }
      }.sum
    }.sum * area.size
  }.sum
end

def solve(data)
  grid, regions = data.map { |l| l.chomp.chars }, []
  draw_grid(grid) if grid.size < 20
  grid.size.times do |y|
    grid[0].size.times do |x|
      regions << crawl(grid, [x, y].to_p) unless @seen.include?([x, y].to_p)
    end
  end
  [part_one(regions), part_two(grid, regions)]
end

# puts solve(get_dataset(year: 2024, day: 12, type: 'example'))
# puts solve(get_dataset(year: 2024, day: 12, type: 'example_2'))
# puts solve(get_dataset(year: 2024, day: 12, type: 'example_3'))
puts solve(get_dataset(year: 2024, day: 12, type: 'example_4'))
# puts solve(get_dataset(year: 2024, day: 12, type: 'input'))
Output:
AAAAAA
AAABBA
AAABBA
ABBAAA
ABBAAA
AAAAAA
1184
368