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