This commit is contained in:
parent
84344d12e5
commit
3d36485a52
145
src/day03.zig
Normal file
145
src/day03.zig
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const util = @import("util.zig");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
const input = @embedFile("data/day03.txt");
|
||||||
|
const sln = try solve(util.gpa, input);
|
||||||
|
std.debug.print("{d}\n", .{sln.sum});
|
||||||
|
std.debug.print("{d}\n", .{sln.gears});
|
||||||
|
}
|
||||||
|
|
||||||
|
const Part = struct {
|
||||||
|
value: usize,
|
||||||
|
line: usize,
|
||||||
|
start: usize,
|
||||||
|
end: usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Symbol = struct { char: u8, line: usize, offset: usize };
|
||||||
|
|
||||||
|
const Solution = struct {
|
||||||
|
sum: usize,
|
||||||
|
gears: usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn absDiff(comptime T: type, a: T, b: T) T {
|
||||||
|
return @max(a, b) - @min(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve(alloc: std.mem.Allocator, input: []const u8) !Solution {
|
||||||
|
var parts = std.ArrayList(Part).init(alloc);
|
||||||
|
var symbols = std.ArrayList(Symbol).init(alloc);
|
||||||
|
|
||||||
|
defer parts.deinit();
|
||||||
|
defer symbols.deinit();
|
||||||
|
|
||||||
|
// Accumulate parts and symbols.
|
||||||
|
var it = std.mem.splitScalar(u8, input, '\n');
|
||||||
|
var lnum: usize = 0;
|
||||||
|
while (it.next()) |line| : (lnum += 1) {
|
||||||
|
var current: Part = undefined;
|
||||||
|
var in_part = false;
|
||||||
|
|
||||||
|
var offset: usize = 0;
|
||||||
|
for (line) |char| {
|
||||||
|
switch (char) {
|
||||||
|
'0'...'9' => {
|
||||||
|
if (!in_part) {
|
||||||
|
current.line = lnum;
|
||||||
|
current.start = offset;
|
||||||
|
current.value = 0;
|
||||||
|
in_part = true;
|
||||||
|
}
|
||||||
|
current.value = current.value * 10 + (char - '0');
|
||||||
|
},
|
||||||
|
'.' => {
|
||||||
|
if (in_part) {
|
||||||
|
current.end = offset - 1;
|
||||||
|
try parts.append(current);
|
||||||
|
}
|
||||||
|
in_part = false;
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
if (in_part) {
|
||||||
|
current.end = offset - 1;
|
||||||
|
try parts.append(current);
|
||||||
|
}
|
||||||
|
in_part = false;
|
||||||
|
try symbols.append(.{ .char = char, .line = lnum, .offset = offset });
|
||||||
|
},
|
||||||
|
}
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle number at the end of a line.
|
||||||
|
if (in_part) {
|
||||||
|
current.end = offset - 1;
|
||||||
|
try parts.append(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate actual parts.
|
||||||
|
var sum: usize = 0;
|
||||||
|
var gear_sum: usize = 0;
|
||||||
|
var gears = std.AutoHashMap(Symbol, Part).init(alloc);
|
||||||
|
defer gears.deinit();
|
||||||
|
|
||||||
|
ploop: for (parts.items) |part| {
|
||||||
|
// std.debug.print("part {d}x{d}..{d}\n", .{ part.line, part.start, part.end });
|
||||||
|
for (symbols.items) |symbol| {
|
||||||
|
// std.debug.print("symbol {d}x{d}\n", .{ symbol.line, symbol.offset });
|
||||||
|
const inOffset = part.start <= symbol.offset + 1 and part.end + 1 >= symbol.offset;
|
||||||
|
const inLine = absDiff(usize, part.line, symbol.line) <= 1;
|
||||||
|
if (inOffset and inLine) {
|
||||||
|
// std.debug.print("part {d}x({d}..{d})={d}\n", .{ part.line, part.start, part.end, part.value });
|
||||||
|
sum += part.value;
|
||||||
|
|
||||||
|
// Detect gears.
|
||||||
|
if (symbol.char == '*') {
|
||||||
|
if (gears.get(symbol)) |other_gear| {
|
||||||
|
gear_sum += part.value * other_gear.value;
|
||||||
|
_ = gears.remove(symbol);
|
||||||
|
} else {
|
||||||
|
try gears.put(symbol, part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue :ploop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{ .sum = sum, .gears = gear_sum };
|
||||||
|
}
|
||||||
|
|
||||||
|
test "silver" {
|
||||||
|
const input =
|
||||||
|
\\467..114..
|
||||||
|
\\...*......
|
||||||
|
\\..35..633.
|
||||||
|
\\......#...
|
||||||
|
\\617*......
|
||||||
|
\\.....+.58.
|
||||||
|
\\..592.....
|
||||||
|
\\......755.
|
||||||
|
\\...$.*....
|
||||||
|
\\664..598..
|
||||||
|
;
|
||||||
|
try std.testing.expectEqual(@as(usize, 4361), (try solve(std.testing.allocator, input)).sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "gold" {
|
||||||
|
const input =
|
||||||
|
\\467..114..
|
||||||
|
\\...*......
|
||||||
|
\\..35..633.
|
||||||
|
\\......#...
|
||||||
|
\\617*......
|
||||||
|
\\.....+.58.
|
||||||
|
\\..592.....
|
||||||
|
\\......755.
|
||||||
|
\\...$.*....
|
||||||
|
\\.664.598..
|
||||||
|
;
|
||||||
|
try std.testing.expectEqual(@as(usize, 467835), (try solve(std.testing.allocator, input)).gears);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user