day 18, part 1 (improved in preparation to part 2)

main
Inga 🏳‍🌈 4 months ago
parent 322b8b7113
commit dba2aeadc8
  1. 119
      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,

Loading…
Cancel
Save