130 lines
3.2 KiB
Zig
130 lines
3.2 KiB
Zig
const std = @import("std");
|
|
const print = std.debug.print;
|
|
|
|
const Node = []const u8;
|
|
const Route = std.ArrayList(Node);
|
|
const Edge = struct {
|
|
left: Node,
|
|
right: Node
|
|
};
|
|
|
|
fn contains(list: []Node, x: Node) bool {
|
|
for (list) |node| {
|
|
if (std.mem.eql(u8, node, x)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
fn getOther(edge: Edge, node: Node) ?Node {
|
|
if (std.mem.eql(u8, edge.left, node)) {
|
|
return edge.right;
|
|
}
|
|
if (std.mem.eql(u8, edge.right, node)) {
|
|
return edge.left;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
fn isSmol(node: Node) bool {
|
|
for (node) |rune| {
|
|
if (!std.ascii.isLower(rune)) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
pub fn main() !void {
|
|
var alloc = std.heap.GeneralPurposeAllocator(.{}){};
|
|
defer std.debug.assert(!alloc.deinit());
|
|
var gpa = &alloc.allocator;
|
|
|
|
const stdin = std.io.getStdIn().reader();
|
|
|
|
var res: u32 = 0;
|
|
|
|
var edges = std.ArrayList(Edge).init(gpa);
|
|
defer edges.deinit();
|
|
|
|
var input = try stdin.readAllAlloc(gpa, 4096);
|
|
defer gpa.free(input);
|
|
|
|
var lines = std.mem.split(input, "\n");
|
|
while (lines.next()) |line| {
|
|
var it = std.mem.split(line, "-");
|
|
var left = it.next() orelse unreachable;
|
|
var right = it.next() orelse unreachable;
|
|
|
|
try edges.append(Edge{
|
|
.left = left,
|
|
.right = right,
|
|
});
|
|
}
|
|
|
|
var routes = std.ArrayList(Route).init(gpa);
|
|
defer {
|
|
for (routes.items) |route| {
|
|
route.deinit();
|
|
}
|
|
routes.deinit();
|
|
}
|
|
{
|
|
var route = Route.init(gpa);
|
|
try route.append("start");
|
|
try routes.append(route);
|
|
}
|
|
|
|
// var x: u8 = 0;
|
|
|
|
while (true) {
|
|
var cont = false;
|
|
|
|
var newRoutes = std.ArrayList(Route).init(gpa);
|
|
defer newRoutes.deinit();
|
|
|
|
var stale = std.ArrayList(usize).init(gpa);
|
|
defer stale.deinit();
|
|
|
|
// print("Routes ({}):\n", .{routes.items.len});
|
|
// for (routes.items) |route| {
|
|
// print("{s}\n", .{route.items});
|
|
// }
|
|
|
|
for (routes.items) |route, i| {
|
|
const last = route.items[route.items.len - 1];
|
|
if (std.mem.eql(u8, last, "end")) {
|
|
continue;
|
|
}
|
|
cont = true;
|
|
try stale.append(i);
|
|
|
|
for (edges.items) |edge| {
|
|
if (getOther(edge, last)) |other| {
|
|
// print("> {s}\n", .{other});
|
|
if (isSmol(other) and contains(route.items, other)) {
|
|
continue;
|
|
} else {
|
|
var newRoute = Route.init(gpa);
|
|
try newRoute.appendSlice(route.items);
|
|
try newRoute.append(other);
|
|
// print("new route: {s}\n", .{newRoute.items});
|
|
try newRoutes.append(newRoute);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var i: usize = 0;
|
|
while (i < stale.items.len) : (i += 1) {
|
|
var route = routes.orderedRemove(stale.items[stale.items.len-1-i]);
|
|
route.deinit();
|
|
}
|
|
|
|
try routes.appendSlice(newRoutes.items);
|
|
|
|
if (!cont) break;
|
|
}
|
|
|
|
std.debug.print("{}\n", .{routes.items.len});
|
|
}
|