stayerc

Advent Of Code 2025 Day 9

Dec 9th, 2025
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.60 KB | Source Code | 0 0
  1. const std = @import("std");
  2. const parseInt = std.fmt.parseInt;
  3.  
  4. const Coords = struct { x: u64, y: u64 };
  5. const Edge = struct {
  6. x1: u64,
  7. y1: u64,
  8. x2: u64,
  9. y2: u64,
  10. horizontal: bool,
  11. };
  12.  
  13. fn partOne(stdout: *std.Io.Writer, allocator: std.mem.Allocator) !void {
  14. const file = try std.fs.cwd().openFile("data.txt", .{ .mode = .read_only });
  15. defer file.close();
  16.  
  17. var file_buffer: [4096]u8 = undefined;
  18. var file_reader = file.reader(&file_buffer);
  19. const reader = &file_reader.interface;
  20.  
  21. var list: std.ArrayList(Coords) = .empty;
  22. defer list.deinit(allocator);
  23.  
  24. while (reader.takeDelimiterExclusive('\n')) |line| {
  25. reader.toss(1);
  26.  
  27. var it = std.mem.tokenizeAny(u8, line, ",");
  28. const first_str = it.next().?;
  29. const x = try parseInt(u64, first_str, 10);
  30. const second_str = it.next().?;
  31. const y = try parseInt(u64, second_str, 10);
  32.  
  33. const coord = Coords{ .x = x, .y = y };
  34. try list.append(allocator, coord);
  35. } else |err| switch (err) {
  36. error.EndOfStream => {},
  37. else => return err,
  38. }
  39.  
  40. var largest_area: u64 = 0;
  41.  
  42. for (list.items, 0..) |first, i| {
  43. for (list.items, 0..) |second, j| {
  44. if (i == j) continue;
  45.  
  46. const dx = if (first.x > second.x) first.x - second.x + 1 else second.x - first.x + 1;
  47. const dy = if (first.y > second.y) first.y - second.y + 1 else second.y - first.y + 1;
  48.  
  49. const area = dx * dy;
  50. if (area > largest_area) largest_area = area;
  51. }
  52. }
  53.  
  54. try stdout.print("Largest area: {d}\n", .{largest_area});
  55. try stdout.flush();
  56. }
  57.  
  58. fn pointOnEdge(x: u64, y: u64, edges: []Edge) bool {
  59. for (edges) |e| {
  60. if (e.horizontal) {
  61. if (y == e.y1 and x >= e.x1 and x <= e.x2) return true;
  62. } else {
  63. if (x == e.x1 and y >= e.y1 and y <= e.y2) return true;
  64. }
  65. }
  66. return false;
  67. }
  68.  
  69. fn pointInPolygon(x: u64, y: u64, edges: []Edge) bool {
  70. if (pointOnEdge(x, y, edges)) return true;
  71.  
  72. var inside: bool = false;
  73.  
  74. for (edges) |e| {
  75. if (e.horizontal) continue;
  76.  
  77. const ey = y;
  78. const y0 = e.y1;
  79. const y1 = e.y2;
  80. if (!(y0 <= ey and ey < y1)) continue;
  81.  
  82. if (e.x1 > x) inside = !inside;
  83. }
  84. return inside;
  85. }
  86.  
  87. fn overlapsPositive(a0: u64, a1: u64, b0: u64, b1: u64) bool {
  88. const left = if (a0 > b0) a0 else b0;
  89. const right = if (a1 < b1) a1 else b1;
  90.  
  91. return right > left;
  92. }
  93.  
  94. fn rectangleInsidePolygon(
  95. xmin: u64,
  96. ymin: u64,
  97. xmax: u64,
  98. ymax: u64,
  99. edges: []Edge,
  100. ) bool {
  101. if (xmin > xmax or ymin > ymax) return false;
  102.  
  103. const mx = xmin + (xmax - xmin) / 2;
  104. const my = ymin + (ymax - ymin) / 2;
  105. if (!pointInPolygon(mx, my, edges)) return false;
  106.  
  107. for (edges) |e| {
  108. if (e.horizontal) {
  109. if ((e.y1 > ymin) and (e.y1 < ymax)) {
  110. if (overlapsPositive(e.x1, e.x2, xmin, xmax)) return false;
  111. }
  112. } else {
  113. if ((e.x1 > xmin) and (e.x1 < xmax)) {
  114. if (overlapsPositive(e.y1, e.y2, ymin, ymax)) return false;
  115. }
  116. }
  117. }
  118.  
  119. return true;
  120. }
  121.  
  122. fn partTwo(stdout: *std.Io.Writer, allocator: std.mem.Allocator) !void {
  123. const file = try std.fs.cwd().openFile("data.txt", .{ .mode = .read_only });
  124. defer file.close();
  125.  
  126. var file_buffer: [4096]u8 = undefined;
  127. var file_reader = file.reader(&file_buffer);
  128. const reader = &file_reader.interface;
  129.  
  130. var list: std.ArrayList(Coords) = .empty;
  131. defer list.deinit(allocator);
  132.  
  133. while (reader.takeDelimiterExclusive('\n')) |line| {
  134. reader.toss(1);
  135.  
  136. var it = std.mem.tokenizeAny(u8, line, ",");
  137. const first_str = it.next().?;
  138. const x = try parseInt(u64, first_str, 10);
  139. const second_str = it.next().?;
  140. const y = try parseInt(u64, second_str, 10);
  141.  
  142. const coord = Coords{ .x = x, .y = y };
  143. try list.append(allocator, coord);
  144. } else |err| switch (err) {
  145. error.EndOfStream => {},
  146. else => return err,
  147. }
  148.  
  149. var edges: std.ArrayList(Edge) = .empty;
  150. defer edges.deinit(allocator);
  151.  
  152. const n = list.items.len;
  153. var i: usize = 0;
  154. while (i < n) : (i += 1) {
  155. const j = if (i + 1 == n) 0 else i + 1;
  156. const a = list.items[i];
  157. const b = list.items[j];
  158.  
  159. if (a.x != b.x and a.y != b.y) {
  160. return error.InvalidEdge;
  161. }
  162.  
  163. if (a.x == b.x) {
  164. const y0 = if (a.y <= b.y) a.y else b.y;
  165. const y1 = if (a.y <= b.y) b.y else a.y;
  166. try edges.append(allocator, Edge{
  167. .x1 = a.x,
  168. .y1 = y0,
  169. .x2 = a.x,
  170. .y2 = y1,
  171. .horizontal = false,
  172. });
  173. } else {
  174. const x0 = if (a.x <= b.x) a.x else b.x;
  175. const x1 = if (a.x <= b.x) b.x else a.x;
  176. try edges.append(allocator, Edge{
  177. .x1 = x0,
  178. .y1 = a.y,
  179. .x2 = x1,
  180. .y2 = a.y,
  181. .horizontal = true,
  182. });
  183. }
  184. }
  185.  
  186. var largest_area: u64 = 0;
  187. for (list.items, 0..) |a, idx| {
  188. for (list.items[idx + 1 ..]) |b| {
  189. const xmin = if (a.x < b.x) a.x else b.x;
  190. const xmax = if (a.x < b.x) b.x else a.x;
  191. const ymin = if (a.y < b.y) a.y else b.y;
  192. const ymax = if (a.y < b.y) b.y else a.y;
  193.  
  194. if (rectangleInsidePolygon(xmin, ymin, xmax, ymax, edges.items)) {
  195. const area = (xmax - xmin + 1) * (ymax - ymin + 1);
  196. if (area > largest_area) largest_area = area;
  197. }
  198. }
  199. }
  200.  
  201. try stdout.print("Largest area: {d}\n", .{largest_area});
  202. try stdout.flush();
  203. }
  204.  
  205. pub fn main() !void {
  206. var stdout_buffer: [1024]u8 = undefined;
  207. var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
  208. const stdout = &stdout_writer.interface;
  209. const day: u8 = 9;
  210. try stdout.print("Start of Day {d} Part 1\n", .{day});
  211. try stdout.print("--" ** 20 ++ "\n", .{});
  212. try stdout.flush();
  213. var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  214. defer arena.deinit();
  215. const allocator = arena.allocator();
  216. try partOne(stdout, allocator);
  217. try stdout.print("--" ** 20 ++ "\n", .{});
  218. try stdout.print("Start of Day {d} Part 2\n", .{day});
  219. try stdout.print("--" ** 20 ++ "\n", .{});
  220. try stdout.flush();
  221. try partTwo(stdout, allocator);
  222. }
  223.  
Advertisement
Add Comment
Please, Sign In to add comment