From 8049b7685d644a880b85301f0143ce05d74ed57e Mon Sep 17 00:00:00 2001 From: Xander Bil Date: Thu, 5 Dec 2024 19:51:53 +0100 Subject: add solution day 5 --- main.zig | 2 + src/day05.zig | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/day05.zig diff --git a/main.zig b/main.zig index 871eec2..3daefa7 100644 --- a/main.zig +++ b/main.zig @@ -5,6 +5,7 @@ const day01 = @import("src/day01.zig"); const day02 = @import("src/day02.zig"); const day03 = @import("src/day03.zig"); const day04 = @import("src/day04.zig"); +const day05 = @import("src/day05.zig"); pub fn main() !void { if (std.os.argv.len != 3) { @@ -37,6 +38,7 @@ pub fn main() !void { 2 => day02.solve(args[2], buffer), 3 => day03.solve(args[2], buffer, allocator), 4 => day04.solve(args[2], buffer, allocator), + 5 => day05.solve(args[2], buffer, allocator), else => print("Day not yet implemented", .{}), }; } 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}); +} -- cgit v1.2.3