const std = @import("std");
const PATH = "../input/day17.txt";
const Str = []const u8;
const Coord = @Vector(3, isize);
// Buggy with i2, see: https://github.com/ziglang/zig/issues/11611
const Dir = @Vector(3, isize);
const Grid = struct {
rows: isize,
cols: isize,
cubes: std.AutoHashMap(Coord, void),
const directions: [9 * 3 - 1]Dir = blk: {
var ret: [9 * 3 - 1]Dir = undefined;
var idx: usize = 0;
for ([_]isize{ -1, 0, 1 }) |x| {
for ([_]isize{ -1, 0, 1 }) |y| {
for ([_]isize{ -1, 0, 1 }) |z| {
if (x == 0 and y == 0 and z == 0) continue;
ret[idx] = Dir{ x, y, z };
idx += 1;
}
}
}
break :blk ret;
};
fn countNeighbor(self: @This(), pos: Coord) u5 {
var sum: u5 = 0;
for (directions) |d| {
const diffpos = pos + d;
if (diffpos[0] < 0 or diffpos[1] < 0 or diffpos[2] < 0) continue;
if (self.cubes.contains(diffpos)) sum += 1;
}
std.debug.assert(sum < 9 * 3);
return sum;
}
};
pub fn first(allocator: ?std.mem.Allocator) anyerror!usize {
var grid = try parseInput(allocator.?, @embedFile(PATH));
// var grid = try parseInput(allocator.?, test_input);
defer grid.cubes.deinit();
var cycle: usize = 1;
while (cycle <= 6) : (cycle += 1) {
var next_grid = Grid{
.rows = grid.rows + 2,
.cols = grid.cols + 2,
.cubes = std.AutoHashMap(Coord, void).init(allocator.?),
};
var row: isize = 0;
while (row < grid.rows + 2) : (row += 1) {
var col: isize = 0;
while (col < grid.cols + 2) : (col += 1) {
var depth: isize = 0;
while (depth <= cycle * 2) : (depth += 1) {
const nbr = grid.countNeighbor(.{ row - 1, col - 1, depth - 1 });
// if active
if (grid.cubes.contains(.{ row - 1, col - 1, depth - 1 })) {
if (nbr == 2 or nbr == 3) try next_grid.cubes.put(.{ row, col, depth }, {});
} else {
if (nbr == 3) try next_grid.cubes.put(.{ row, col, depth }, {});
}
}
}
}
grid.cubes.deinit();
grid = next_grid;
}
return grid.cubes.count();
}
pub fn second(allocator: ?std.mem.Allocator) anyerror!usize {
_ = allocator;
return 0;
}
fn parseInput(allocator: std.mem.Allocator, input: Str) !Grid {
var lines = std.mem.tokenize(u8, input, "\n");
var grid = Grid{
.rows = 0,
.cols = 0,
.cubes = std.AutoHashMap(Coord, void).init(allocator),
};
var row: isize = 0;
while (lines.next()) |line| : (row += 1) {
grid.cols = @intCast(isize, line.len);
for (line) |ch, col| {
if (ch == '#') try grid.cubes.put(.{ row, @intCast(isize, col), 0 }, {});
}
}
grid.rows = row;
return grid;
}
test "day17a" {
try std.testing.expectEqual(@as(usize, 223), try first(std.testing.allocator));
}
test "day17b" {
try std.testing.expectEqual(@as(usize, 0), try second(std.testing.allocator));
}
const test_input =
\\.#.
\\..#
\\###
;