aoc/2020/6/src/main.zig

119 lines
3.8 KiB
Zig

const std = @import("std");
pub fn main() anyerror!void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
var gpa = &arena.allocator;
var records = try read_records("input", gpa);
// part 1
var yes_per_group = std.ArrayList(u32).init(gpa);
var yeses : u32 = 0;
for (records.items) |r| {
var map = std.hash_map.AutoHashMap(u8, bool).init(gpa);
defer map.deinit();
try map.ensureCapacity(26);
for (r) |c| {
if (std.ascii.isAlpha(c)) {
map.putAssumeCapacity(c, true);
}
}
var count = map.count();
std.log.debug("{} yeses in group '{}'", .{count, r});
try yes_per_group.append(count);
yeses += count;
}
std.log.info("{} yeses across {} groups", .{yeses, yes_per_group.items.len});
// part 2
const one :u26 = comptime 1;
var and_yeses : u32 = 0;
for (records.items) |r| {
var it = std.mem.tokenize(r, " ");
var state : u26 = std.math.maxInt(u26);
while (it.next()) |answer| {
var person_yeses : u26 = 0;
for (answer) |c| {
if (std.ascii.isAlpha(c)) {
person_yeses |= (one << @intCast(u5, (c-97)));
}
}
//std.log.debug("{x} <-- {}", .{person_yeses, answer});
state &= person_yeses;
}
//std.log.debug("{x}", .{state});
var count = count_one_bits(state);
//std.log.debug("{} and-yeses in group '{}'", .{count, r});
and_yeses += count;
}
std.log.info("{} and-yeses across {} groups", .{and_yeses, yes_per_group.items.len});
}
fn count_one_bits(a: u26) u32 {
var i : u5 = 0;
var one : u26 = 1;
var count : u32 = 0;
while (i < 26) : (i += 1) {
var b : u26 = one << i;
if ((a & b) == b) {
count +=1;
}
}
return count;
}
fn read_records(filename: []const u8, allocator: *std.mem.Allocator) !std.ArrayList([]u8) {
var file = try std.fs.cwd().openFile(filename, .{});
var reader = file.reader();
var records = std.ArrayList([]u8).init(allocator);
var record = std.ArrayList(u8).init(allocator);
var n_newlines : u32 = 0;
var just_had_newline = false;
const state = enum {
AddingData,
CheckingNewline,
RecordEnd,
};
var current_state = state.AddingData;
while(true) {
var n = reader.readByte() catch |err| {
// Finalize record
try records.append(try allocator.dupe(u8, record.items[0..record.items.len]));
//std.log.debug("Found record: '{}'", .{record.items});
record.deinit();
record = std.ArrayList(u8).init(allocator);
std.mem.set(u8, record.items, 0);
break;
};
if (n == '\n') {
if (current_state == state.CheckingNewline) {
current_state = state.RecordEnd;
// Finalize record
try records.append(try allocator.dupe(u8, record.items[0..record.items.len]));
//std.log.debug("Found record: '{}'", .{record.items});
record.deinit();
record = std.ArrayList(u8).init(allocator);
std.mem.set(u8, record.items, 0);
current_state = state.AddingData;
continue;
}
else {
current_state = state.CheckingNewline;
// whitespace can always be added
try record.append(' ');
continue;
}
}
else {
if (current_state == state.CheckingNewline) {
current_state = state.AddingData;
}
try record.append(n);
}
}
std.log.debug("Found {} records", .{records.items.len});
return records;
}