-
Notifications
You must be signed in to change notification settings - Fork 0
/
day5.zig
81 lines (66 loc) · 2.78 KB
/
day5.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const std = @import("std");
const util = @import("util.zig");
const Day5Error = error{
NotEnoughArgs,
InvalidPart,
};
pub fn main() !void {
const argv = try std.process.argsAlloc(std.heap.page_allocator);
defer std.process.argsFree(std.heap.page_allocator, argv);
if (argv.len != 3) {
std.log.err("3 args required but only {d} provided", .{argv.len});
return Day5Error.NotEnoughArgs;
}
const file_path = argv[1];
const part = try std.fmt.parseInt(i32, argv[2], 10);
const file = try std.fs.cwd().openFile(file_path, .{});
// First parse constraints graph
var buf: [1024]u8 = undefined;
const ConstraintSet = std.AutoArrayHashMap(i32, std.ArrayList(i32));
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var constraints = ConstraintSet.init(allocator);
while (try util.readLineOrEof(file.reader(), &buf)) |line| {
if (line.len == 0)
break;
var parts = std.mem.splitScalar(u8, line, '|');
const from = try std.fmt.parseInt(i32, parts.next().?, 10);
const to = try std.fmt.parseInt(i32, parts.next().?, 10);
if (constraints.getPtr(from)) |constraint| {
try constraint.append(to);
} else {
var newlist = std.ArrayList(i32).init(allocator);
try newlist.append(to);
try constraints.put(from, newlist);
}
}
switch (part) {
1 => {
var mid_page_sum: i32 = 0;
while (try util.readLineOrEof(file.reader(), &buf)) |line| {
var it = std.mem.splitScalar(u8, line, ',');
var update = std.ArrayList(i32).init(allocator);
while (it.next()) |s| {
try update.append(try std.fmt.parseInt(i32, s, 10));
}
var seen_pages = std.AutoArrayHashMap(i32, void).init(allocator);
const valid_update = outer: for (update.items) |page| {
// For each page, check that none of the pages that must come after it
// are in the set of pages that have already been seen.
if (constraints.get(page)) |*constraint|
for (constraint.items) |cpage|
if (seen_pages.contains(cpage))
break :outer false;
try seen_pages.put(page, {});
} else true;
if (valid_update) {
const mid_page = update.items[update.items.len / 2];
mid_page_sum += mid_page;
}
}
std.log.info("Mid page sum: {d}", .{mid_page_sum});
},
else => return Day5Error.InvalidPart,
}
}