From 5a8bf213860ea17d6af4ef18a60dfcb8df259df9 Mon Sep 17 00:00:00 2001 From: ktkk Date: Tue, 9 Dec 2025 21:09:38 +0000 Subject: [PATCH] Finish day09, part 2 This doesn't work on the example but it does work on the actual dataset. TODO: Fix that --- src/days/day09.zig | 167 +++++++++++++++++++++++++++++++++------------ 1 file changed, 124 insertions(+), 43 deletions(-) diff --git a/src/days/day09.zig b/src/days/day09.zig index b51820c..c167255 100644 --- a/src/days/day09.zig +++ b/src/days/day09.zig @@ -3,23 +3,24 @@ const std = @import("std"); pub const title = "Day 09: Movie Theater"; pub fn run(allocator: std.mem.Allocator) !void { - //const input = @embedFile("./input/day09.txt"); - const input = - \\7,1 - \\11,1 - \\11,7 - \\9,7 - \\9,5 - \\2,5 - \\2,3 - \\7,3 - ; + const input = @embedFile("./input/day09.txt"); + //const input = + // \\7,1 + // \\11,1 + // \\11,7 + // \\9,7 + // \\9,5 + // \\2,5 + // \\2,3 + // \\7,3 + // ; var lines = std.mem.tokenizeScalar(u8, input, '\n'); var tiles: std.ArrayList(Tile) = .empty; defer tiles.deinit(allocator); + std.debug.print("parsing tiles...\n", .{}); var index: usize = 0; while (lines.next()) |line| { defer index += 1; @@ -35,39 +36,56 @@ pub fn run(allocator: std.mem.Allocator) !void { try tiles.append(allocator, .{ .index = index, .pos = .{ x, y } }); } - const width = 14; - const height = 9; - for (0..height) |y| { - var buffer: [width]u8 = [_]u8{'.'} ** width; - for (0..width) |x| { - for (tiles.items) |tile| { - if (@reduce(.And, tile.pos == @Vector(2, u64){ x, y })) { - buffer[x] = 'X'; - } - } - } - std.debug.print("{s}\n", .{buffer}); + std.debug.print("calculating edges...\n", .{}); + var edges: std.ArrayList(Edge) = .empty; + defer edges.deinit(allocator); + for (tiles.items, 0..) |tile, i| { + const a = tile; + const b = if (i == tiles.items.len - 1) tiles.items[0] else tiles.items[i + 1]; + try edges.append(allocator, Edge.fromTiles(a, b)); } + std.debug.print("finding largest rectangle...\n", .{}); var largest_area: usize = 0; var largest_rectangle: Rectangle = undefined; for (tiles.items, 0..) |first_tile, i| { - if (i == 0) continue; - for (tiles.items[i + 1..]) |second_tile| { + inner: for (tiles.items[i + 1..]) |second_tile| { const rectangle = first_tile.rectangle(second_tile); - const w = rectangle.width(); - const h = rectangle.height(); - std.debug.print("rectangle {d}-{d}\n", .{rectangle.a.index, rectangle.b.index}); - std.debug.print("width = {d}, height = {d}\n", .{w, h}); - if (w != 1 and h != 1) { - var verts_outside: bool = false; - for (tiles.items[first_tile.index + 1..second_tile.index]) |between| { - const cond = rectangle.c > between.pos; - if (@reduce(.Or, cond)) { - std.debug.print("vert c ({any}) of rect {d}-{d} is outside the shape\n", .{rectangle.c, rectangle.a.index, rectangle.b.index}); - verts_outside = true; - break; + std.debug.print("checking rectangle {f}...\n", .{rectangle}); + + const has_inside = rectangle.width() >= 3 and rectangle.height() >= 3; + if (has_inside) { + const one: @Vector(2, u64) = @splat(1); + const top_left = rectangle.topLeft() + one; + const bottom_right = rectangle.bottomRight() - one; + edge_loop: for (edges.items) |edge| { + if (edge.direction == .horizontal) { + if (edge.a.pos[1] < top_left[1] or edge.a.pos[1] > bottom_right[1]) { + continue :edge_loop; + } + + const start, const end = if (edge.a.pos[0] < edge.b.pos[0] + 1) .{ edge.a.pos[0], edge.b.pos[0] } else .{ edge.b.pos[0], edge.a.pos[0] + 1 }; + for (start..end) |ex| { + const edge_tile: @Vector(2, u64) = .{ ex, edge.a.pos[1] }; + if (top_left[0] <= edge_tile[0] and edge_tile[0] <= bottom_right[0]) { + std.debug.print("rectangle {f} hits edge {f}\n", .{rectangle, edge}); + continue :inner; + } + } + } else { + if (edge.a.pos[0] < top_left[0] or edge.a.pos[0] > bottom_right[0]) { + continue :edge_loop; + } + + const start, const end = if (edge.a.pos[1] < edge.b.pos[1] + 1) .{ edge.a.pos[1], edge.b.pos[1] } else .{ edge.b.pos[1], edge.a.pos[1] + 1 }; + for (start..end) |ey| { + const edge_tile: @Vector(2, u64) = .{ edge.a.pos[0], ey }; + if (top_left[1] <= edge_tile[1] and edge_tile[1] <= bottom_right[1]) { + std.debug.print("rectangle {f} hits edge {f}\n", .{rectangle, edge}); + continue :inner; + } + } } } } @@ -78,10 +96,10 @@ pub fn run(allocator: std.mem.Allocator) !void { largest_rectangle = rectangle; } } - break; } std.debug.print("rectangle = {f}\n", .{largest_rectangle}); + std.debug.print("top_left = {any}, bottom_right = {any}\n", .{largest_rectangle.topLeft(), largest_rectangle.bottomRight()}); var buffer: [64]u8 = undefined; var stdout_writer = std.fs.File.stdout().writer(&buffer); @@ -103,15 +121,41 @@ const Tile = struct { } pub fn rectangle(self: Self, other_corner: Self) Rectangle { - const a = self; - const b = other_corner; + return Rectangle.fromTiles(self, other_corner); + } +}; + +const Edge = struct { + a: Tile, + b: Tile, + + direction: Direction, + + const Self = @This(); + + const Direction = enum { + horizontal, + vertical, + }; + + pub fn fromTiles(a: Tile, b: Tile) Self { + const direction: Direction = if (a.pos[0] == b.pos[0]) + .vertical + else if (a.pos[1] == b.pos[1]) + .horizontal + else + unreachable; + return .{ .a = a, .b = b, - .c = .{ b.pos[0], a.pos[1] }, - .d = .{ a.pos[0], b.pos[1] }, + .direction = direction, }; } + + pub fn format(self: Self, w: *std.io.Writer) std.io.Writer.Error!void { + try w.print("{f} - {f}", .{self.a, self.b}); + } }; /// 0,0 1,0 @@ -129,8 +173,45 @@ const Rectangle = struct { const Self = @This(); + pub fn fromTiles(a: Tile, b: Tile) Self { + const cx = if (a.pos[0] <= b.pos[0]) b.pos[0] else a.pos[0]; + const cy = if (a.pos[1] >= b.pos[1]) a.pos[1] else b.pos[1]; + const dx = if (a.pos[0] <= b.pos[0]) a.pos[0] else b.pos[0]; + const dy = if (a.pos[1] >= b.pos[1]) b.pos[1] else a.pos[1]; + return .{ + .a = a, + .b = b, + .c = .{ cx, cy }, + .d = .{ dx, dy }, + }; + } + pub fn format(self: Self, w: *std.io.Writer) std.io.Writer.Error!void { - try w.print("{f} to {f}", .{self.a, self.b}); + try w.print("{d} to {d} ({f} - {d},{d} - {f} - {d},{d})", .{self.a.index, self.b.index, self.a, self.c[0], self.c[1], self.b, self.d[0], self.d[1]}); + } + + pub fn topLeft(self: Self) @Vector(2, u64) { + const verts = [_]@Vector(2, u64){ self.c, self.b.pos, self.d }; + var top_left: @Vector(2, u64) = self.a.pos; + for (verts) |vert| { + const cond = vert <= top_left; + if (@reduce(.And, cond)) { + top_left = vert; + } + } + return top_left; + } + + pub fn bottomRight(self: Self) @Vector(2, u64) { + const verts = [_]@Vector(2, u64){ self.d, self.a.pos, self.c }; + var bottom_right: @Vector(2, u64) = self.b.pos; + for (verts) |vert| { + const cond = vert >= bottom_right; + if (@reduce(.And, cond)) { + bottom_right = vert; + } + } + return bottom_right; } pub fn width(self: Self) u64 {