solve_day7 :: (test: bool) {
    content := read_entire_file(ifx test then "inputs/day7_test.txt" else "inputs/day7.txt");
    lines   := split(content, "\n");

    directories: Table(string, Directory); 

    part1: u64 = 0;
    part2: u64 = 0;

    current_dir: string = "/";
    root_dir := table_add(*directories, "/", .{
        name = "/",
        parent = "/",
    });

    for line: lines {

        if line[0] == {
            case #char "$";
                run_command(line, *current_dir, directories);
            case #char "d";
                dir_name := sprint("%0%0/", current_dir, slice(line, 4, line.count - 4));

                new_dir_ptr := table_add(*directories, dir_name, .{
                    name = dir_name,
                    parent = current_dir,
                });
                current_dir_ptr := table_find_pointer(*directories, current_dir);

                array_add(*current_dir_ptr.sub_dirs, new_dir_ptr.name);
            case;
                space_index := find_index_from_left(line, " ");
                current_dir_ptr := table_find_pointer(*directories, current_dir);
                file_ptr := array_add(*(current_dir_ptr.files));
                << file_ptr = .{
                    name = copy_string(slice(line, space_index, line.count - space_index)),
                    size = string_to_int(slice(line, 0, space_index), 10, u64),
                };


                current_dir_ptr.file_size_accum += file_ptr.size;
                //print("%, %\n", << file_ptr, current_dir.file_size_accum);
        }
    }

    dir_sizes: Table(string, u64);
    part2 = calc_dir_sizes("/", directories, *dir_sizes);

    needed_size := 30_000_000 - (70_000_000 - part2);
    

    for v,k: dir_sizes {

        if v < 100_000  part1 += v;

        if needed_size < v  part2 = min(part2, v);
    }

    print("Part 1: %\n", part1);
    print("Part 2: %\n", part2);
}

calc_dir_sizes :: (curr: string, dirs: Table, dir_sizes: *Table) -> u64 {
    accum: u64 = 0;

    curr_dir,_ := table_find(*dirs, curr);

    for sub_dir: curr_dir.sub_dirs {
        accum += calc_dir_sizes(sub_dir, dirs, dir_sizes);
    }

    accum += curr_dir.file_size_accum;

    table_add(dir_sizes, curr, accum);

    return accum;
}

print_dir :: (dir: *Directory) {
    print("%, size: %\n", dir.name, dir.sub_dirs.count);

    for dir.sub_dirs {
        //print_dir(it);

    }
}

run_command :: (command: string, current_dir: *string, directories: Table) {
    if slice(command, 2, 2) == {
        case "ls";
            return;
        case "cd";
            dir := slice(command, 5, command.count - 5);

            if dir == "/"  return;

            current_dir_ptr := table_find_pointer(*directories, << current_dir);


            if dir == ".." {
                << current_dir = current_dir_ptr.parent;
            } else {
                into := tprint("%0%0/", current_dir_ptr.name, dir);
                << current_dir = table_find_pointer(*directories, into).name;
            }

        case; assert(false, "Bad command: %", command);
    }
}

Directory :: struct {
    name: string;
    parent: string;
    file_size_accum: u64;
    sub_dirs: [..]string;
    files: [..]DFile;
}

DFile :: struct {
    name: string;
    size: u64;
}