diff options
author | Xander Bil <xander@biltopia.org> | 2024-12-05 19:51:53 +0100 |
---|---|---|
committer | Xander Bil <xander@biltopia.org> | 2024-12-05 19:51:53 +0100 |
commit | 8049b7685d644a880b85301f0143ce05d74ed57e (patch) | |
tree | 016c611e9cbce96367c0b2d03d142a304bf5ead7 /src | |
parent | 30dcfdae77add982081b5fa70f3823dd1a942419 (diff) | |
download | aoc2024-8049b7685d644a880b85301f0143ce05d74ed57e.tar.xz aoc2024-8049b7685d644a880b85301f0143ce05d74ed57e.zip |
add solution day 5
Diffstat (limited to 'src')
-rw-r--r-- | src/day05.zig | 132 |
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}); +} |