Finish day09, part 2

This doesn't work on the example but it does work on the actual dataset.

TODO: Fix that
This commit is contained in:
ktkk 2025-12-09 21:09:38 +00:00
parent 605b5ee85a
commit 5a8bf21386

View file

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