protected override object SolvePart1() { var nodes = new List <RecursiveCircusNode>(); foreach (var line in Input) { var splits = line.Split(new[] { "->" }, StringSplitOptions.None); var node = new RecursiveCircusNode { Name = splits[0].Split()[0], Weight = int.Parse(splits[0].Split()[1].Trim().Trim('(', ')'), CultureInfo.InvariantCulture) }; if (splits.Length == 2) { node.ChildNodes.AddRange(splits[1].Trim().Split().Select(c => c.Trim(',')).ToList()); } nodes.Add(node); } var children = nodes.Where(n => n.ChildNodes.Count > 0).SelectMany(n => n.ChildNodes); return(nodes.Single(n => !children.Contains(n.Name)).Name); }
protected override object SolvePart2() { // Create all nodes. var nodes = new List <RecursiveCircusNode>(); foreach (var line in Input) { var splits = line.Split(new[] { "->" }, StringSplitOptions.None); var node = new RecursiveCircusNode { Name = splits[0].Split()[0], Weight = int.Parse(splits[0].Split()[1].Trim().Trim('(', ')'), CultureInfo.InvariantCulture) }; if (splits.Length == 2) { node.ChildNodes.AddRange(splits[1].Trim().Split().Select(c => c.Trim(',')).ToList()); } nodes.Add(node); } // Build tree foreach (var node in nodes) { foreach (var child in node.ChildNodes) { node.Children.Add(nodes.Single(n => n.Name == child)); } node.Children.ForEach(n => n.Parent = node); } // Get root node (the only one that isn't a child to another node. var children = nodes.Where(n => n.ChildNodes.Count > 0).SelectMany(n => n.ChildNodes); var rootNode = nodes.Single(n => !children.Contains(n.Name)); // Traverse tree to find the faulty weight. var currentNode = rootNode; var lastDiff = 0; while (currentNode != null) { var childWeights = currentNode.GetChildWeights(); var diff = childWeights.Distinct().Max() - childWeights.Distinct().Min(); if (diff == 0) { return(currentNode.Weight - lastDiff); } lastDiff = diff; var unique = childWeights.Single(n => childWeights.Count(m => m == n) == 1); currentNode = currentNode.Children.Single(n => n.GetTowerWeight() == unique); } return(null); }