2024 Day 5 Zig backport
This commit is contained in:
parent
eb2f09dfe4
commit
4279067eae
2 changed files with 238 additions and 0 deletions
|
|
@ -28,3 +28,36 @@ pub const Lines = struct {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn AutoHashSet(comptime T: type) type {
|
||||
const Empty = struct {};
|
||||
const Map = std.AutoHashMap(T, Empty);
|
||||
|
||||
return struct {
|
||||
map: Map,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) Self {
|
||||
return .{
|
||||
.map = Map.init(allocator),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.map.deinit();
|
||||
}
|
||||
|
||||
pub fn put(self: *Self, v: T) !void {
|
||||
return self.map.put(v, .{});
|
||||
}
|
||||
|
||||
pub fn contains(self: Self, v: T) bool {
|
||||
return self.map.contains(v);
|
||||
}
|
||||
|
||||
pub fn valueIterator(self: Self) Map.KeyIterator {
|
||||
return self.map.keyIterator();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
205
2024/src/day05.zig
Normal file
205
2024/src/day05.zig
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
const std = @import("std");
|
||||
const aoc = @import("aoc.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const ArrayList = std.ArrayList;
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .{};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const file = try std.fs.cwd().openFile("input/day05.txt", .{});
|
||||
defer file.close();
|
||||
|
||||
const text = try file.readToEndAlloc(allocator, comptime 1 << 30);
|
||||
defer allocator.free(text);
|
||||
|
||||
var input = try Input.parse(allocator, text);
|
||||
defer input.deinit();
|
||||
|
||||
const stdout_file = std.io.getStdOut().writer();
|
||||
var bw = std.io.bufferedWriter(stdout_file);
|
||||
const stdout = bw.writer();
|
||||
|
||||
try stdout.print("{d}\n", .{try part1(input)});
|
||||
try bw.flush();
|
||||
|
||||
try stdout.print("{d}\n", .{try part2(input)});
|
||||
try bw.flush();
|
||||
}
|
||||
|
||||
const Input = struct {
|
||||
rules: ArrayList(Rule),
|
||||
updates: ArrayList(Update),
|
||||
constraints: std.AutoHashMap(u32, Constraints),
|
||||
|
||||
fn deinit(self: *Input) void {
|
||||
self.rules.deinit();
|
||||
|
||||
for (self.updates.items) |update| {
|
||||
update.deinit();
|
||||
}
|
||||
|
||||
self.updates.deinit();
|
||||
|
||||
var it = self.constraints.valueIterator();
|
||||
while (it.next()) |value| {
|
||||
value.before.deinit();
|
||||
value.after.deinit();
|
||||
}
|
||||
self.constraints.deinit();
|
||||
}
|
||||
|
||||
fn parse(alloc: Allocator, text: []const u8) !Input {
|
||||
var blocks = std.mem.tokenizeSequence(u8, text, "\n\n");
|
||||
|
||||
var rule_lines = std.mem.tokenizeScalar(u8, blocks.next().?, '\n');
|
||||
var rules = ArrayList(Rule).init(alloc);
|
||||
while (rule_lines.next()) |line| {
|
||||
try rules.append(try Rule.parse(line));
|
||||
}
|
||||
|
||||
var update_lines = std.mem.tokenizeScalar(u8, blocks.next().?, '\n');
|
||||
var updates = ArrayList(Update).init(alloc);
|
||||
while (update_lines.next()) |line| {
|
||||
try updates.append(try Update.parse(alloc, line));
|
||||
}
|
||||
|
||||
var constraints = std.AutoHashMap(u32, Constraints).init(alloc);
|
||||
|
||||
for (rules.items) |rule| {
|
||||
{
|
||||
var c = try constraints.getOrPut(rule.x);
|
||||
if (!c.found_existing) {
|
||||
c.value_ptr.* = Constraints.init(alloc);
|
||||
}
|
||||
try c.value_ptr.after.put(rule.y);
|
||||
}
|
||||
|
||||
{
|
||||
var c = try constraints.getOrPut(rule.y);
|
||||
if (!c.found_existing) {
|
||||
c.value_ptr.* = Constraints.init(alloc);
|
||||
}
|
||||
try c.value_ptr.before.put(rule.x);
|
||||
}
|
||||
}
|
||||
|
||||
return .{
|
||||
.rules = rules,
|
||||
.updates = updates,
|
||||
.constraints = constraints,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const Rule = struct {
|
||||
x: u32,
|
||||
y: u32,
|
||||
|
||||
fn parse(line: []const u8) !Rule {
|
||||
var it = std.mem.tokenizeScalar(u8, line, '|');
|
||||
|
||||
const x = try std.fmt.parseInt(u32, it.next().?, 10);
|
||||
const y = try std.fmt.parseInt(u32, it.next().?, 10);
|
||||
|
||||
return .{
|
||||
.x = x,
|
||||
.y = y,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const Update = struct {
|
||||
pages: ArrayList(u32),
|
||||
|
||||
fn deinit(self: Update) void {
|
||||
self.pages.deinit();
|
||||
}
|
||||
|
||||
fn parse(alloc: Allocator, line: []const u8) !Update {
|
||||
var pages = ArrayList(u32).init(alloc);
|
||||
|
||||
var it = std.mem.tokenizeScalar(u8, line, ',');
|
||||
while (it.next()) |p| {
|
||||
const page = try std.fmt.parseInt(u32, p, 10);
|
||||
try pages.append(page);
|
||||
}
|
||||
|
||||
return .{
|
||||
.pages = pages,
|
||||
};
|
||||
}
|
||||
|
||||
fn valid(self: Update, constraints: std.AutoHashMap(u32, Constraints)) bool {
|
||||
const items = self.pages.items;
|
||||
for (items[0..(items.len - 1)], items[1..]) |x, y| {
|
||||
if (constraints.get(x)) |c| {
|
||||
if (!c.after.contains(y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const Constraints = struct {
|
||||
before: aoc.AutoHashSet(u32),
|
||||
after: aoc.AutoHashSet(u32),
|
||||
|
||||
fn init(alloc: Allocator) Constraints {
|
||||
return .{
|
||||
.before = aoc.AutoHashSet(u32).init(alloc),
|
||||
.after = aoc.AutoHashSet(u32).init(alloc),
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: *Constraints) void {
|
||||
self.before.deinit();
|
||||
self.before = undefined;
|
||||
self.after.deinit();
|
||||
self.after = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
fn part1(input: Input) !u32 {
|
||||
var sum: u32 = 0;
|
||||
for (input.updates.items) |u| {
|
||||
if (u.valid(input.constraints)) {
|
||||
sum += u.pages.items[u.pages.items.len / 2];
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
const FixUpdate = struct {
|
||||
constraints: std.AutoHashMap(u32, Constraints),
|
||||
|
||||
fn lessThan(self: FixUpdate, x: u32, y: u32) bool {
|
||||
if (self.constraints.get(x)) |c| {
|
||||
return c.after.contains(y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
fn part2(input: Input) !u32 {
|
||||
var sum: u32 = 0;
|
||||
for (input.updates.items) |u| {
|
||||
if (u.valid(input.constraints)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std.mem.sort(
|
||||
u32,
|
||||
u.pages.items,
|
||||
FixUpdate{ .constraints = input.constraints },
|
||||
FixUpdate.lessThan,
|
||||
);
|
||||
|
||||
sum += u.pages.items[u.pages.items.len / 2];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
Loading…
Reference in a new issue