Day 7
This commit is contained in:
parent
7a59369808
commit
1ca55ed289
|
@ -0,0 +1,105 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn main() void {
|
||||
const input = @embedFile("input");
|
||||
|
||||
var part1: usize = 0;
|
||||
// Go through each command one by one
|
||||
var iter = dirIterator.init(input);
|
||||
|
||||
const root = sumSizes(&iter, 100_000, &part1);
|
||||
std.debug.print("Part 1: {}\n", .{part1});
|
||||
|
||||
var part2: usize = 0;
|
||||
_ = findBiggest(iter.reset(), root - 40_000_000, &part2);
|
||||
std.debug.print("Part 2: {}\n", .{part2});
|
||||
}
|
||||
|
||||
fn eql(a: []const u8, b: []const u8) bool {
|
||||
return std.mem.eql(u8, a, b);
|
||||
}
|
||||
|
||||
fn findBiggest(iter: *dirIterator, minimum: usize, global: *usize) usize {
|
||||
var size: usize = 0;
|
||||
|
||||
while (iter.next()) |cmd| {
|
||||
size += switch (cmd) {
|
||||
.file => iter.parseSize(),
|
||||
.dirEnter => findBiggest(iter, minimum, global),
|
||||
.dirExit => break,
|
||||
};
|
||||
}
|
||||
|
||||
// If the size doesn't exceed the limit, add it to the total
|
||||
if (size > minimum and (size < global.* or global.* == 0)) global.* = size;
|
||||
|
||||
// Return the size witout filtering
|
||||
return size;
|
||||
}
|
||||
|
||||
fn sumSizes(iter: *dirIterator, limit: usize, total: *usize) usize {
|
||||
var size: usize = 0;
|
||||
|
||||
while (iter.next()) |cmd| {
|
||||
size += switch (cmd) {
|
||||
.file => iter.parseSize(),
|
||||
.dirEnter => sumSizes(iter, limit, total),
|
||||
.dirExit => break,
|
||||
};
|
||||
}
|
||||
|
||||
// If the size doesn't exceed the limit, add it to the total
|
||||
total.* += if (size <= limit) size else 0;
|
||||
|
||||
// Return the size witout filtering
|
||||
return size;
|
||||
}
|
||||
|
||||
// Helper to iterate through the commands
|
||||
const dirIterator = struct {
|
||||
iter: std.mem.SplitIterator(u8),
|
||||
|
||||
const cmdType = enum {
|
||||
dirEnter,
|
||||
dirExit,
|
||||
file,
|
||||
};
|
||||
|
||||
pub fn init(input: []const u8) dirIterator {
|
||||
return .{ .iter = std.mem.split(u8, input, "\n") };
|
||||
}
|
||||
|
||||
// Returns the file size of the current line or 0
|
||||
pub fn parseSize(self: dirIterator) usize {
|
||||
const numSlice = std.mem.sliceTo(self.iter.rest(), ' ');
|
||||
return std.fmt.parseInt(usize, numSlice, 10) catch 0;
|
||||
}
|
||||
|
||||
pub fn next(self: *dirIterator) ?cmdType {
|
||||
// Go through each command one by one
|
||||
while (self.iter.next()) |line| {
|
||||
// Not a valid input
|
||||
if (line.len <= 0) continue;
|
||||
|
||||
// Changing folder (quitting or recursing)
|
||||
if (line.len > 5 and eql(line[0..5], "$ cd ")) {
|
||||
// Reached the end of the folder
|
||||
if (eql(line[5..], "..")) return cmdType.dirExit;
|
||||
|
||||
// "cd" command not to parent, then it's a child
|
||||
return cmdType.dirEnter;
|
||||
}
|
||||
|
||||
// Not a cd, maybe it's a size
|
||||
return cmdType.file;
|
||||
}
|
||||
|
||||
// Exhausted the input
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn reset(self: *dirIterator) *dirIterator {
|
||||
self.iter.reset();
|
||||
return self;
|
||||
}
|
||||
};
|
Reference in New Issue