const std = @import("std"); const mem = std.mem; const path = "data/day22/input.txt"; const Cuboid = struct { state: bool, xmin: isize, xmax: isize, ymin: isize, ymax: isize, zmin: isize, zmax: isize, }; const Cubes = []Cuboid; const CoordList = std.ArrayList(isize); pub fn main() !void { var timer = try std.time.Timer.start(); const ret = try second(); const t = timer.lap() / 1000; try std.testing.expectEqual(@as(usize, 1267133912086024), ret); std.debug.print("Day 22b result: {d}time: {d}us\n", .{ ret, t }); } pub fn second() !usize { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); var X = CoordList.init(allocator); defer X.deinit(); var Y = CoordList.init(allocator); defer Y.deinit(); var Z = CoordList.init(allocator); defer Z.deinit(); const input = try parseInput(allocator, &X, &Y, &Z); defer allocator.free(input); std.sort.sort(isize, X.items, {}, comptime std.sort.asc(isize)); std.sort.sort(isize, Y.items, {}, comptime std.sort.asc(isize)); std.sort.sort(isize, Z.items, {}, comptime std.sort.asc(isize)); const N: usize = X.items.len; // XXX: this one is _really_ sloooooow..., why? // const grid_size = 840; // var grid = [_][grid_size][grid_size]bool{[_][grid_size]bool{[_]bool{false} ** grid_size} ** grid_size} ** grid_size; var grid = try std.DynamicBitSet.initEmpty(allocator, N * N * N); defer grid.deinit(); for (input) |cube| { const x0 = mem.indexOfScalar(isize, X.items, cube.xmin).?; const x1 = mem.indexOfScalar(isize, X.items, cube.xmax).?; const y0 = mem.indexOfScalar(isize, Y.items, cube.ymin).?; const y1 = mem.indexOfScalar(isize, Y.items, cube.ymax).?; const z0 = mem.indexOfScalar(isize, Z.items, cube.zmin).?; const z1 = mem.indexOfScalar(isize, Z.items, cube.zmax).?; var x = x0; while (x < x1) : (x += 1) { var y = y0; while (y < y1) : (y += 1) { var z = z0; while (z < z1) : (z += 1) { grid.setValue(x * N * N + y * N + z, cube.state); } } } } var sum: isize = 0; var x: usize = 0; while (x < N - 1) : (x += 1) { var y: usize = 0; while (y < N - 1) : (y += 1) { var z: usize = 0; while (z < N - 1) : (z += 1) { if (grid.isSet(x * N * N + y * N + z)) { sum += (X.items[x + 1] - X.items[x]) * (Y.items[y + 1] - Y.items[y]) * (Z.items[z + 1] - Z.items[z]); } } } } return @intCast(usize, sum); } fn parseInput(a: mem.Allocator, X: *CoordList, Y: *CoordList, Z: *CoordList) !Cubes { const input = @embedFile(path); var lines = mem.split(u8, input, "\n"); var ret = std.ArrayList(Cuboid).init(a); while (lines.next()) |line| { if (line.len == 0) break; var cube: Cuboid = undefined; var st_coord = mem.tokenize(u8, line, " "); // set cuboid state if (mem.eql(u8, st_coord.next().?, "on")) cube.state = true else cube.state = false; var axes = mem.tokenize(u8, st_coord.next().?, ","); var cntr: u2 = 0; while (axes.next()) |ax| : (cntr += 1) { const axis = ax[2..]; // strip x=, y=, z= var min_max = mem.tokenize(u8, axis, ".."); // coordinates if (cntr == 0) { cube.xmin = try std.fmt.parseInt(isize, min_max.next().?, 10); cube.xmax = try std.fmt.parseInt(isize, min_max.next().?, 10); cube.xmax += 1; try X.append(cube.xmin); try X.append(cube.xmax); } if (cntr == 1) { cube.ymin = try std.fmt.parseInt(isize, min_max.next().?, 10); cube.ymax = try std.fmt.parseInt(isize, min_max.next().?, 10); cube.ymax += 1; try Y.append(cube.ymin); try Y.append(cube.ymax); } if (cntr == 2) { cube.zmin = try std.fmt.parseInt(isize, min_max.next().?, 10); cube.zmax = try std.fmt.parseInt(isize, min_max.next().?, 10); cube.zmax += 1; try Z.append(cube.zmin); try Z.append(cube.zmax); } } try ret.append(cube); } return ret.toOwnedSlice(); } test "day22b" { try std.testing.expectEqual(@as(usize, 1267133912086024), try second()); }