const std = @import("std");
const path = "data/day04/input.txt";
const retSize = u16;
const grid_size = 5;
const grid_item_size = u7;
const Board = struct {
items: [grid_size][grid_size]grid_item_size,
row: [grid_size]u5 = [_]u5{0} ** grid_size,
col: [grid_size]u5 = [_]u5{0} ** grid_size,
pub fn value(self: @This()) retSize {
var ret: retSize = 0;
for (self.items) |row, rowID| {
for (row) |item, col| {
if (self.row[rowID] & (@as(u5, 1) <<| col) == 0) {
ret += item;
}
}
}
return ret;
}
};
const Bingo = struct {
numbers: std.ArrayList(grid_item_size),
boards: std.ArrayList(Board),
};
fn parseInput(allocator: std.mem.Allocator) anyerror!Bingo {
const input = @embedFile(path);
var lines = std.mem.split(u8, input, "\n");
var ret = Bingo{
.numbers = std.ArrayList(grid_item_size).init(allocator),
.boards = std.ArrayList(Board).init(allocator),
};
var gridRow: u3 = 0;
var gridCol: u3 = 0;
var g = Board{ .items = undefined };
var idx: usize = 0;
while (lines.next()) |line| : (idx += 1) {
// read in numbers
if (idx == 0) {
var nums = std.mem.tokenize(u8, line, ",");
while (nums.next()) |num| {
try ret.numbers.append(try std.fmt.parseUnsigned(grid_item_size, num, 10));
}
continue;
}
// read in Grids
var items = std.mem.tokenize(u8, line, " ");
while (items.next()) |item| {
const value = try std.fmt.parseUnsigned(grid_item_size, item, 10);
g.items[gridRow][gridCol] = value;
gridCol += 1;
}
gridCol = 0;
if (line.len != 0) gridRow += 1;
// append grid
if (gridRow == 5) {
try ret.boards.append(g);
gridRow = 0;
gridCol = 0;
// create new grid
g = Board{ .items = undefined };
}
}
return ret;
}
pub fn first(allocator: ?std.mem.Allocator) anyerror!retSize {
var bg = try parseInput(allocator.?);
defer { // cleanup code
bg.boards.deinit();
bg.numbers.deinit();
}
for (bg.numbers.items) |num| {
boards_loop: for (bg.boards.items) |_, idx| {
var grid = &bg.boards.items[idx];
for (grid.items) |row, i| {
for (row) |item, j| {
if (item == num) {
// increase row, col counter
grid.row[i] += @as(u5, 1) <<| j;
grid.col[j] += @as(u5, 1) <<| i;
// check if row or grid equals to 11111, return when true
if ((grid.row[i] == 0b11111) or (grid.col[j] == 0b11111)) {
return num * grid.value();
}
// break out to grid loop
continue :boards_loop;
}
}
}
}
}
unreachable;
}
pub fn main() anyerror!void {
var buf: [500 * grid_size * grid_size]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
var timer = try std.time.Timer.start();
const ret = try first(fba.allocator());
const f = timer.lap() / 1000;
try std.testing.expectEqual(ret, @as(retSize, 11536));
std.debug.print("Day 4a result: {d} \t\ttime: {d}us\n", .{ ret, f });
}
test "day04a" {
try std.testing.expectEqual(@as(retSize, 11536), try first(std.testing.allocator));
}