From d1e798bdbf149aad36422aaceeea8a42a08774a8 Mon Sep 17 00:00:00 2001 From: ktkk Date: Tue, 9 Dec 2025 09:17:25 +0000 Subject: [PATCH 1/4] Finish day09, part 1 --- src/days/day09.zig | 88 ++++++- src/days/input/day09.txt | 496 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 582 insertions(+), 2 deletions(-) create mode 100755 src/days/input/day09.txt diff --git a/src/days/day09.zig b/src/days/day09.zig index 5b8cfab..e85cb36 100644 --- a/src/days/day09.zig +++ b/src/days/day09.zig @@ -1,7 +1,91 @@ const std = @import("std"); -pub const title = "Day 09"; +pub const title = "Day 09: Movie Theater"; -pub fn run(_: std.mem.Allocator) !void { +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 + // ; + + var lines = std.mem.tokenizeScalar(u8, input, '\n'); + + var tiles: std.ArrayList(Tile) = .empty; + defer tiles.deinit(allocator); + + while (lines.next()) |line| { + var coordinates = std.mem.tokenizeScalar(u8, line, ','); + const x = blk: { + const s = coordinates.next() orelse continue; + break :blk try std.fmt.parseUnsigned(u64, s, 10); + }; + const y = blk: { + const s = coordinates.next() orelse continue; + break :blk try std.fmt.parseUnsigned(u64, s, 10); + }; + try tiles.append(allocator, .{ .x = x, .y = y }); + } + + var largest_area: usize = 0; + var largest_rectangle: Rectangle = undefined; + for (tiles.items, 0..) |first_tile, i| { + for (tiles.items[i + 1..]) |second_tile| { + const rectangle = first_tile.rectangle(second_tile); + const area = rectangle.area(); + if (area > largest_area) { + largest_area = area; + largest_rectangle = rectangle; + } + } + } + + std.debug.print("rectangle = {f}\n", .{largest_rectangle}); + + var buffer: [64]u8 = undefined; + var stdout_writer = std.fs.File.stdout().writer(&buffer); + const stdout = &stdout_writer.interface; + + try stdout.print("{d}\n", .{largest_area}); + + try stdout.flush(); } +const Tile = struct { + x: u64, + y: u64, + + const Self = @This(); + + pub fn format(self: Self, w: *std.io.Writer) std.io.Writer.Error!void { + try w.print("{d},{d}", .{self.x, self.y}); + } + + pub fn rectangle(self: Self, other_corner: Self) Rectangle { + return .{ .a = self, .b = other_corner }; + } +}; + +const Rectangle = struct { + a: Tile, + b: Tile, + + const Self = @This(); + + pub fn format(self: Self, w: *std.io.Writer) std.io.Writer.Error!void { + try w.print("{f} to {f}", .{self.a, self.b}); + } + + pub fn area(self: Self) u64 { + const width = @max(self.a.x, self.b.x) - @min(self.a.x, self.b.x) + 1; + const height = @max(self.a.y, self.b.y) - @min(self.a.y, self.b.y) + 1; + return width * height; + } +}; + diff --git a/src/days/input/day09.txt b/src/days/input/day09.txt new file mode 100755 index 0000000..44cac4b --- /dev/null +++ b/src/days/input/day09.txt @@ -0,0 +1,496 @@ +98241,50245 +98241,51464 +98122,51464 +98122,52660 +97649,52660 +97649,53867 +97585,53867 +97585,55104 +97774,55104 +97774,56255 +97196,56255 +97196,57546 +97636,57546 +97636,58780 +97591,58780 +97591,59958 +97238,59958 +97238,61063 +96596,61063 +96596,62184 +96091,62184 +96091,63423 +96024,63423 +96024,64739 +96152,64739 +96152,65592 +94869,65592 +94869,66846 +94784,66846 +94784,67925 +94219,67925 +94219,69237 +94206,69237 +94206,70195 +93369,70195 +93369,71228 +92725,71228 +92725,72421 +92396,72421 +92396,73353 +91573,73353 +91573,74531 +91190,74531 +91190,75402 +90295,75402 +90295,76446 +89686,76446 +89686,77385 +88921,77385 +88921,78413 +88284,78413 +88284,79671 +87931,79671 +87931,80568 +87102,80568 +87102,81220 +85994,81220 +85994,82478 +85581,82478 +85581,83480 +84863,83480 +84863,83949 +83605,83949 +83605,84603 +82559,84603 +82559,85593 +81829,85593 +81829,86686 +81171,86686 +81171,87253 +80061,87253 +80061,87969 +79082,87969 +79082,88669 +78093,88669 +78093,89502 +77196,89502 +77196,90250 +76233,90250 +76233,91130 +75347,91130 +75347,91250 +74000,91250 +74000,92327 +73212,92327 +73212,92894 +72128,92894 +72128,93270 +70952,93270 +70952,93370 +69660,93370 +69660,94478 +68819,94478 +68819,94708 +67595,94708 +67595,95183 +66472,95183 +66472,95207 +65195,95207 +65195,96147 +64221,96147 +64221,96615 +63081,96615 +63081,96461 +61777,96461 +61777,97201 +60700,97201 +60700,97015 +59412,97015 +59412,97740 +58305,97740 +58305,97562 +57038,97562 +57038,97176 +55764,97176 +55764,97302 +54566,97302 +54566,97656 +53385,97656 +53385,98146 +52195,98146 +52195,97889 +50969,97889 +50969,97871 +49756,97871 +49756,97859 +48543,97859 +48543,97449 +47351,97449 +47351,97738 +46119,97738 +46119,97642 +44909,97642 +44909,97226 +43740,97226 +43740,97219 +42519,97219 +42519,96788 +41367,96788 +41367,97309 +40026,97309 +40026,96882 +38868,96882 +38868,96221 +37780,96221 +37780,95804 +36640,95804 +36640,96136 +35265,96136 +35265,95792 +34086,95792 +34086,94892 +33112,94892 +33112,94733 +31866,94733 +31866,94172 +30777,94172 +30777,93317 +29828,93317 +29828,92857 +28705,92857 +28705,92156 +27705,92156 +27705,91484 +26696,91484 +26696,91543 +25258,91543 +25258,90924 +24200,90924 +24200,90213 +23201,90213 +23201,89043 +22528,89043 +22528,88927 +21108,88927 +21108,88089 +20204,88089 +20204,87315 +19255,87315 +19255,86250 +18557,86250 +18557,85773 +17347,85773 +17347,84679 +16696,84679 +16696,83809 +15843,83809 +15843,82679 +15268,82679 +15268,82055 +14153,82055 +14153,81303 +13157,81303 +13157,80213 +12558,80213 +12558,79102 +12004,79102 +12004,78475 +10804,78475 +10804,76971 +10824,76971 +10824,76102 +9952,76102 +9952,75038 +9369,75038 +9369,74238 +8339,74238 +8339,72905 +8231,72905 +8231,71987 +7378,71987 +7378,70721 +7205,70721 +7205,69997 +5885,69997 +5885,68793 +5582,68793 +5582,67760 +4871,67760 +4871,66522 +4679,66522 +4679,65214 +4737,65214 +4737,64207 +3895,64207 +3895,62932 +3915,62932 +3915,61848 +3259,61848 +3259,60571 +3366,60571 +3366,59436 +2864,59436 +2864,58155 +3122,58155 +3122,57084 +2124,57084 +2124,55838 +2213,55838 +2213,54652 +1807,54652 +1807,53424 +1794,53424 +1794,52197 +1810,52197 +1810,50973 +1890,50973 +1890,50228 +94822,50228 +94822,48525 +1557,48525 +1557,47341 +2383,47341 +2383,46107 +2110,46107 +2110,44867 +1961,44867 +1961,43734 +2727,43734 +2727,42467 +2452,42467 +2452,41283 +2754,41283 +2754,40077 +2933,40077 +2933,38872 +3134,38872 +3134,37713 +3522,37713 +3522,36439 +3506,36439 +3506,35262 +3852,35262 +3852,34252 +4684,34252 +4684,33262 +5505,33262 +5505,32101 +5846,32101 +5846,31022 +6392,31022 +6392,29688 +6381,29688 +6381,28480 +6689,28480 +6689,27621 +7685,27621 +7685,26247 +7715,26247 +7715,25643 +9102,25643 +9102,24398 +9389,24398 +9389,23514 +10255,23514 +10255,22573 +11021,22573 +11021,21166 +11150,21166 +11150,20538 +12337,20538 +12337,19792 +13336,19792 +13336,18451 +13627,18451 +13627,17941 +14878,17941 +14878,16560 +15179,16560 +15179,15977 +16322,15977 +16322,14917 +16989,14917 +16989,14500 +18254,14500 +18254,13050 +18605,13050 +18605,12768 +19956,12768 +19956,11585 +20576,11585 +20576,11164 +21786,11164 +21786,10359 +22708,10359 +22708,9858 +23836,9858 +23836,8777 +24596,8777 +24596,8258 +25713,8258 +25713,7978 +26955,7978 +26955,7540 +28095,7540 +28095,6507 +28940,6507 +28940,6682 +30363,6682 +30363,6251 +31489,6251 +31489,5782 +32598,5782 +32598,4548 +33429,4548 +33429,4750 +34790,4750 +34790,4015 +35829,4015 +35829,4049 +37104,4049 +37104,3690 +38261,3690 +38261,2708 +39279,2708 +39279,3314 +40653,3314 +40653,2568 +41748,2568 +41748,2300 +42941,2300 +42941,2002 +44135,2002 +44135,2479 +45412,2479 +45412,1845 +46579,1845 +46579,2346 +47826,2346 +47826,2049 +49029,2049 +49029,2462 +50242,2462 +50242,2326 +51451,2326 +51451,1711 +52695,1711 +52695,1956 +53904,1956 +53904,1808 +55148,1808 +55148,2309 +56320,2309 +56320,3006 +57444,3006 +57444,3165 +58640,3165 +58640,3456 +59812,3456 +59812,3478 +61045,3478 +61045,3412 +62316,3412 +62316,4049 +63401,4049 +63401,4368 +64572,4368 +64572,4266 +65892,4266 +65892,5403 +66775,5403 +66775,5880 +67884,5880 +67884,6132 +69090,6132 +69090,6792 +70119,6792 +70119,6784 +71472,6784 +71472,7784 +72326,7784 +72326,8026 +73577,8026 +73577,8876 +74490,8876 +74490,8978 +75860,8978 +75860,9930 +76701,9930 +76701,10352 +77896,10352 +77896,11232 +78772,11232 +78772,11817 +79867,11817 +79867,12626 +80792,12626 +80792,14062 +81171,14062 +81171,14424 +82471,14424 +82471,15055 +83557,15055 +83557,16158 +84188,16158 +84188,16772 +85314,16772 +85314,18188 +85573,18188 +85573,18598 +86957,18598 +86957,19899 +87301,19899 +87301,20942 +87937,20942 +87937,21902 +88675,21902 +88675,22692 +89662,22692 +89662,23972 +89932,23972 +89932,24741 +90987,24741 +90987,25832 +91538,25832 +91538,27127 +91708,27127 +91708,28094 +92461,28094 +92461,29086 +93191,29086 +93191,30203 +93671,30203 +93671,31293 +94211,31293 +94211,32525 +94402,32525 +94402,33715 +94665,33715 +94665,34739 +95400,34739 +95400,35775 +96158,35775 +96158,36914 +96627,36914 +96627,38153 +96733,38153 +96733,39465 +96473,39465 +96473,40509 +97404,40509 +97404,41858 +96797,41858 +96797,42955 +97601,42955 +97601,44214 +97352,44214 +97352,45389 +97756,45389 +97756,46601 +97847,46601 +97847,47809 +98021,47809 +98021,49037 +97534,49037 +97534,50245 From 1d6cdccaf8c18a2e70fc852fa1a530b61a9fab95 Mon Sep 17 00:00:00 2001 From: ktkk Date: Tue, 9 Dec 2025 09:24:55 +0000 Subject: [PATCH 2/4] Vectors! --- src/days/day09.zig | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/days/day09.zig b/src/days/day09.zig index e85cb36..0a0044b 100644 --- a/src/days/day09.zig +++ b/src/days/day09.zig @@ -30,7 +30,7 @@ pub fn run(allocator: std.mem.Allocator) !void { const s = coordinates.next() orelse continue; break :blk try std.fmt.parseUnsigned(u64, s, 10); }; - try tiles.append(allocator, .{ .x = x, .y = y }); + try tiles.append(allocator, .{ .pos = .{ x, y } }); } var largest_area: usize = 0; @@ -58,13 +58,12 @@ pub fn run(allocator: std.mem.Allocator) !void { } const Tile = struct { - x: u64, - y: u64, + pos: @Vector(2, u64), const Self = @This(); pub fn format(self: Self, w: *std.io.Writer) std.io.Writer.Error!void { - try w.print("{d},{d}", .{self.x, self.y}); + try w.print("{d},{d}", .{self.pos[0], self.pos[1]}); } pub fn rectangle(self: Self, other_corner: Self) Rectangle { @@ -83,9 +82,12 @@ const Rectangle = struct { } pub fn area(self: Self) u64 { - const width = @max(self.a.x, self.b.x) - @min(self.a.x, self.b.x) + 1; - const height = @max(self.a.y, self.b.y) - @min(self.a.y, self.b.y) + 1; - return width * height; + const cond = self.a.pos > self.b.pos; + const high = @select(u64, cond, self.a.pos, self.b.pos); + const low = @select(u64, !cond, self.a.pos, self.b.pos); + const diff = high - low; + const one: @Vector(2, u64) = @splat(1); + return @reduce(.Mul, diff + one); } }; From 605b5ee85ad5d5f4e591b5d4910a809a6a0fc054 Mon Sep 17 00:00:00 2001 From: ktkk Date: Tue, 9 Dec 2025 16:32:37 +0000 Subject: [PATCH 3/4] WIP: implement part 2 --- src/days/day09.zig | 94 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 13 deletions(-) diff --git a/src/days/day09.zig b/src/days/day09.zig index 0a0044b..b51820c 100644 --- a/src/days/day09.zig +++ b/src/days/day09.zig @@ -3,24 +3,26 @@ 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); + var index: usize = 0; while (lines.next()) |line| { + defer index += 1; var coordinates = std.mem.tokenizeScalar(u8, line, ','); const x = blk: { const s = coordinates.next() orelse continue; @@ -30,20 +32,53 @@ pub fn run(allocator: std.mem.Allocator) !void { const s = coordinates.next() orelse continue; break :blk try std.fmt.parseUnsigned(u64, s, 10); }; - try tiles.append(allocator, .{ .pos = .{ x, y } }); + 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}); } 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| { 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; + } + } + } + const area = rectangle.area(); if (area > largest_area) { largest_area = area; largest_rectangle = rectangle; } } + break; } std.debug.print("rectangle = {f}\n", .{largest_rectangle}); @@ -58,6 +93,7 @@ pub fn run(allocator: std.mem.Allocator) !void { } const Tile = struct { + index: usize, pos: @Vector(2, u64), const Self = @This(); @@ -67,20 +103,52 @@ const Tile = struct { } pub fn rectangle(self: Self, other_corner: Self) Rectangle { - return .{ .a = self, .b = other_corner }; + const a = self; + const b = other_corner; + return .{ + .a = a, + .b = b, + .c = .{ b.pos[0], a.pos[1] }, + .d = .{ a.pos[0], b.pos[1] }, + }; } }; +/// 0,0 1,0 +/// a ---- c +/// | | +/// | | +/// d ---- b +/// 0,1 1,1 const Rectangle = struct { a: Tile, b: Tile, + c: @Vector(2, u64), + d: @Vector(2, u64), + const Self = @This(); pub fn format(self: Self, w: *std.io.Writer) std.io.Writer.Error!void { try w.print("{f} to {f}", .{self.a, self.b}); } + pub fn width(self: Self) u64 { + const cond = self.a.pos > self.b.pos; + const high = @select(u64, cond, self.a.pos, self.b.pos); + const low = @select(u64, !cond, self.a.pos, self.b.pos); + const diff = high - low; + return diff[0] + 1; + } + + pub fn height(self: Self) u64 { + const cond = self.a.pos > self.b.pos; + const high = @select(u64, cond, self.a.pos, self.b.pos); + const low = @select(u64, !cond, self.a.pos, self.b.pos); + const diff = high - low; + return diff[1] + 1; + } + pub fn area(self: Self) u64 { const cond = self.a.pos > self.b.pos; const high = @select(u64, cond, self.a.pos, self.b.pos); From 5a8bf213860ea17d6af4ef18a60dfcb8df259df9 Mon Sep 17 00:00:00 2001 From: ktkk Date: Tue, 9 Dec 2025 21:09:38 +0000 Subject: [PATCH 4/4] 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 {