const std = @import("std");

const Str = []const u8;

const PATH = "input/day05.txt";

pub fn first(allocator: std.mem.Allocator) !usize {
    _ = allocator;

    var lines = std.mem.tokenize(u8, @embedFile(PATH), "\n");

    var ret: usize = 0;

    while (lines.next()) |line| {
        if (checkLine(line)) ret += 1;
    }

    return ret;
}

pub fn second(allocator: std.mem.Allocator) !usize {
    _ = allocator;

    var lines = std.mem.tokenize(u8, @embedFile(PATH), "\n");

    var ret: usize = 0;

    while (lines.next()) |line| {
        if (checkLine2(line)) ret += 1;
    }

    return ret;
}

fn checkLine(line: Str) bool {
    var vowels: usize = 0;
    var double: bool = false;

    for (line) |ch, idx| {
        // vowels
        switch (ch) {
            'a', 'e', 'i', 'o', 'u' => vowels += 1,
            else => {},
        }

        // index underrun
        if (idx == 0) continue;

        // bad combinations
        switch (ch) {
            'b', 'd', 'q', 'y' => {
                if (ch - 1 == line[idx - 1]) return false;
            },
            else => {},
        }

        // doubles
        if (ch == line[idx - 1]) double = true;
    }

    return double and (vowels > 2);
}

fn checkLine2(line: Str) bool {
    var repeat: bool = false;
    var pair: bool = false;

    for (line) |ch, idx| {
        // pair
        if (idx == 0) continue;
        if (!pair) {
            const sub_line = if (idx + 2 < line.len) line[idx + 1 ..] else "";
            for (sub_line) |sch, sidx| {
                if (sidx == sub_line.len - 1) break;
                // std.debug.print("{c}{c} - {c}{c}\n", .{ line[idx - 1], ch, sch, sub_line[sidx + 1] });
                if (ch == sub_line[sidx + 1] and line[idx - 1] == sch) {
                    pair = true;
                    break;
                }
            }
        }

        // repeat check
        if (idx < 2) continue;
        if (ch == line[idx - 2]) repeat = true;

        if (repeat and pair) return true;
    }

    return false;
}

test "checkLine" {
    try std.testing.expectEqual(true, checkLine("ugknbfddgicrmopn"));
    try std.testing.expectEqual(true, checkLine("aaa"));
    try std.testing.expectEqual(false, checkLine("jchzalrnumimnmhp"));
    try std.testing.expectEqual(false, checkLine("haegwjzuvuyypxyu"));
    try std.testing.expectEqual(false, checkLine("dvszwmarrgswjxmb"));
}

test "checkLine - Part 2" {
    try std.testing.expectEqual(true, checkLine2("qjhvhtzxzqqjkmpb"));
    try std.testing.expectEqual(true, checkLine2("xxyxx"));
    try std.testing.expectEqual(false, checkLine2("uurcxstgmygtbstg"));
    try std.testing.expectEqual(false, checkLine2("ieodomkazucvgmuy"));
}

test "day05a" {
    try std.testing.expectEqual(@as(usize, 236), try first(std.testing.allocator));
}

test "day05b" {
    try std.testing.expectEqual(@as(usize, 51), try second(std.testing.allocator));
}