From a289714873a30d260b80310d834419fc901bb1e5 Mon Sep 17 00:00:00 2001 From: John Costa Date: Wed, 20 Dec 2023 00:09:18 +0000 Subject: [PATCH] day 19 part 1 --- AdventOfCode2023/src/day19/day19.zig | 213 +++++++++++++++++++++++++++ AdventOfCode2023/src/main.zig | 7 +- 2 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 AdventOfCode2023/src/day19/day19.zig diff --git a/AdventOfCode2023/src/day19/day19.zig b/AdventOfCode2023/src/day19/day19.zig new file mode 100644 index 0000000..d73e496 --- /dev/null +++ b/AdventOfCode2023/src/day19/day19.zig @@ -0,0 +1,213 @@ +const std = @import("std"); +const print = std.debug.print; + +// rfg{s<537:gd,x>2440:R,A} + +const Condition = struct { + category: u8, //xmas + value: usize, + operation: u8, // <, > + trueCondition: []const u8, +}; + +const Rule = struct { conditions: std.ArrayList(*Condition), endAccept: bool, endReject: bool, endRule: []const u8 }; + +const Part = struct { + x: usize, + m: usize, + a: usize, + s: usize, +}; + +pub fn solve(input: [][]const u8) !void { + var allocator = std.heap.page_allocator; + var foundEmptyLine = false; + + var ruleMap = std.StringHashMap(*Rule).init(allocator); + var parts = std.ArrayList(*Part).init(allocator); + + for (input) |line| { + if (line[0] == '{') { + foundEmptyLine = true; + } + + if (!foundEmptyLine) { + // parse rule + var l = line[0 .. line.len - 1]; + var index: usize = 0; + for (l) |c| { + if (c == '{') { + break; + } + index += 1; + } + + var ruleName = l[0..index]; + l = l[index + 1 ..]; + + var ruleList = std.ArrayList(*Condition).init(allocator); + + var commasTokens = std.mem.tokenizeSequence(u8, l, ","); + var currentRule: []const u8 = "hello"; + + while (commasTokens.next()) |rule| { + currentRule = rule; + if (commasTokens.peek()) |_| { + var dotsTokens = std.mem.tokenizeSequence(u8, rule, ":"); + var condition = dotsTokens.next().?; + var name = dotsTokens.next().?; + + var category = condition[0]; + var operation = condition[1]; + + var c = try allocator.create(Condition); + + c.*.category = category; + c.*.value = try std.fmt.parseInt(usize, condition[2..], 10); + c.*.operation = operation; + c.*.trueCondition = name; + + try ruleList.append(c); + } + } + + var rule = try allocator.create(Rule); + rule.*.endAccept = false; + rule.*.endReject = false; + + if (currentRule[0] == 'A') { + rule.*.endAccept = true; + } else if (currentRule[0] == 'R') { + rule.*.endReject = true; + } + + rule.*.conditions = ruleList; + rule.*.endRule = currentRule; + + try ruleMap.put(ruleName, rule); + continue; + } + + var l = line[1 .. line.len - 1]; + var commas = std.mem.tokenizeSequence(u8, l, ","); + + var x = commas.next().?; + var m = commas.next().?; + var a = commas.next().?; + var s = commas.next().?; + + var part = try allocator.create(Part); + part.*.x = try std.fmt.parseInt(usize, x[2..], 10); + part.*.m = try std.fmt.parseInt(usize, m[2..], 10); + part.*.a = try std.fmt.parseInt(usize, a[2..], 10); + part.*.s = try std.fmt.parseInt(usize, s[2..], 10); + + try parts.append(part); + } + + var acceptedParts = std.ArrayList(Part).init(allocator); + + var accepted: usize = 0; + var rejected: usize = 0; + + itemChecking: for (parts.items) |part| { + var p: Part = part.*; + var currentRule: Rule = ruleMap.get("in").?.*; + + checking: while (true) { + for (currentRule.conditions.items) |condition| { + var c = condition.*; + // print("End Rule {s}\n", .{currentRule.endRule}); + + switch (c.category) { + 'x' => { + if (c.operation == '<' and p.x < c.value or c.operation == '>' and p.x > c.value) { + // print("X accept\n", .{}); + if (condition.trueCondition[0] == 'A') { + accepted += 1; + try acceptedParts.append(p); + continue :itemChecking; + } else if (condition.trueCondition[0] == 'R') { + rejected += 1; + continue :itemChecking; + } + currentRule = ruleMap.get(condition.trueCondition).?.*; + continue :checking; + } + }, + 'm' => { + if (c.operation == '<' and p.m < c.value or c.operation == '>' and p.m > c.value) { + // print("M accept\n", .{}); + if (condition.trueCondition[0] == 'A') { + accepted += 1; + try acceptedParts.append(p); + continue :itemChecking; + } else if (condition.trueCondition[0] == 'R') { + rejected += 1; + continue :itemChecking; + } + currentRule = ruleMap.get(condition.trueCondition).?.*; + continue :checking; + } + }, + 'a' => { + if (c.operation == '<' and p.a < c.value or c.operation == '>' and p.a > c.value) { + // print("A accept\n", .{}); + if (condition.trueCondition[0] == 'A') { + accepted += 1; + try acceptedParts.append(p); + continue :itemChecking; + } else if (condition.trueCondition[0] == 'R') { + rejected += 1; + continue :itemChecking; + } + currentRule = ruleMap.get(condition.trueCondition).?.*; + continue :checking; + } + }, + 's' => { + if (c.operation == '<' and p.s < c.value or c.operation == '>' and p.s > c.value) { + // print("S Accept\n", .{}); + if (condition.trueCondition[0] == 'A') { + accepted += 1; + try acceptedParts.append(p); + continue :itemChecking; + } else if (condition.trueCondition[0] == 'R') { + rejected += 1; + continue :itemChecking; + } + // print("S true condition: {s}\n", .{condition.trueCondition}); + currentRule = ruleMap.get(condition.trueCondition).?.*; + continue :checking; + } + }, + else => unreachable, + } + + // print("Reached end of rules\n", .{}); + // print("-----\n", .{}); + // Reached end of rule. But nothing was satisfied. + } + + if (currentRule.endAccept) { + accepted += 1; + try acceptedParts.append(p); + continue :itemChecking; + } else if (currentRule.endReject) { + rejected += 1; + continue :itemChecking; + } + + currentRule = ruleMap.get(currentRule.endRule).?.*; + } + } + + var part1: usize = 0; + + for (acceptedParts.items) |part| { + var p: Part = part; + part1 += p.x + p.m + p.a + p.s; + } + + print("Part 1: {}\n", .{part1}); +} diff --git a/AdventOfCode2023/src/main.zig b/AdventOfCode2023/src/main.zig index 44429f8..003a169 100644 --- a/AdventOfCode2023/src/main.zig +++ b/AdventOfCode2023/src/main.zig @@ -12,13 +12,14 @@ const std = @import("std"); // const day12 = @import("./day12/day12.zig"); // const day15 = @import("./day15/day15.zig"); // const day16 = @import("./day16/day16.zig"); -const day18 = @import("./day18/day18.zig"); +// const day18 = @import("./day18/day18.zig"); +const day19 = @import("./day19/day19.zig"); const utils = @import("utils.zig"); pub fn main() !void { const allocator = std.heap.page_allocator; - var input = try utils.getInput("./src/day18/input.txt", allocator); + var input = try utils.getInput("./src/day19/input.txt", allocator); defer allocator.free(input); - try day18.solve(input); + try day19.solve(input); }