You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
2.3 KiB
Zig
92 lines
2.3 KiB
Zig
12 months ago
|
const std = @import("std");
|
||
|
|
||
|
pub fn main() !void {
|
||
|
const content = @embedFile("data.txt");
|
||
|
var lines = std.mem.split(u8, content, "\n");
|
||
|
|
||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||
|
const allocator = gpa.allocator();
|
||
|
|
||
|
const instructions = lines.next().?;
|
||
|
_ = lines.next();
|
||
|
|
||
|
var map = std.StringArrayHashMap([]const u8).init(allocator);
|
||
|
defer map.deinit();
|
||
|
|
||
|
while (lines.next()) |line| {
|
||
|
if (line.len == 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
try map.put(line[0..3], line[7..15]);
|
||
|
}
|
||
|
|
||
|
var i: u16 = 0;
|
||
|
var cur = try allocator.dupe(u8, "AAA");
|
||
|
while (true) : (i += 1) {
|
||
|
if (std.mem.eql(u8, cur, "ZZZ")) {
|
||
|
break;
|
||
|
}
|
||
|
const ins = instructions[i % instructions.len];
|
||
|
const nodes = map.get(cur).?;
|
||
|
if (ins == 'L') {
|
||
|
std.mem.copy(u8, cur, nodes[0..3]);
|
||
|
} else {
|
||
|
std.mem.copy(u8, cur, nodes[5..8]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std.debug.print("Part 1: {d}\n", .{i});
|
||
|
|
||
|
// Part 2
|
||
|
var nodes = std.ArrayList([]const u8).init(allocator);
|
||
|
defer nodes.deinit();
|
||
|
|
||
|
var steps = std.ArrayList(u32).init(allocator);
|
||
|
defer steps.deinit();
|
||
|
|
||
|
// Find starting nodes
|
||
|
for (map.keys()) |k| {
|
||
|
if (k[2] == 'A') {
|
||
|
try nodes.append(k);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// for each starting node, how long until we get to a Z-ending node
|
||
|
for (nodes.items) |node| {
|
||
|
var j: u32 = 0;
|
||
|
cur = try allocator.dupe(u8, node);
|
||
|
while (true) : (j += 1) {
|
||
|
// std.debug.print("checking node: {s}\n", .{cur});
|
||
|
if (cur[2] == 'Z') {
|
||
|
break;
|
||
|
}
|
||
|
const ins = instructions[j % instructions.len];
|
||
|
|
||
|
const next = map.get(cur).?;
|
||
|
if (ins == 'L') {
|
||
|
std.mem.copy(u8, cur, next[0..3]);
|
||
|
} else {
|
||
|
std.mem.copy(u8, cur, next[5..8]);
|
||
|
}
|
||
|
}
|
||
|
try steps.append(j);
|
||
|
}
|
||
|
|
||
|
var lowest: u64 = steps.items[0];
|
||
|
for (0..steps.items.len - 1) |j| {
|
||
|
lowest = lcm(lowest, steps.items[j + 1]).?;
|
||
|
}
|
||
|
std.debug.print("Part 2: {d}\n", .{lowest});
|
||
|
}
|
||
|
|
||
|
fn lcm(left: u64, right: u64) ?u64 {
|
||
|
var i: u64 = @max(left, right);
|
||
|
while (true) : (i += @max(left, right)) {
|
||
|
if (i % left == 0 and i % right == 0) {
|
||
|
return @as(u64, @intCast(i));
|
||
|
}
|
||
|
}
|
||
|
return null;
|
||
|
}
|