aoc-zig-2025/day3.zig

103 lines
2.8 KiB
Zig

const std = @import("std");
const Io = std.Io;
const shared = @import("shared.zig");
const print = shared.print;
// limited single loop for part 1
pub fn findLargest(line: []const u8, charsLeft: usize) usize {
var largest: u8 = 0;
var index: usize = 0;
for (line, 0..) |v, i| {
if (v > largest and line.len - i > charsLeft) {
// print("{d}", .{line[i] - '0'});
index = i;
largest = line[i];
}
}
return index;
}
const RecursiveFind = struct {
line: []const u8,
arena: std.heap.ArenaAllocator,
count: usize,
backing: std.mem.Allocator,
output: std.ArrayList(usize) = .empty,
pub fn init(allocator: std.mem.Allocator, line: []const u8, count: usize) @This() {
return .{
.line = line,
.count = count,
.backing = allocator,
.arena = std.heap.ArenaAllocator.init(allocator),
};
}
pub fn deinit(self: *@This()) void {
self.arena.deinit();
}
pub fn toDigits(self: *@This(), allocator: std.mem.Allocator, out: *std.ArrayList(u8)) !void {
for (self.output.items) |i| {
try out.append(allocator, self.line[i]);
}
}
// RecursiveFindNextLargestDigit
pub fn rflnd(self: *@This(), offset: usize) void {
const charsLeft = self.count - self.output.items.len;
if (charsLeft == 0 or offset > self.line.len)
return;
const allocator = self.arena.allocator();
const subline = self.line[offset..self.line.len];
const index = findLargest(subline, charsLeft - 1) + offset;
if (index == self.line.len)
return;
self.output.append(allocator, index) catch unreachable;
rflnd(self, index + 1);
}
};
pub fn main(init: std.process.Init) !void {
try shared.sharedInit(init);
const allocator: std.mem.Allocator = init.arena.allocator();
const bytes = shared.loadBytesArg(allocator);
var lineIter = std.mem.tokenizeScalar(u8, bytes, '\n');
var part1: i64 = 0;
var part2: i64 = 0;
var digits: std.ArrayList(u8) = .empty;
defer digits.deinit(allocator);
while (lineIter.next()) |l| {
const line = shared.trim(l);
var find = RecursiveFind.init(allocator, line, 2);
find.rflnd(0);
defer find.deinit();
digits.clearRetainingCapacity();
try find.toDigits(allocator, &digits);
part1 += try std.fmt.parseInt(i64, digits.items, 10);
var find2 = RecursiveFind.init(allocator, line, 12);
defer find2.deinit();
find2.rflnd(0);
digits.clearRetainingCapacity();
try find2.toDigits(allocator, &digits);
part2 += try std.fmt.parseInt(i64, digits.items, 10);
}
print("part1 {d}", .{part1});
print("part2 {d}", .{part2});
}