@@ -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