Skip to content

Commit 4ff6a3c

Browse files
committed
feat(2024): solution for day 12 part 2
1 parent 0a403b7 commit 4ff6a3c

File tree

1 file changed

+88
-24
lines changed

1 file changed

+88
-24
lines changed

2024/day12.zig

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -107,26 +107,36 @@ const GardenMap = struct {
107107
cols: usize = undefined,
108108
buffer: [][]u8 = undefined,
109109
processed: [][]bool = undefined,
110+
sides: [][]u8 = undefined,
110111

111112
pub fn init(allocator: Allocator, input: []const u8) !GardenMap {
112113
var instance = GardenMap{};
113114

114115
var row_it = std.mem.split(u8, input, "\n");
115116

116-
instance.cols = row_it.peek().?.len;
117-
instance.rows = 0;
117+
instance.cols = row_it.peek().?.len + 2;
118+
instance.rows = 2;
118119
while (row_it.next()) |_| : (instance.rows += 1) {}
119120
row_it.reset();
120121

121-
var x: usize = 0;
122+
// log.info("map size {d} × {d}", .{ instance.rows, instance.cols });
123+
122124
instance.buffer = try allocator.alloc([]u8, instance.cols);
123125
instance.processed = try allocator.alloc([]bool, instance.cols);
124-
while (row_it.next()) |row| : (x += 1) {
126+
instance.sides = try allocator.alloc([]u8, instance.cols);
127+
for (0..instance.cols) |x| {
125128
instance.buffer[x] = try allocator.alloc(u8, instance.rows);
126129
instance.processed[x] = try allocator.alloc(bool, instance.rows);
130+
instance.sides[x] = try allocator.alloc(u8, instance.rows);
131+
var row: ?[]const u8 = null;
132+
if (x > 0) row = row_it.next();
127133
for (0..instance.rows) |y| {
128-
instance.buffer[x][y] = row[y];
134+
instance.buffer[x][y] = ' ';
135+
if (row != null and y > 0 and y < instance.rows - 1) {
136+
instance.buffer[x][y] = row.?[y - 1];
137+
}
129138
instance.processed[x][y] = false;
139+
instance.sides[x][y] = ' ';
130140
}
131141
}
132142

@@ -157,14 +167,15 @@ const GardenMap = struct {
157167
}
158168

159169
pub fn findRegions(self: *GardenMap, allocator: Allocator) ![]Region {
160-
log.info(t.hide_cursor, .{});
161-
log.info(t.clear_screen, .{});
170+
// log.info(t.hide_cursor, .{});
171+
// log.info(t.clear_screen, .{});
162172

163173
var regions = std.ArrayList(Region).init(allocator);
164174
var all_points = VectorSet(2, usize).init(allocator);
165175

166176
for (0..self.buffer.len) |y| {
167177
for (0..self.buffer[0].len) |x| {
178+
if (self.buffer[y][x] == ' ') continue;
168179
try all_points.insert(.{ x, y });
169180
}
170181
}
@@ -214,23 +225,59 @@ const GardenMap = struct {
214225
}
215226
}
216227

217-
var processed_per_pos = VectorSet(2, isize).init(allocator);
218-
var per_pos_it = perimeter_positions.iterator();
228+
var visited = VectorSet(3, isize).init(allocator);
229+
var perimeter_dir_positions = VectorSet(3, isize).init(allocator);
230+
var perimeter_pos_it = perimeter_positions.iterator();
231+
while (perimeter_pos_it.next()) |p| {
232+
inline for (std.meta.fields(Dir)) |d| {
233+
const tile = p.* + @as(Dir, @enumFromInt(d.value)).toVec();
234+
if (tile[0] > 0 and tile[1] > 0 and region.tiles.contains(@intCast(tile))) {
235+
try perimeter_dir_positions.insert(@Vector(3, isize){ p[0], p[1], d.value });
236+
}
237+
}
238+
}
239+
var perimeter_dir_pos_it = perimeter_dir_positions.iterator();
240+
219241
var sides: usize = 0;
220-
while (per_pos_it.next()) |pos| {
221-
// var other_it = perimeter_positions.iterator();
222-
if (processed_per_pos.contains(pos.*)) continue;
223-
try processed_per_pos.insert(pos.*);
224-
// while (other_it.next()) |other_pos| {
225-
// if (@reduce(.And, other_pos.* == pos.*)) continue;
226-
// const diff = pos.* - other_pos.*;
227-
// log.info("{d} - {d} == {d}", .{ pos.*, other_pos.*, diff });
228-
// }
242+
243+
self.cleanSidesMap();
244+
while (perimeter_dir_pos_it.next()) |curr| {
245+
if (visited.contains(curr.*)) continue;
229246
sides += 1;
247+
248+
var nq = std.ArrayList(@Vector(3, isize)).init(allocator);
249+
try nq.append(curr.*);
250+
defer nq.deinit();
251+
252+
while (nq.items.len > 0) {
253+
const next_n = nq.pop();
254+
if (visited.contains(next_n)) continue;
255+
256+
// self.sides[@intCast(next_n[1])][@intCast(next_n[0])] = 'X';
257+
// std.debug.print("\nSides: {d}", .{sides});
258+
// self.printSidesMap();
259+
// aoc.blockAskForNext();
260+
261+
try visited.insert(next_n);
262+
const neighbours = [_]@Vector(3, isize){
263+
@as(@Vector(3, isize), @intCast(next_n)) +| @Vector(3, isize){ -1, 0, 0 },
264+
@as(@Vector(3, isize), @intCast(next_n)) +| @Vector(3, isize){ 0, -1, 0 },
265+
@as(@Vector(3, isize), @intCast(next_n)) +| @Vector(3, isize){ 1, 0, 0 },
266+
@as(@Vector(3, isize), @intCast(next_n)) +| @Vector(3, isize){ 0, 1, 0 },
267+
};
268+
for (0..neighbours.len) |i| {
269+
const n = neighbours[i];
270+
if (perimeter_dir_positions.contains(n) and
271+
(n[0] == curr[0] or n[1] == curr[1]))
272+
{
273+
try nq.append(n);
274+
}
275+
}
276+
}
230277
}
278+
231279
region.sides = sides;
232-
log.info("{any}", .{region});
233-
aoc.blockAskForNext();
280+
// log.info("# Sides: {d}", .{region.sides});
234281

235282
var tile_it = region.tiles.iterator();
236283
while (tile_it.next()) |tile| {
@@ -242,6 +289,23 @@ const GardenMap = struct {
242289
return regions.items;
243290
}
244291

292+
pub fn cleanSidesMap(self: *GardenMap) void {
293+
for (0..self.cols) |x| {
294+
for (0..self.rows) |y| {
295+
self.sides[x][y] = ' ';
296+
}
297+
}
298+
}
299+
300+
pub fn printSidesMap(self: *GardenMap) void {
301+
for (0..self.cols) |x| {
302+
log.info("\n ", .{});
303+
for (0..self.rows) |y| {
304+
log.info("{c} ", .{self.sides[x][y]});
305+
}
306+
}
307+
}
308+
245309
pub fn format(self: GardenMap, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
246310
_ = fmt;
247311
_ = options;
@@ -283,7 +347,7 @@ fn part1(allocator: Allocator, input: []const u8) anyerror!void {
283347

284348
var total_prize: usize = 0;
285349
for (0..regions.len) |i| {
286-
log.info("{any}", .{regions[i]});
350+
// log.info("{any}", .{regions[i]});
287351
const region_price = try regions[i].calculatePriceWithPerimeter();
288352
total_prize += region_price;
289353
}
@@ -296,7 +360,7 @@ fn part2(allocator: Allocator, input: []const u8) anyerror!void {
296360

297361
var total_prize: usize = 0;
298362
for (0..regions.len) |i| {
299-
log.info("{any}", .{regions[i]});
363+
// log.info("{any}", .{regions[i]});
300364
const region_price = try regions[i].calculatePriceWithSides();
301365
total_prize += region_price;
302366
}
@@ -308,6 +372,6 @@ pub fn main() !void {
308372
defer arena.deinit();
309373
const allocator = arena.allocator();
310374

311-
// try aoc.runPart(allocator, 2024, DAY, .PUZZLE, part1);
312-
try aoc.runPart(allocator, 2024, DAY, .EXAMPLE, part2);
375+
try aoc.runPart(allocator, 2024, DAY, .PUZZLE, part1);
376+
try aoc.runPart(allocator, 2024, DAY, .PUZZLE, part2);
313377
}

0 commit comments

Comments
 (0)