solve_day9 :: (test: bool) {
    contents := read_entire_file(ifx test then "inputs/day9_test.txt" else "inputs/day9.txt");
    lines    := split(contents, "\n");

    tails: [10]Coord;

    visited: Table(s64, Coord);
    visited_2: Table(s64, Coord);

    for line: lines {
        dir := convert_dir(line[0]);
        amount := string_to_int(slice(line, 2, line.count - 2), 10, s64);

        for 0..amount - 1 {
            tails[0].x += dir.x;
            tails[0].y += dir.y;

            for 1..tails.count - 1 {
                tails[it] = move_tail(tails[it - 1], tails[it]);
            }

            table_set(*visited, convert_to_s64(tails[1]), tails[1]);
            table_set(*visited_2, convert_to_s64(tails[tails.count - 1]), tails[tails.count - 1]);
        }

    }

    print("Part 1: %\n", visited.count);
    print("Part 2: %\n", visited_2.count);
}

move_tail :: (head: Coord, tail: Coord) -> Coord {
    if abs(head.x - tail.x) <= 1 && abs(head.y - tail.y) <= 1  return tail;

    x := head.x - tail.x;
    y := head.y - tail.y;

    if x == 0 || abs(x) < abs(y) {
        return .{
            x = head.x,
            y = ifx y > 0 then head.y - 1 else head.y + 1,
        };
    }

    if y == 0 || abs(x) > abs(y) {
        return .{
            y = head.y,
            x = ifx x > 0 then head.x - 1 else head.x + 1,
        };
    }

    return .{
        x = ifx x > 0 then head.x - 1 else head.x + 1,
        y = ifx y > 0 then head.y - 1 else head.y + 1,
    };
}

convert_dir :: (dir: u8) -> Coord {
    if dir == {
        case #char "U";
            return .{ x = 0, y = -1 };
        case #char "R";
            return .{ x = 1, y = 0 };
        case #char "D";
            return .{ x = 0, y = 1 };
        case #char "L";
            return .{ x = -1, y = 0 };
        case; assert(false, "Bad dir '%'", dir);
    } 
    return .{};
}

convert_to_s64 :: (c: Coord) -> s64 {
    result := (cast,no_check(u64)c.x) << 32 | cast(u64)(cast,no_check(u32)c.y);
    return cast,no_check(s64)result;
}

#scope_file
Coord :: struct {
    x: s32;
    y: s32;
}