aoc-2020-zig

Advent of Code 2020 Solutions in Zig
git clone https://git.sinitax.com/sinitax/aoc-2020-zig
Log | Files | Refs | README | sfeed.txt

main.zig (3350B)


      1const std = @import("std");
      2const aoc = @import("aoc");
      3
      4fn intChecker(
      5    comptime min: u32,
      6    comptime max: u32,
      7    comptime len: ?u32,
      8    comptime suffix: ?[]const u8,
      9) fn ([]const u8) bool {
     10    const impl = struct {
     11        fn check(input: []const u8) bool {
     12            var parsed = input;
     13            if (suffix) |suf| {
     14                if (!std.mem.eql(u8, suf, input[(input.len - suf.len)..]))
     15                    return false;
     16                parsed = input[0..(input.len - suf.len)];
     17            }
     18            if (len != null and parsed.len != len.?)
     19                return false;
     20            const val = std.fmt.parseInt(u32, parsed, 10) catch {
     21                return false;
     22            };
     23            return (val >= min and val <= max);
     24        }
     25    };
     26    return impl.check;
     27}
     28
     29fn combineOr(
     30    comptime f1: fn ([]const u8) bool,
     31    comptime f2: fn ([]const u8) bool,
     32) fn ([]const u8) bool {
     33    const impl = struct {
     34        fn check(input: []const u8) bool {
     35            return f1(input) or f2(input);
     36        }
     37    };
     38    return impl.check;
     39}
     40
     41fn isColorStr(input: []const u8) bool {
     42    if (input.len != 7) return false;
     43    _ = std.fmt.parseInt(u32, input[1..], 16) catch {
     44        return false;
     45    };
     46    return input[0] == '#';
     47}
     48
     49fn isEyeColor(input: []const u8) bool {
     50    const valids = "amb blu brn gry grn hzl oth";
     51    return std.mem.indexOf(u8, valids[0..], input) != null;
     52}
     53
     54fn countValids(input: []u8, validate: bool) !u16 {
     55    var entryit = std.mem.split(u8, input, "\n\n");
     56    const required_keys = [_][]const u8{ "byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid", "cid" };
     57    const validation_funcs = [required_keys.len]?*const fn ([]const u8) bool{
     58        intChecker(1920, 2002, 4, null),
     59        intChecker(2010, 2020, 4, null),
     60        intChecker(2020, 2030, 4, null),
     61        combineOr(intChecker(150, 193, 3, "cm"), intChecker(59, 76, 2, "in")),
     62        isColorStr,
     63        isEyeColor,
     64        intChecker(0, 999999999, 9, null),
     65        null,
     66    };
     67    var count: u16 = 0;
     68    entryloop: while (entryit.next()) |entry| {
     69        const key_mask = [required_keys.len]u8{ 1, 1, 1, 1, 1, 1, 1, 'X' };
     70        var present = [required_keys.len]u1{ 0, 0, 0, 0, 0, 0, 0, 0 };
     71        var partit = std.mem.tokenize(u8, entry, ": \n");
     72        while (partit.next()) |key| {
     73            const value = partit.next().?;
     74            for (required_keys) |ckey, i| {
     75                if (std.mem.eql(u8, key, ckey)) {
     76                    if (validate and validation_funcs[i] != null) {
     77                        if (!validation_funcs[i].?(value)) continue :entryloop;
     78                    }
     79                    present[i] = 1;
     80                }
     81            }
     82        }
     83        for (key_mask) |k, i| {
     84            if (k != 'X' and present[i] != k)
     85                continue :entryloop;
     86        }
     87        count += 1;
     88    }
     89    return count;
     90}
     91
     92fn part1(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 {
     93    _ = args;
     94
     95    const answer = try countValids(input, false);
     96
     97    return try std.fmt.allocPrint(allocator, "{d}", .{answer});
     98}
     99
    100fn part2(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 {
    101    _ = args;
    102
    103    const answer = try countValids(input, true);
    104
    105    return try std.fmt.allocPrint(allocator, "{d}", .{answer});
    106}
    107
    108pub const main = aoc.main(part1, part2, .{ "226", "160" });