about summary refs log tree commit diff
path: root/day14.zig
blob: 42f6b891c2e54316c98a0f33e6b4bdda987732b4 (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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// needs -O ReleaseFast, else super slow

const std = @import("std");
const data = @embedFile("day14");

var area = [_][800]u8{ [_]u8{0} ** 800 } ** 800;

fn draw(ox: usize, oy: usize, x: usize, y: usize) void {
    if (ox == x) {
        var vy = std.math.min(oy, y);
        while (vy <= std.math.max(oy, y)) : (vy += 1)
            area[x][vy] = 9;
    } else {
        var vx = std.math.min(ox, x);
        while (vx <= std.math.max(ox, x)) : (vx += 1)
            area[vx][y] = 9;
    }
}

fn drop_sand(y1: usize, x1: usize) bool {
    var y = y1;
    var x = x1;

    while (x < 799 and y < 799) {
        if (area[y+1][x] == 0) {
            y += 1;
            continue;
        } 
        if (area[y+1][x-1] == 0) {
            x -= 1;
            y += 1;
            continue;
        }
        if (area[y+1][x+1] == 0) {
            x += 1;
            y += 1;
            continue;
        }
        area[y][x] = 1;
        return true;
    }
    
    return false;
}

pub fn main() !void {
    var lines = std.mem.tokenize(u8, data, "\n");

    while (lines.next()) |line| {
        if (line.len == 0)
            break;

        var coords = std.mem.tokenize(u8, line, " -> ");

        var ox: usize = 0;
        var oy: usize = 0;
        while (coords.next()) |coord| {
            var ns = std.mem.tokenize(u8, coord, ",");
            var y = try std.fmt.parseInt(usize, ns.next().?, 10);
            var x = try std.fmt.parseInt(usize, ns.next().?, 10);

            if (ox != 0)
                draw(ox, oy, x, y);

            ox = x;
            oy = y;
        }
    }


    var part1: usize = 0;
    while (drop_sand(0, 500))
        part1 += 1;

    for (area) |*line| {
        for (line) |*item| {
            if (item.* == 1)
                item.* = 0;
        }
    }

    var bottom: usize = 799;
    loop: while (bottom > 0) : (bottom -= 1) {
        for (area[bottom]) |item| {
            if (item == 9) {
                draw(bottom + 2, 0, bottom + 2, 799);
                break :loop;
            }
        }
    }
    
    var part2: usize = 0;
    loop: while (drop_sand(0, 500)) {
        part2 += 1;

        if (area[0][500] != 0)
            break :loop;
    }

//    for (area) |line| {
//        for (line) |item| {
//            std.debug.print("{}", .{item});
//        }
//        std.debug.print("\n", .{});
//    }

    std.debug.print("{}\n{}\n", .{part1, part2});
}