aboutsummaryrefslogtreecommitdiffstats
path: root/src/02/main.zig
blob: e965c95a4d60911c12b5a574510dc2cb0f913c5a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
const std = @import("std");
const aoc = @import("aoc");

const Entry = struct { a: u16, b: u16, char: u8, pass: []u8 };

fn freeEntries(allocator: std.mem.Allocator, entries: *const std.ArrayList(Entry)) void {
    for (entries.items) |item|
        allocator.free(item.pass);
    entries.deinit();
}

fn parse(allocator: std.mem.Allocator, input: []u8) !std.ArrayList(Entry) {
    var entries = std.ArrayList(Entry).init(allocator);
    errdefer freeEntries(allocator, &entries);

    var lineit = std.mem.tokenize(u8, input, "\n");
    while (lineit.next()) |line| {
        var entry: Entry = undefined;
        var it = std.mem.tokenize(u8, line, " -");
        entry.a = try std.fmt.parseInt(u16, it.next().?, 10);
        entry.b = try std.fmt.parseInt(u16, it.next().?, 10);
        entry.char = it.next().?[0];
        entry.pass = try allocator.dupe(u8, it.next().?);
        try entries.append(entry);
    }

    return entries;
}

fn part1(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 {
    _ = args;

    const entries = try parse(allocator, input);
    defer freeEntries(allocator, &entries);

    var valid: u32 = 0;
    for (entries.items) |entry| {
        var count: u16 = 0;
        for (entry.pass) |c| count += @boolToInt(c == entry.char);
        valid += @boolToInt(count >= entry.a and count <= entry.b);
    }

    return try std.fmt.allocPrint(allocator, "{d}", .{valid});
}

fn part2(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 {
    _ = args;

    const entries = try parse(allocator, input);
    defer freeEntries(allocator, &entries);

    var valid: u32 = 0;
    for (entries.items) |entry| {
        valid += @boolToInt((entry.pass[entry.a - 1] == entry.char) !=
            (entry.pass[entry.b - 1] == entry.char));
    }

    return try std.fmt.allocPrint(allocator, "{d}", .{valid});
}

pub const main = aoc.main(part1, part2, .{ "603", "404" });