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}); }