day 17, part 1 (replaced depth-first with breadth-first, implemented ring queue, switched from up/down/left/right to vertical/horizontal), wrong answer

main
Inga 🏳‍🌈 1 year ago
parent 120b14f067
commit 11788cc1ed
  1. 194
      day17-easy/src/main.zig

@ -44,67 +44,128 @@ fn StackList(comptime T: type, comptime capacity_type: type, comptime capacity:
}; };
} }
const Direction = enum(u2) { fn RingQueue(comptime T: type, comptime capacity_type: type, comptime capacity: capacity_type) type {
Up, return struct {
Down, const Self = @This();
Left, mem: [capacity]T,
Right, first: capacity_type,
next: capacity_type,
fn add(self: *Self, value: T) void {
std.debug.assert(self.next - self.first < capacity);
self.mem[self.next % capacity] = value;
self.next += 1;
}
fn take(self: *Self) T {
const result = self.mem[self.first % capacity];
self.first += 1;
return result;
}
fn isEmpty(self: *const Self) bool {
return self.next == self.first;
}
fn init() Self {
return Self{
.mem = undefined,
.first = 0,
.next = 0,
};
}
};
}
const Direction = enum(u8) {
Horizontal,
Vertical,
}; };
const ResultsByDirection = std.EnumArray(Direction, u32); const ResultsByDirection = std.EnumArray(Direction, u32);
const Results = [150][150]ResultsByDirection; const Results = [150][150]ResultsByDirection;
const NextCellCoordinates = StackList([2]usize, usize, 3); const Task = packed struct(u48) {
current_heat: u16,
x: u8,
y: u8,
entry_direction: Direction,
_: u8 = 0,
};
const NextTasks = StackList(Task, usize, 6);
fn getNextTasks(board: []const []const u8, task: Task) NextTasks {
var result = NextTasks.init();
const previous_direction: Direction = switch (task.entry_direction) {
.Vertical => .Horizontal,
.Horizontal => .Vertical,
};
fn fillResults(board: []const []const u8, results: *Results, x: usize, y: usize, entry_direction: Direction, depth: usize) void { {
//std.debug.print("Solving for {d},{d}, {any}, depth: {d}, total: {d}\n", .{ x, y, entry_direction, depth, results.*[x][y].get(entry_direction) }); var previous_cells_list = StackList([2]u8, usize, 3).init();
var previous_cells_list = StackList([2]usize, usize, 3).init(); switch (task.entry_direction) {
switch (entry_direction) { .Vertical => {
.Up => { inline for (1..4) |delta| {
for (1..4) |delta| { if (task.x + delta < board.len) {
if (x + delta < board.len) { previous_cells_list.add(.{ task.x + @as(u8, delta), task.y });
previous_cells_list.add(.{ x + delta, y }); }
} }
} },
}, .Horizontal => {
.Down => { inline for (1..4) |delta| {
for (1..4) |delta| { if (task.y + delta < board[task.x].len) {
if (x >= delta) { previous_cells_list.add(.{ task.x, task.y + @as(u8, delta) });
previous_cells_list.add(.{ x - delta, y }); }
} }
} },
}, }
.Left => { var current_heat = task.current_heat;
for (1..4) |delta| { for (previous_cells_list.getSlice()) |previous_cell| {
if (y + delta < board[x].len) { current_heat += board[previous_cell[0]][previous_cell[1]];
previous_cells_list.add(.{ x, y + delta }); result.add(.{
.current_heat = current_heat,
.x = previous_cell[0],
.y = previous_cell[1],
.entry_direction = previous_direction,
});
}
}
{
var previous_cells_list = StackList([2]u8, usize, 3).init();
switch (task.entry_direction) {
.Vertical => {
inline for (1..4) |delta| {
if (task.x >= delta) {
previous_cells_list.add(.{ task.x - @as(u8, delta), task.y });
}
} }
} },
}, .Horizontal => {
.Right => { inline for (1..4) |delta| {
for (1..4) |delta| { if (task.y >= delta) {
if (y >= delta) { previous_cells_list.add(.{ task.x, task.y - @as(u8, delta) });
previous_cells_list.add(.{ x, y - delta }); }
} }
} },
}, }
var current_heat = task.current_heat;
for (previous_cells_list.getSlice()) |previous_cell| {
current_heat += board[previous_cell[0]][previous_cell[1]];
result.add(.{
.current_heat = current_heat,
.x = previous_cell[0],
.y = previous_cell[1],
.entry_direction = previous_direction,
});
}
} }
const previous_directions: [2]Direction = switch (entry_direction) { //std.debug.print("Next tasks for {any}: {any}\n", .{ task, result.getSlice() });
.Up, .Down => .{ .Left, .Right },
.Left, .Right => .{ .Up, .Down },
};
var current_heat = results.*[x][y].get(entry_direction); return result;
for (previous_cells_list.getSlice()) |previous_cell| {
current_heat += board[previous_cell[0]][previous_cell[1]];
for (previous_directions) |direction| {
if (results.*[previous_cell[0]][previous_cell[1]].get(direction) > current_heat) {
results.*[previous_cell[0]][previous_cell[1]].set(direction, current_heat);
fillResults(board, results, previous_cell[0], previous_cell[1], direction, depth + 1);
}
}
}
} }
fn solveLines(lines: [][]u8) usize { fn solveLines(lines: [][]u8) usize {
@ -116,26 +177,47 @@ fn solveLines(lines: [][]u8) usize {
} }
} }
const x_max = lines.len - 1; const x_max = @as(u8, @intCast(lines.len - 1));
const y_max = lines[x_max].len - 1; const y_max = @as(u8, @intCast(lines[x_max].len - 1));
var results: Results = [_][150]ResultsByDirection{[_]ResultsByDirection{ResultsByDirection.initFill(total_max)} ** 150} ** 150; var results: Results = [_][150]ResultsByDirection{[_]ResultsByDirection{ResultsByDirection.initFill(total_max)} ** 150} ** 150;
results[x_max][y_max].set(.Down, lines[x_max][y_max]); var tasks = RingQueue(Task, usize, 1_024_576).init();
results[x_max][y_max].set(.Right, lines[x_max][y_max]); tasks.add(.{
.current_heat = lines[x_max][y_max],
.x = x_max,
.y = y_max,
.entry_direction = .Horizontal,
});
tasks.add(.{
.current_heat = lines[x_max][y_max],
.x = x_max,
.y = y_max,
.entry_direction = .Vertical,
});
fillResults(lines, &results, x_max, y_max, .Down, 0); var i: usize = 0;
fillResults(lines, &results, x_max, y_max, .Right, 0); while (!tasks.isEmpty()) : (i += 1) {
//std.debug.print("Handling task {d}\n", .{i});
var current_task = tasks.take();
if (results[current_task.x][current_task.y].get(current_task.entry_direction) > current_task.current_heat) {
results[current_task.x][current_task.y].set(current_task.entry_direction, current_task.current_heat);
for (getNextTasks(lines, current_task).getSlice()) |next_task| {
tasks.add(next_task);
}
}
}
if (false) { if (false) {
std.debug.print("Total tasks done: {d}\n", .{i});
for (0..lines.len) |x| { for (0..lines.len) |x| {
for (0..lines[x].len) |y| { for (0..lines[x].len) |y| {
std.debug.print("{d} ", .{@min(@min(results[x][y].get(.Up), results[x][y].get(.Down)), @min(results[x][y].get(.Left), results[x][y].get(.Right)))}); std.debug.print("{d}/{d} ", .{ results[x][y].get(.Horizontal), results[x][y].get(.Vertical) });
} }
std.debug.print("\n", .{}); std.debug.print("\n", .{});
} }
} }
return results[0][0].get(.Down) - lines[0][0]; return results[0][0].get(.Vertical) - lines[0][0];
} }
pub fn solveAll(reader: anytype) !usize { pub fn solveAll(reader: anytype) !usize {

Loading…
Cancel
Save