120 lines
3.2 KiB
Zig
120 lines
3.2 KiB
Zig
const std = @import("std");
|
|
|
|
pub const title = "Day 11: Reactor";
|
|
|
|
pub fn run(allocator: std.mem.Allocator) !void {
|
|
const input = @embedFile("./input/day11.txt");
|
|
//const input =
|
|
// \\aaa: you hhh
|
|
// \\you: bbb ccc
|
|
// \\bbb: ddd eee
|
|
// \\ccc: ddd eee fff
|
|
// \\ddd: ggg
|
|
// \\eee: out
|
|
// \\fff: out
|
|
// \\ggg: out
|
|
// \\hhh: ccc fff iii
|
|
// \\iii: out
|
|
// ;
|
|
//const input =
|
|
// \\svr: aaa bbb
|
|
// \\aaa: fft
|
|
// \\fft: ccc
|
|
// \\bbb: tty
|
|
// \\tty: ccc
|
|
// \\ccc: ddd eee
|
|
// \\ddd: hub
|
|
// \\hub: fff
|
|
// \\eee: dac
|
|
// \\dac: fff
|
|
// \\fff: ggg hhh
|
|
// \\ggg: out
|
|
// \\hhh: out
|
|
// ;
|
|
|
|
var lines = std.mem.tokenizeScalar(u8, input, '\n');
|
|
|
|
var devices: std.StringHashMap([][]const u8) = .init(allocator);
|
|
defer {
|
|
var outputs_iter = devices.valueIterator();
|
|
while (outputs_iter.next()) |value| {
|
|
allocator.free(value.*);
|
|
}
|
|
devices.deinit();
|
|
}
|
|
|
|
while (lines.next()) |line| {
|
|
const device = line[0..3];
|
|
std.debug.print("device = {s}\n", .{device});
|
|
|
|
var outputs: std.ArrayList([]const u8) = .empty;
|
|
defer outputs.deinit(allocator);
|
|
|
|
var outputs_iter = std.mem.tokenizeScalar(u8, line[5..], ' ');
|
|
while (outputs_iter.next()) |output| {
|
|
try outputs.append(allocator, output);
|
|
}
|
|
|
|
const outputs_slice = try outputs.toOwnedSlice(allocator);
|
|
errdefer allocator.free(outputs_slice);
|
|
|
|
try devices.put(device, outputs_slice);
|
|
}
|
|
|
|
var cache: std.StringHashMap(usize) = .init(allocator);
|
|
defer cache.deinit();
|
|
try cache.ensureTotalCapacity(devices.count());
|
|
|
|
const dac_to_fft = try visitOutputs("dac", "fft", devices, &cache);
|
|
const svr_to_fft = try visitOutputs("svr", "fft", devices, &cache);
|
|
cache.clearRetainingCapacity();
|
|
|
|
const to_fft = if (dac_to_fft == 0) svr_to_fft else dac_to_fft;
|
|
|
|
const dac_start = if (dac_to_fft == 0) "fft" else "svr";
|
|
const end_start = if (dac_to_fft == 0) "dac" else "fft";
|
|
|
|
const to_dac = try visitOutputs(dac_start, "dac", devices, &cache);
|
|
cache.clearRetainingCapacity();
|
|
|
|
const to_end = try visitOutputs(end_start, "out", devices, &cache);
|
|
|
|
const result = to_fft * to_dac * to_end;
|
|
|
|
var buffer: [8]u8 = undefined;
|
|
var stdout_writer = std.fs.File.stdout().writer(&buffer);
|
|
const stdout = &stdout_writer.interface;
|
|
|
|
try stdout.print("{d}\n", .{result});
|
|
|
|
try stdout.flush();
|
|
}
|
|
|
|
fn visitOutputs(
|
|
start: []const u8,
|
|
end: []const u8,
|
|
devices: std.StringHashMap([][]const u8),
|
|
cache: *std.StringHashMap(usize),
|
|
) !usize {
|
|
if (cache.get(start)) |result| {
|
|
return result;
|
|
}
|
|
|
|
var paths: usize = 0;
|
|
const device = devices.get(start);
|
|
if (device) |outputs| {
|
|
for (outputs) |output| {
|
|
if (std.mem.eql(u8, output, end)) {
|
|
paths += 1;
|
|
} else {
|
|
paths += try visitOutputs(output, end, devices, cache);
|
|
}
|
|
}
|
|
try cache.put(start, paths);
|
|
return paths;
|
|
} else {
|
|
std.debug.print("device {s} not found\n", .{start});
|
|
return 0;
|
|
}
|
|
}
|
|
|