day 19 part 1
This commit is contained in:
213
AdventOfCode2023/src/day19/day19.zig
Normal file
213
AdventOfCode2023/src/day19/day19.zig
Normal file
@ -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});
|
||||||
|
}
|
@ -12,13 +12,14 @@ const std = @import("std");
|
|||||||
// const day12 = @import("./day12/day12.zig");
|
// const day12 = @import("./day12/day12.zig");
|
||||||
// const day15 = @import("./day15/day15.zig");
|
// const day15 = @import("./day15/day15.zig");
|
||||||
// const day16 = @import("./day16/day16.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");
|
const utils = @import("utils.zig");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
const allocator = std.heap.page_allocator;
|
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);
|
defer allocator.free(input);
|
||||||
|
|
||||||
try day18.solve(input);
|
try day19.solve(input);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user