aoc-2020-zig

Advent of Code 2020 Solutions in Zig
git clone https://git.sinitax.com/sinitax/aoc-2020-zig
Log | Files | Refs | README | sfeed.txt

main.zig (3728B)


      1const std = @import("std");
      2const aoc = @import("aoc");
      3
      4fn getBit(v: u36, i: u6) bool {
      5    return ((v >> i) & 1) > 0;
      6}
      7
      8fn clearBit(v: u36, i: u6) u36 {
      9    return v & ~(@as(u36, 1) << i);
     10}
     11
     12fn setBit(v: u36, i: u6) u36 {
     13    return v | (@as(u36, 1) << i);
     14}
     15
     16fn getValStr(line: []const u8) ![]const u8 {
     17    const sep = std.mem.indexOf(u8, line, " = ");
     18    if (sep == null) return aoc.Error.InvalidInput;
     19    return line[sep.? + 3 ..];
     20}
     21
     22fn getAddrStr(line: []const u8) ![]const u8 {
     23    const sep = std.mem.indexOfScalar(u8, line, ']');
     24    if (sep == null) return aoc.Error.InvalidInput;
     25    return line[4..sep.?];
     26}
     27
     28fn part1(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 {
     29    _ = args;
     30
     31    var answer: u64 = 0;
     32
     33    var memmap = std.AutoHashMap(u36, u64).init(allocator);
     34    defer memmap.deinit();
     35
     36    var ormask: u36 = 0;
     37    var andmask: u36 = ~@as(u36, 0);
     38
     39    var lineit = std.mem.tokenize(u8, input, "\n");
     40    while (lineit.next()) |line| {
     41        if (std.mem.eql(u8, line[0..4], "mask")) {
     42            andmask = ~@as(u36, 0);
     43            ormask = 0;
     44            for (try getValStr(line)) |c, i| {
     45                if (c == '0') {
     46                    andmask = clearBit(andmask, @intCast(u6, 35 - i));
     47                } else if (c == '1') {
     48                    ormask = setBit(ormask, @intCast(u6, 35 - i));
     49                }
     50            }
     51        } else {
     52            const val = try std.fmt.parseInt(u36, try getValStr(line), 10);
     53            const addr = try std.fmt.parseInt(u36, try getAddrStr(line), 10);
     54            try memmap.put(addr, (val & andmask) | ormask);
     55        }
     56    }
     57
     58    var mapit = memmap.iterator();
     59    while (mapit.next()) |kv| {
     60        answer += kv.value_ptr.*;
     61    }
     62
     63    return try std.fmt.allocPrint(allocator, "{}", .{answer});
     64}
     65
     66fn bitRecurse(map: *std.AutoHashMap(u36, u64), addr: *u36, val: u64, mask: u36, index: u6) anyerror!void {
     67    if (index == 36) {
     68        aoc.debugfmt("SET: {b} {}\n", .{ addr.*, val });
     69        try map.put(addr.*, val);
     70    } else {
     71        if (getBit(mask, index)) {
     72            addr.* = setBit(addr.*, index);
     73            try bitRecurse(map, addr, val, mask, index + 1);
     74            addr.* = clearBit(addr.*, index);
     75            try bitRecurse(map, addr, val, mask, index + 1);
     76        } else {
     77            try bitRecurse(map, addr, val, mask, index + 1);
     78        }
     79    }
     80}
     81
     82fn part2(allocator: std.mem.Allocator, input: []u8, args: [][]u8) !?[]u8 {
     83    _ = args;
     84
     85    var answer: u64 = 0;
     86
     87    var memmap = std.AutoHashMap(u36, u64).init(allocator);
     88    defer memmap.deinit();
     89
     90    var ormask: u36 = 0;
     91    var flipmask: u36 = 0;
     92
     93    var lineit = std.mem.tokenize(u8, input, "\n");
     94    while (lineit.next()) |line| {
     95        if (std.mem.eql(u8, line[0..4], "mask")) {
     96            ormask = 0;
     97            flipmask = 0;
     98            for (try getValStr(line)) |c, i| {
     99                if (c == '1') {
    100                    ormask = setBit(ormask, @intCast(u6, 35 - i));
    101                } else if (c == 'X') {
    102                    flipmask = setBit(flipmask, @intCast(u6, 35 - i));
    103                }
    104            }
    105        } else {
    106            var addr = try std.fmt.parseInt(u36, try getAddrStr(line), 10);
    107            const val = try std.fmt.parseInt(u36, try getValStr(line), 10);
    108            addr = addr | ormask;
    109            aoc.debugfmt("{b} {b} {} {}\n", .{ flipmask, ormask, addr, val });
    110            try bitRecurse(&memmap, &addr, val, flipmask, 0);
    111        }
    112    }
    113
    114    var mapit = memmap.iterator();
    115    while (mapit.next()) |kv| {
    116        answer += kv.value_ptr.*;
    117    }
    118
    119    return try std.fmt.allocPrint(allocator, "{}", .{answer});
    120}
    121
    122pub const main = aoc.main(part1, part2, .{ "4886706177792", "3348493585827" });