const std = @import("std"); const path = "data/day08/input.txt"; const RetType = u20; const DigitType = u7; const pattern_pieces = 10; const output_pieces = 4; const input_lines = 200; const InputLine = struct { // patterns patterns: [pattern_pieces]DigitType = [_]DigitType{0} ** pattern_pieces, // output outputs: [output_pieces]DigitType = [_]DigitType{0} ** output_pieces, // 2, 3, 5 five_len: [3]DigitType = [_]DigitType{0} ** 3, // 0, 6, 9 six_len: [3]DigitType = [_]DigitType{0} ** 3, }; const FullInput = [input_lines]InputLine; pub fn parseInput() anyerror!FullInput { const input = @embedFile(path); var lines = std.mem.tokenize(u8, input, "\n"); // This does not run the InputLine initialization var inl: FullInput = undefined; var i: usize = 0; while (lines.next()) |line| : (i += 1) { inl[i] = InputLine{}; var pattern_output = std.mem.tokenize(u8, line, "|"); var patts = std.mem.tokenize(u8, pattern_output.next().?, " "); var outs = std.mem.tokenize(u8, pattern_output.next().?, " "); // collect outs var idx: usize = 0; while (outs.next()) |out| : (idx += 1) { for (out) |ch| { inl[i].outputs[idx] |= @as(DigitType, 1) << @intCast(u3, ch - 'a'); } } // collect patterns var five: usize = 0; var six: usize = 0; while (patts.next()) |patt| { var curr: *u7 = undefined; switch (patt.len) { 2 => curr = &inl[i].patterns[1], 4 => curr = &inl[i].patterns[4], 3 => curr = &inl[i].patterns[7], 7 => { inl[i].patterns[8] = 0b1111111; continue; }, 5 => { curr = &inl[i].five_len[five]; five += 1; }, 6 => { curr = &inl[i].six_len[six]; six += 1; }, else => { unreachable; }, } for (patt) |ch| { curr.* |= @as(DigitType, 1) << @intCast(u3, ch - 'a'); } } } return inl; } pub fn second(allocator: ?std.mem.Allocator) anyerror!RetType { _ = allocator; var input = try parseInput(); var sum: RetType = 0; for (input) |*line| { // 1. deduct 3 from 1 for (line.five_len) |five| { if (five & line.patterns[1] == line.patterns[1]) { line.patterns[3] = five; break; } } // 2. deduct 9 from 4 for (line.six_len) |six| { if (six & line.patterns[4] == line.patterns[4]) { line.patterns[9] = six; break; } } // 3. from six_len (discard 9!) the matching with 1 is 0, the other is 6 for (line.six_len) |six| { if (six == line.patterns[9]) continue; if (six & line.patterns[1] == line.patterns[1]) { line.patterns[0] = six; } else { line.patterns[6] = six; } } // 4. from five_len (discard 3!) the matching with 9 is 5, the other is 2 for (line.five_len) |five| { if (five == line.patterns[3]) continue; if (five & line.patterns[9] == five) { line.patterns[5] = five; } else { line.patterns[2] = five; } } // decode output var ret: RetType = 0; for (line.outputs) |out, idx| { for (line.patterns) |patt, i| { if (out == patt) { ret += @intCast(RetType, i) * try std.math.powi(RetType, 10, @intCast(RetType, 3 - idx)); break; } } } sum += ret; } return sum; } pub fn main() anyerror!void { var timer = try std.time.Timer.start(); const ret = try second(null); const s = timer.lap() / 1000; try std.testing.expectEqual(ret, @as(RetType, 1023686)); std.debug.print("Day 8b result: {d} \t\ttime: {d}us\n", .{ ret, s }); } test "day08b" { try std.testing.expectEqual(@as(RetType, 1023686), try second(std.testing.allocator)); }