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) {
Up,
Down,
Left,
Right,
fn RingQueue(comptime T: type, comptime capacity_type: type, comptime capacity: capacity_type) type {
return struct {
const Self = @This();
mem: [capacity]T,
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 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]usize, usize, 3).init();
switch (entry_direction) {
.Up => {
for (1..4) |delta| {
if (x + delta < board.len) {
previous_cells_list.add(.{ x + delta, y });
{
var previous_cells_list = StackList([2]u8, usize, 3).init();
switch (task.entry_direction) {
.Vertical => {
inline for (1..4) |delta| {
if (task.x + delta < board.len) {
previous_cells_list.add(.{ task.x + @as(u8, delta), task.y });
}
}
}
},
.Down => {
for (1..4) |delta| {
if (x >= delta) {
previous_cells_list.add(.{ x - delta, y });
},
.Horizontal => {
inline for (1..4) |delta| {
if (task.y + delta < board[task.x].len) {
previous_cells_list.add(.{ task.x, task.y + @as(u8, delta) });
}
}
}
},
.Left => {
for (1..4) |delta| {
if (y + delta < board[x].len) {
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,
});
}
}
{
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 });
}
}
}
},
.Right => {
for (1..4) |delta| {
if (y >= delta) {
previous_cells_list.add(.{ x, y - delta });
},
.Horizontal => {
inline for (1..4) |delta| {
if (task.y >= delta) {
previous_cells_list.add(.{ task.x, task.y - @as(u8, 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) {
.Up, .Down => .{ .Left, .Right },
.Left, .Right => .{ .Up, .Down },
};
//std.debug.print("Next tasks for {any}: {any}\n", .{ task, result.getSlice() });
var current_heat = results.*[x][y].get(entry_direction);
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);
}
}
}
return result;
}
fn solveLines(lines: [][]u8) usize {
@ -116,26 +177,47 @@ fn solveLines(lines: [][]u8) usize {
}
}
const x_max = lines.len - 1;
const y_max = lines[x_max].len - 1;
const x_max = @as(u8, @intCast(lines.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;
results[x_max][y_max].set(.Down, lines[x_max][y_max]);
results[x_max][y_max].set(.Right, lines[x_max][y_max]);
var tasks = RingQueue(Task, usize, 1_024_576).init();
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);
fillResults(lines, &results, x_max, y_max, .Right, 0);
var i: usize = 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) {
std.debug.print("Total tasks done: {d}\n", .{i});
for (0..lines.len) |x| {
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", .{});
}
}
return results[0][0].get(.Down) - lines[0][0];
return results[0][0].get(.Vertical) - lines[0][0];
}
pub fn solveAll(reader: anytype) !usize {

Loading…
Cancel
Save