Skip to content

Commit f3bbec3

Browse files
committed
DAY 12 PUZZLE 12
Key was calculating corners instead of edges.
1 parent 9d76f96 commit f3bbec3

File tree

2 files changed

+103
-42
lines changed

2 files changed

+103
-42
lines changed

β€Žlib/solutions/day_12.rbβ€Ž

Lines changed: 102 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,24 @@ def part_two(input)
1515
@cols = @map[0].length
1616
@visited = Array.new(@rows) { Array.new(@cols, false) }
1717

18+
@grid = Grid.new(@map)
19+
20+
price_perimeter, price_sides = @grid.calculate_price_area_perimeter
21+
22+
puts "Price perimeter: #{price_perimeter}"
23+
puts "Price sides: #{price_sides}"
24+
25+
price_sides
26+
end
27+
end
28+
29+
class Day12Part1
30+
def part_one(input)
31+
@map = input.split("\n")
32+
@rows = @map.length
33+
@cols = @map[0].length
34+
@visited = Array.new(@rows) { Array.new(@cols, false) }
35+
1836
total_price
1937
end
2038

@@ -71,65 +89,108 @@ def out_of_bounds?(row, col)
7189
end
7290
end
7391

74-
class Day12Part1
75-
def part_one(input)
76-
@map = input.split("\n")
77-
@rows = @map.length
78-
@cols = @map[0].length
79-
@visited = Array.new(@rows) { Array.new(@cols, false) }
92+
class Grid
93+
attr_reader :width, :height
8094

81-
total_price
82-
end
95+
def initialize(grid)
96+
@grid = grid
97+
@height = @grid.size
98+
@width = @grid[0].size
99+
@visited = Array.new(@height) { Array.new(@width, false) }
83100

84-
def total_price
85-
regions = find_regions
86-
regions.sum { |region| region[:area] * region[:perimeter] }
101+
# directions: up, down, left, right
102+
@directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]
87103
end
88104

89-
def find_regions
90-
regions = []
91-
(0...@rows).each do |row|
92-
(0...@cols).each do |col|
93-
next if @visited[row][col]
94-
95-
char = @map[row][col]
96-
area, perimeter = explore_region(row, col, char)
97-
regions << { area: area, perimeter: perimeter }
98-
end
99-
end
100-
regions
105+
def on_map?(x, y)
106+
# check if x, y coord exist
107+
x.between?(0, @height - 1) && y.between?(0, @width - 1)
101108
end
102109

103-
def explore_region(row, col, char)
104-
queue = [[row, col]]
110+
def find_plot_BFS(start_x, start_y)
111+
plant_type = @grid[start_x][start_y]
112+
queue = [[start_x, start_y]]
113+
@visited[start_x][start_y] = true
114+
105115
area = 0
106116
perimeter = 0
117+
cells = Set.new([[start_x, start_y]])
107118

108119
until queue.empty?
109-
current_row, current_col = queue.shift
110-
next if out_of_bounds?(current_row, current_col) || @visited[current_row][current_col]
111-
112-
next unless @map[current_row][current_col] == char
113-
114-
@visited[current_row][current_col] = true
120+
x, y = queue.shift
115121
area += 1
116122

117-
# Check all four directions
118-
[[0, 1], [1, 0], [0, -1], [-1, 0]].each do |dr, dc|
119-
new_row = current_row + dr
120-
new_col = current_col + dc
121-
if out_of_bounds?(new_row, new_col) || @map[new_row][new_col] != char
122-
perimeter += 1
123+
@directions.each do |dx, dy|
124+
nx = x + dx
125+
ny = y + dy
126+
127+
if on_map?(nx, ny)
128+
if @grid[nx][ny] == plant_type && !@visited[nx][ny]
129+
@visited[nx][ny] = true
130+
queue << [nx, ny]
131+
cells.add([nx, ny])
132+
elsif @grid[nx][ny] != plant_type
133+
perimeter += 1
134+
end
123135
else
124-
queue << [new_row, new_col] unless @visited[new_row][new_col]
136+
# Out of bounds contributes to perimeter
137+
perimeter += 1
125138
end
126139
end
127140
end
128141

129-
[area, perimeter]
142+
# Calculate the number of sides (== corners) for the plot
143+
sides = calculate_corners(cells)
144+
[area, perimeter, sides]
130145
end
131146

132-
def out_of_bounds?(row, col)
133-
row < 0 || row >= @rows || col < 0 || col >= @cols
147+
def calculate_corners(cells)
148+
corners = 0
149+
150+
cells.each do |cell|
151+
x, y = cell
152+
u = [x - 1, y] # Up
153+
d = [x + 1, y] # Down
154+
r = [x, y + 1] # Right
155+
l = [x, y - 1] # Left
156+
157+
# External corners
158+
corners += 1 if !cells.include?(u) && !cells.include?(r)
159+
corners += 1 if !cells.include?(r) && !cells.include?(d)
160+
corners += 1 if !cells.include?(d) && !cells.include?(l)
161+
corners += 1 if !cells.include?(l) && !cells.include?(u)
162+
163+
# Internal (diagonal) corners
164+
ur = [x - 1, y + 1] # Up-Right
165+
ul = [x - 1, y - 1] # Up-Left
166+
dr = [x + 1, y + 1] # Down-Right
167+
dl = [x + 1, y - 1] # Down-Left
168+
169+
corners += 1 if cells.include?(u) && cells.include?(r) && !cells.include?(ur)
170+
corners += 1 if cells.include?(r) && cells.include?(d) && !cells.include?(dr)
171+
corners += 1 if cells.include?(d) && cells.include?(l) && !cells.include?(dl)
172+
corners += 1 if cells.include?(l) && cells.include?(u) && !cells.include?(ul)
173+
end
174+
175+
corners
176+
end
177+
178+
def calculate_price_area_perimeter
179+
total_price_perimeter = 0
180+
total_price_sides = 0
181+
@visited = Array.new(@height) { Array.new(@width, false) }
182+
183+
@height.times do |x|
184+
@width.times do |y|
185+
next if @visited[x][y]
186+
187+
area, perimeter, sides = find_plot_BFS(x, y)
188+
total_price_perimeter += area * perimeter
189+
total_price_sides += area * sides
190+
end
191+
end
192+
193+
[total_price_perimeter, total_price_sides]
134194
end
135195
end
196+

β€Žspec/solutions/day_12_spec.rbβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
end
1212

1313
describe '#part_two' do
14-
xit 'calculates the correct solutions for part two' do
14+
it 'calculates the correct solutions for part two' do
1515
expect(subject.part_two(input)).to eq(1206)
1616
end
1717
end

0 commit comments

Comments
Β (0)