aboutsummaryrefslogtreecommitdiffstats
path: root/day15/solution.zig
blob: eb6dcbe8f005dd4eada14e66d7ce60f88794d4d4 (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
const std = @import("std");
const print = std.debug.print;
const assert = std.debug.assert;
const ArrayList = std.ArrayList;
const HashMap = std.HashMap;
const mem = std.mem;

const fin = mem.trim(u8, @embedFile("./input.txt"), &std.ascii.whitespace);
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();

fn hash(s: []const u8) u64 {
    var h: u64 = 0;
    for (s) |c| {
        h += c;
        h *= 17;
        h %= 256;
    }

    return @bitCast(h);
}

fn part1(strings: []const []const u8) void {
    var ans: u64 = 0;

    for (strings) |s| {
        ans += hash(s);
    }

    print("{d}\n", .{ans});
}

const Pair = struct {
    label: []const u8,
    value: u64,
};

fn part2(strings: []const []const u8) !void {
    var map: [256]ArrayList(Pair) = undefined;

    for (&map) |*e| {
        e.* = ArrayList(Pair).init(allocator);
    }

    for (strings) |s| {
        const action = s[mem.indexOfAny(u8, s, "-=").?];
        var toks = mem.tokenizeAny(u8, s, "-=");
        const label = toks.next().?;
        const value = toks.next();

        if (action == '=') {
            const v = try std.fmt.parseInt(u64, value.?, 10);
            const m = &map[hash(label)];
            for (m.items) |*i| {
                if (mem.eql(u8, i.label, label)) {
                    i.value = v;
                    break;
                }
            } else {
                try map[hash(label)].append(Pair{
                    .value = v,
                    .label = label,
                });
            }
        } else {
            var m = &map[hash(label)];
            for (m.items, 0..) |e, i| {
                if (mem.eql(u8, e.label, label)) {
                    _ = m.orderedRemove(i);
                    break;
                }
            }
        }
    }

    var ans: u64 = 0;
    for (map, 1..) |m, i| {
        for (m.items, 1..) |e, j| {
            ans += i * j * e.value;
        }
    }

    print("{d}\n", .{ans});
}

pub fn solve(strings: []const []const u8) !void {
    part1(strings);
    try part2(strings);
}

pub fn main() !void {
    var splitComma = mem.splitScalar(u8, fin, ',');
    var strings = ArrayList([]const u8).init(allocator);

    while (splitComma.next()) |s| {
        try strings.append(s);
    }

    try solve(strings.items);
}