From dba2aeadc88dc4c8e069592deee55eed71dd24b4 Mon Sep 17 00:00:00 2001 From: Inga Date: Sun, 7 Jan 2024 17:10:07 +0000 Subject: [PATCH] day 18, part 1 (improved in preparation to part 2) --- day18-easy/src/main.zig | 119 ++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 40 deletions(-) diff --git a/day18-easy/src/main.zig b/day18-easy/src/main.zig index 499b8be..06fc658 100644 --- a/day18-easy/src/main.zig +++ b/day18-easy/src/main.zig @@ -104,14 +104,59 @@ fn readNumber(comptime T: type, line: []const u8, index: *usize) T { return if (is_negative) (0 - result) else result; } -fn GenericTerrain(comptime CoordinateType: type, comptime height: CoordinateType, comptime width: CoordinateType, comptime CellType: type) type { +fn Coordinates(comptime CoordinateType: type) type { return struct { const Self = @This(); x: CoordinateType, y: CoordinateType, + + fn isSameX(self: *const Self, other: Self) bool { + return self.x == other.x; + } + + fn approachX(self: *Self, other: Self) void { + if (self.x < other.x) { + self.x += 1; + } else { + self.x -= 1; + } + } + + fn isSameY(self: *const Self, other: Self) bool { + return self.y == other.y; + } + + fn approachY(self: *Self, other: Self) void { + if (self.y < other.y) { + self.y += 1; + } else { + self.y -= 1; + } + } + }; +} + +fn GenericTerrain(comptime CoordinateType: type, comptime height: CoordinateType, comptime width: CoordinateType, comptime CellType: type) type { + return struct { + const Self = @This(); + coordinates: Coordinates(CoordinateType), cells: [height][width]CellType, fn initZeroes() Self { - return .{ .x = height / 2, .y = width / 2, .cells = std.mem.zeroes([height][width]CellType) }; + return .{ + .coordinates = .{ + .x = height / 2, + .y = width / 2, + }, + .cells = std.mem.zeroes([height][width]CellType), + }; + } + + fn getCurrentCell(self: *const Self) CellType { + return self.cells[self.coordinates.x][self.coordinates.y]; + } + + fn setCurrentCell(self: *Self, value: CellType) void { + self.cells[self.coordinates.x][self.coordinates.y] = value; } }; } @@ -126,10 +171,7 @@ const TerrainCoordinate = u16; const Terrain = GenericTerrain(TerrainCoordinate, 1024, 1024, CellStatus); -const FloodTask = struct { - x: TerrainCoordinate, - y: TerrainCoordinate, -}; +const TerrainCoordinates = Coordinates(TerrainCoordinate); const Direction = enum(u8) { Right = 0, @@ -140,24 +182,26 @@ const Direction = enum(u8) { const Command = packed struct(u32) { direction: Direction, - length: u24, + _: u8 = 0, + length: u16, }; fn floodTerrain(terrain: *Terrain) void { - var queue_mem: [65_536]FloodTask = undefined; - var tasks = RingQueueWrapper(FloodTask, queue_mem.len).init(&queue_mem); + var queue_mem: [65_536]TerrainCoordinates = undefined; + var tasks = RingQueueWrapper(TerrainCoordinates, queue_mem.len).init(&queue_mem); tasks.add(.{ .x = 0, .y = 0 }); while (!tasks.isEmpty()) { const task = tasks.take(); - const x = task.x; - const y = task.y; + terrain.coordinates = task; //std.debug.print("Processing task for {d},{d} (current status: {any})\n", .{ x, y, terrain.*.cells[x][y] }); - if (terrain.*.cells[x][y] == .Default) { - terrain.*.cells[x][y] = .NotDug; + if (terrain.getCurrentCell() == .Default) { + terrain.setCurrentCell(.NotDug); //std.debug.print("Marked {d},{d} as NotDug\n", .{ x, y }); + const x = task.x; + const y = task.y; if (x > 0) { tasks.add(.{ .x = x - 1, .y = y }); } @@ -194,43 +238,38 @@ fn solveForTerrain(terrain: *Terrain) usize { return result; } -fn dig(terrain: *Terrain, command: Command) void { - const target_x = switch (command.direction) { - .Right => terrain.*.x + command.length, - .Left => terrain.*.x - command.length, - .Up, .Down => terrain.*.x, - }; - - const target_y = switch (command.direction) { - .Down => terrain.*.y + command.length, - .Up => terrain.*.y - command.length, - .Left, .Right => terrain.*.y, +fn getTargetCoordinates(coordinates: TerrainCoordinates, command: Command) TerrainCoordinates { + return .{ + .x = switch (command.direction) { + .Right => coordinates.x + command.length, + .Left => coordinates.x - command.length, + .Up, .Down => coordinates.x, + }, + .y = switch (command.direction) { + .Down => coordinates.y + command.length, + .Up => coordinates.y - command.length, + .Left, .Right => coordinates.y, + }, }; +} - while (terrain.*.x != target_x) { - if (terrain.*.x < target_x) { - terrain.*.x += 1; - } else { - terrain.*.x -= 1; - } +fn dig(terrain: *Terrain, command: Command) void { + const target = getTargetCoordinates(terrain.*.coordinates, command); - terrain.*.cells[terrain.*.x][terrain.*.y] = .Dug; + while (!terrain.*.coordinates.isSameX(target)) { + terrain.*.coordinates.approachX(target); + terrain.*.setCurrentCell(.Dug); } - while (terrain.*.y != target_y) { - if (terrain.*.y < target_y) { - terrain.*.y += 1; - } else { - terrain.*.y -= 1; - } - - terrain.*.cells[terrain.*.x][terrain.*.y] = .Dug; + while (!terrain.*.coordinates.isSameY(target)) { + terrain.*.coordinates.approachY(target); + terrain.*.setCurrentCell(.Dug); } } fn parseCommand(command: []const u8) Command { var index: usize = 2; - const length = readNumber(u24, command, &index); + const length = readNumber(u16, command, &index); const direction: Direction = switch (command[0]) { 'R' => .Right, 'L' => .Left,