const std = @import("std"); const Link = struct { a: [3]u8 = [3]u8{ 0, 0, 0 }, b: [3]u8 = [3]u8{ 0, 0, 0 }, }; const Node = struct { name: [3]u8 = [3]u8{ 0, 0, 0 }, depth: u32 = 0, parent: ?*Node, }; const Links = std.ArrayList(Link); const Nodes = std.StringHashMap(*Node); fn parse(alloc: *std.mem.Allocator, stream: *std.fs.File.InStream.Stream) !Links { var list: Links = Links.init(alloc); var buf: [8]u8 = undefined; var i: u32 = 0; while (try stream.readUntilDelimiterOrEof(&buf, '\n')) |line| { std.debug.assert(line.len == 7 and line[3] == ')'); std.debug.warn("{}\n", line); var out: Link = Link{}; std.mem.copy(u8, &out.a, line[0..3]); std.mem.copy(u8, &out.b, line[4..7]); try list.append(out); } return list; } fn getOrCreateNode(alloc: *std.mem.Allocator, nodes: var, name: [3]u8) !*Node { if (nodes.get(name)) |kv| { return kv.value; } else { var node: *Node = try alloc.create(Node); node.parent = null; node.depth = 0; std.mem.copy(u8, &node.name, name); var kv = try nodes.put(name, node); return node; } } pub fn main() anyerror!void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const alloc = &arena.allocator; const file = std.io.getStdIn(); const stream = &file.inStream().stream; var links = try parse(alloc, stream); std.debug.warn("Part 1: {} links\n", links.len); // name -> node var nodes = Nodes.init(alloc); // The input isn't ordered, so we need to pass over it several times // Pass 1: create all nodes for (links.toSlice()) |link| { var a = try getOrCreateNode(alloc, &nodes, link.a); var b = try getOrCreateNode(alloc, &nodes, link.b); } // Pass 2: link all nodes to their parents for (links.toSlice()) |link| { var a = try getOrCreateNode(alloc, &nodes, link.a); var b = try getOrCreateNode(alloc, &nodes, link.b); std.debug.warn("\t{} ) {}\n", a.name, b.name); std.debug.assert(b.parent == null); b.parent = a; } // Pass 3: The tree is fully constructed, so we can count parents var count: u32 = 0; var iter = nodes.iterator(); while (iter.next()) |kv| { var node = kv.value; // Count number of orbits var n: *Node = node; while (n.parent) |p| { node.depth += 1; n = p; } count += node.depth; } std.debug.warn("Part 1: {}\n", count); }