Solve day 7
This commit is contained in:
parent
1db82043b9
commit
aca30f0380
115
src/day07.zig
Normal file
115
src/day07.zig
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const input = @embedFile("input/day07.txt");
|
||||||
|
const test_input = @embedFile("input/day07_test1.txt");
|
||||||
|
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{ .safety = true }){};
|
||||||
|
const allocator = gpa.allocator();
|
||||||
|
|
||||||
|
const Dir = struct {
|
||||||
|
name: []const u8,
|
||||||
|
saved_size: ?usize,
|
||||||
|
parent: ?*Dir,
|
||||||
|
dirs: std.StringHashMap(*Dir),
|
||||||
|
file_size: usize,
|
||||||
|
fn new(name: []const u8, parent: ?*Dir) !*Dir {
|
||||||
|
const dir = try allocator.create(Dir);
|
||||||
|
dir.* = Dir{
|
||||||
|
.name = name,
|
||||||
|
.saved_size = null,
|
||||||
|
.parent = parent,
|
||||||
|
.dirs = std.StringHashMap(*Dir).init(allocator),
|
||||||
|
.file_size = 0,
|
||||||
|
};
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
fn size(self: Dir) usize {
|
||||||
|
if (self.saved_size) |s| return s;
|
||||||
|
|
||||||
|
var total = self.file_size;
|
||||||
|
var dir_iter = self.dirs.valueIterator();
|
||||||
|
while (dir_iter.next()) |dir| {
|
||||||
|
total += dir.*.size();
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
fn sum_sizes_lte(self: Dir, size_limit: usize) usize {
|
||||||
|
var sum: usize = if (self.size() <= size_limit) self.size() else 0;
|
||||||
|
var dir_iter = self.dirs.valueIterator();
|
||||||
|
while (dir_iter.next()) |dir| {
|
||||||
|
sum += dir.*.sum_sizes_lte(size_limit);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
fn find_smallest_size_gte(self: Dir, size_limit: usize) ?usize {
|
||||||
|
var smallest_size = if (self.size() >= size_limit) self.size() else null;
|
||||||
|
var dir_iter = self.dirs.valueIterator();
|
||||||
|
while (dir_iter.next()) |dir| {
|
||||||
|
if (dir.*.find_smallest_size_gte(size_limit)) |child_size| {
|
||||||
|
if (smallest_size) |current_size| {
|
||||||
|
if (child_size < current_size) {
|
||||||
|
smallest_size = child_size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
smallest_size = child_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return smallest_size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn build_dir_tree(commands: []const u8) !*Dir {
|
||||||
|
var lines = std.mem.tokenize(u8, commands, "\n");
|
||||||
|
_ = lines.next(); // first line is always `cd /`
|
||||||
|
var root = try Dir.new("/", null);
|
||||||
|
var current_dir = root;
|
||||||
|
while (lines.next()) |line| {
|
||||||
|
if (std.mem.eql(u8, line[0..1], "$")) {
|
||||||
|
if (std.mem.eql(u8, line[2..4], "cd")) {
|
||||||
|
if (std.mem.eql(u8, line[5..], "..")) {
|
||||||
|
current_dir = current_dir.parent.?;
|
||||||
|
} else {
|
||||||
|
if (current_dir.dirs.get(line[5..])) |dir| {
|
||||||
|
current_dir = dir;
|
||||||
|
} else {
|
||||||
|
var new_dir = try Dir.new(line[5..], current_dir);
|
||||||
|
try current_dir.dirs.put(line[5..], new_dir);
|
||||||
|
current_dir = new_dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var output_parts = std.mem.tokenize(u8, line, " ");
|
||||||
|
const dir_or_size = output_parts.next().?;
|
||||||
|
if (std.mem.eql(u8, dir_or_size, "dir")) {
|
||||||
|
const name = output_parts.next().?;
|
||||||
|
var new_dir = try Dir.new(name, current_dir);
|
||||||
|
try current_dir.dirs.put(name, new_dir);
|
||||||
|
} else {
|
||||||
|
const size = try std.fmt.parseInt(usize, dir_or_size, 10);
|
||||||
|
current_dir.file_size += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn solve_part1(data: []const u8) !usize {
|
||||||
|
const root = try build_dir_tree(data);
|
||||||
|
return root.sum_sizes_lte(100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn solve_part2(data: []const u8) !usize {
|
||||||
|
const root = try build_dir_tree(data);
|
||||||
|
const space_needed = 30000000 - (70000000 - root.size());
|
||||||
|
return root.find_smallest_size_gte(space_needed).?;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "solves part1" {
|
||||||
|
try std.testing.expectEqual(solve_part1(test_input), 95437);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "solves part2" {
|
||||||
|
try std.testing.expectEqual(solve_part2(test_input), 24933642);
|
||||||
|
}
|
1031
src/input/day07.txt
Executable file
1031
src/input/day07.txt
Executable file
File diff suppressed because it is too large
Load Diff
23
src/input/day07_test1.txt
Normal file
23
src/input/day07_test1.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
$ cd /
|
||||||
|
$ ls
|
||||||
|
dir a
|
||||||
|
14848514 b.txt
|
||||||
|
8504156 c.dat
|
||||||
|
dir d
|
||||||
|
$ cd a
|
||||||
|
$ ls
|
||||||
|
dir e
|
||||||
|
29116 f
|
||||||
|
2557 g
|
||||||
|
62596 h.lst
|
||||||
|
$ cd e
|
||||||
|
$ ls
|
||||||
|
584 i
|
||||||
|
$ cd ..
|
||||||
|
$ cd ..
|
||||||
|
$ cd d
|
||||||
|
$ ls
|
||||||
|
4060174 j
|
||||||
|
8033020 d.log
|
||||||
|
5626152 d.ext
|
||||||
|
7214296 k
|
@ -6,6 +6,7 @@ const day03 = @import("day03.zig");
|
|||||||
const day04 = @import("day04.zig");
|
const day04 = @import("day04.zig");
|
||||||
const day05 = @import("day05.zig");
|
const day05 = @import("day05.zig");
|
||||||
const day06 = @import("day06.zig");
|
const day06 = @import("day06.zig");
|
||||||
|
const day07 = @import("day07.zig");
|
||||||
const utils = @import("utils.zig");
|
const utils = @import("utils.zig");
|
||||||
|
|
||||||
fn solve_day(comptime day_num: u8, day: anytype, stdout: anytype, timer: *std.time.Timer) !void {
|
fn solve_day(comptime day_num: u8, day: anytype, stdout: anytype, timer: *std.time.Timer) !void {
|
||||||
@ -44,6 +45,7 @@ pub fn main() !void {
|
|||||||
try solve_day(4, day04, &stdout, &timer);
|
try solve_day(4, day04, &stdout, &timer);
|
||||||
try solve_day(5, day05, &stdout, &timer);
|
try solve_day(5, day05, &stdout, &timer);
|
||||||
try solve_day(6, day06, &stdout, &timer);
|
try solve_day(6, day06, &stdout, &timer);
|
||||||
|
try solve_day(7, day07, &stdout, &timer);
|
||||||
|
|
||||||
try bw.flush();
|
try bw.flush();
|
||||||
}
|
}
|
||||||
@ -57,5 +59,6 @@ test {
|
|||||||
_ = day04;
|
_ = day04;
|
||||||
_ = day05;
|
_ = day05;
|
||||||
_ = day06;
|
_ = day06;
|
||||||
|
_ = day07;
|
||||||
_ = utils;
|
_ = utils;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user