You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
advent-of-code/2024/ruby/day_12.rb

81 lines
1.6 KiB

garden = DATA.readlines(chomp: true).flat_map.with_index {|row, y|
row.chars.map.with_index {|id, x| [[y,x], id] }
}.to_h
DELTAS = [[-1, 0], [1, 0], [0, -1], [0, 1]]
queue = Set[*garden.keys]
plots = [Set[queue.first]]
until queue.empty?
yx = plots.last.select { queue.include?(_1) }.first
if yx.nil?
plots << Set[queue.first] if queue.first
next
end
queue.delete(yx)
id = garden.fetch(yx)
neighbors = DELTAS
.map {|d| yx.zip(d).map { _1 + _2 }}
.select { garden.fetch(_1, nil) == id }
if neighbors.empty?
plots << Set[queue.first] if queue.first
else
plots.last.merge(neighbors)
end
end
perimeter = ->(plot) {
plot.flat_map {|yx|
DELTAS
.map {|delta| yx.zip(delta).map { _1 + _2 }}
.reject { garden.fetch(_1, nil) == garden[plot.first] }
}
}
pp plots
.map { [_1.size, perimeter[_1]] }
.sum { _1 * _2.length }
sides = ->(plot) {
id = garden.fetch(plot.first)
rows = plot.group_by(&:first).values.flat_map {|row|
[-1, 1].flat_map {|dy|
row
.map {|y,x| [y+dy, x] }
.reject { garden.fetch(_1, nil) == id }
.map(&:last)
.sort
.chunk_while { _1 + 1 == _2 }
}
}
cols = plot.group_by(&:last).values.flat_map {|row|
[-1, 1].flat_map {|dx|
row
.map {|y,x| [y, x+dx] }
.reject { garden.fetch(_1, nil) == id }
.map(&:first)
.sort
.chunk_while { _1 + 1 == _2 }
}
}
rows + cols
}
pp plots
.map { [garden.fetch(_1.first), _1.size, sides[_1]] }
.sum { _2 * _3.sum(&:count) }
__END__
RRRRIICCFF
RRRRIICCCF
VVRRRCCFFF
VVRCCCJFFF
VVVVCJJCFE
VVIVCCJJEE
VVIIICJJEE
MIIIIIJJEE
MIIISIJEEE
MMMISSJEEE