summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/day05.zig132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/day05.zig b/src/day05.zig
new file mode 100644
index 0000000..27eafac
--- /dev/null
+++ b/src/day05.zig
@@ -0,0 +1,132 @@
+const std = @import("std");
+const mecha = @import("mecha");
+const print = std.debug.print;
+
+pub fn solve(part: []u8, buffer: []u8, allocator: std.mem.Allocator) !void {
+ var lines = std.mem.splitScalar(u8, buffer, '\n');
+ if (std.mem.eql(u8, part, "1")) {
+ try part1(&lines, allocator);
+ } else {
+ try part2(&lines, allocator);
+ }
+}
+
+fn get_ordering_rules(lines: *std.mem.SplitIterator(u8, .scalar), allocator: std.mem.Allocator) !std.AutoHashMap(usize, std.ArrayList(usize)) {
+ var ordering_rules = std.AutoHashMap(usize, std.ArrayList(usize)).init(allocator);
+ errdefer ordering_rules.deinit();
+
+ const parser = mecha.combine(.{ mecha.int(usize, .{}), mecha.ascii.char('|').discard(), mecha.int(usize, .{}) });
+
+ // PAGE ORDERING RULES
+ while (lines.next()) |line| {
+ if (line.len == 0) {
+ break;
+ }
+
+ const parsed = try parser.parse(allocator, line);
+
+ if (ordering_rules.getPtr(parsed.value[0])) |value| {
+ try value.append(parsed.value[1]);
+ } else {
+ var list = std.ArrayList(usize).init(allocator);
+ errdefer list.deinit();
+ try list.append(parsed.value[1]);
+ try ordering_rules.put(parsed.value[0], list);
+ }
+ }
+
+ return ordering_rules;
+}
+
+fn part1(lines: *std.mem.SplitIterator(u8, .scalar), allocator: std.mem.Allocator) !void {
+ var ordering_rules = try get_ordering_rules(lines, allocator);
+ defer ordering_rules.deinit();
+
+ var total: usize = 0;
+
+ // UPDATES
+ outer: while (lines.next()) |line| {
+ if (line.len == 0) {
+ break;
+ }
+
+ var list = std.ArrayList(usize).init(allocator);
+ defer list.deinit();
+
+ var covered_numbers = std.AutoHashMap(usize, void).init(allocator);
+ defer covered_numbers.deinit();
+
+ var page_numbers = std.mem.splitScalar(u8, line, ',');
+ while (page_numbers.next()) |page_number| {
+ const number = try std.fmt.parseInt(usize, page_number, 10);
+ try covered_numbers.put(number, {});
+ try list.append(number);
+
+ const next = ordering_rules.get(number) orelse continue;
+ for (next.items) |n| {
+ if (covered_numbers.contains(n)) {
+ continue :outer;
+ }
+ }
+ }
+
+ total += list.items[list.items.len / 2];
+ }
+
+ print("{d}\n", .{total});
+}
+
+//-----------------------PART 2----------------------------
+
+fn reorder(list: *std.ArrayList(usize), ordering_rules: *std.AutoHashMap(usize, std.ArrayList(usize)), allocator: std.mem.Allocator) !bool {
+ var covered_numbers = std.AutoHashMap(usize, usize).init(allocator);
+ defer covered_numbers.deinit();
+
+ for (list.items, 0..) |number, i| {
+ try covered_numbers.put(number, i);
+
+ const next = ordering_rules.get(number) orelse continue;
+ for (next.items) |n| {
+ if (covered_numbers.get(n)) |index| {
+ list.items[i] = n;
+ list.items[index] = number;
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+fn part2(lines: *std.mem.SplitIterator(u8, .scalar), allocator: std.mem.Allocator) !void {
+ var ordering_rules = try get_ordering_rules(lines, allocator);
+ defer ordering_rules.deinit();
+
+ var total: usize = 0;
+
+ // UPDATES
+ while (lines.next()) |line| {
+ if (line.len == 0) {
+ break;
+ }
+
+ var list = std.ArrayList(usize).init(allocator);
+ defer list.deinit();
+
+ var page_numbers = std.mem.splitScalar(u8, line, ',');
+ while (page_numbers.next()) |page_number| {
+ const number = try std.fmt.parseInt(usize, page_number, 10);
+ try list.append(number);
+ }
+
+ var incorrect = false;
+ while (!try reorder(&list, &ordering_rules, allocator)) {
+ incorrect = true;
+ }
+
+ if (incorrect) {
+ total += list.items[list.items.len / 2];
+ }
+ }
+
+ print("{d}\n", .{total});
+}