using System.Collections.Frozen; using System.Numerics; using System.Runtime.Intrinsics.X86; using System.Text; using Spectre.Console; namespace AdventOfCode.Days; public class Day23 : Day { public override int Number => 23; public override string Name => "LAN Party"; public override void RunPart1(bool display = true) { var computerLinks = new Dictionary>(); // Parse all links foreach (var line in Input.AsSpan().EnumerateLines()) { var firstComputer = line[..2].ToString(); var secondComputer = line[3..].ToString(); if (!computerLinks.TryGetValue(firstComputer, out var firstLinks)) { firstLinks = []; computerLinks[firstComputer] = firstLinks; } firstLinks.Add(secondComputer); if (!computerLinks.TryGetValue(secondComputer, out var secondLinks)) { secondLinks = []; computerLinks[secondComputer] = secondLinks; } secondLinks.Add(firstComputer); } var sets = new HashSet(); foreach (var (firstComputer, firstLinks) in computerLinks) { foreach (var secondComputer in firstLinks) { var thirdComputers = computerLinks[secondComputer].Intersect(firstLinks); foreach (var thirdComputer in thirdComputers) { sets.Add(new ComputerSet(firstComputer, secondComputer, thirdComputer)); } } } var finalCount = sets.Count(set => set.First.StartsWith('t') || set.Second.StartsWith('t') || set.Third.StartsWith('t')); if (display) { AnsiConsole.MarkupLine($"[green]Amount of sets that contain at least one computer that starts with t: [yellow]{finalCount}[/][/]"); } } public override void RunPart2(bool display = true) { var computerLinks = new Dictionary>(); // Parse all links foreach (var line in Input.AsSpan().EnumerateLines()) { var firstComputer = line[..2].ToString(); var secondComputer = line[3..].ToString(); if (!computerLinks.TryGetValue(firstComputer, out var firstLinks)) { firstLinks = []; computerLinks[firstComputer] = firstLinks; } firstLinks.Add(secondComputer); if (!computerLinks.TryGetValue(secondComputer, out var secondLinks)) { secondLinks = []; computerLinks[secondComputer] = secondLinks; } secondLinks.Add(firstComputer); } List largestSet = []; AnsiConsole.Status().Start("Starting check...", status => { var size = 4; while (true) { var ended = true; status.Status($"Checking set size: {size}"); var i = 0; foreach (var (firstComputer, firstLinks) in computerLinks) { status.Status($"Checking set size: {size} ({i++}/{computerLinks.Count})"); if (GenerateLargestSet(firstLinks, size, [ firstComputer ]) is { } largest) { largestSet = largest; size++; ended = false; break; } } if (ended) { break; } } }); var password = string.Join(',', largestSet.Order()); if (display) { AnsiConsole.MarkupLine($"[green]Password to enter lan party: [yellow]{password}[/][/]"); } return; List? GenerateLargestSet(HashSet set, int targetSize, List selected) { if (selected.Count == targetSize) { return selected; } if (set.Count is 0 || (set.Count < (targetSize - selected.Count))) { return null; } // Next depth foreach (var computer in set) { var nextSet = set.Intersect(computerLinks[computer]).ToHashSet(); var nextSelected = selected.Append(computer).ToList(); if (GenerateLargestSet(nextSet, targetSize, nextSelected) is { } largest) { return largest; } } return null; } } private record ComputerSet(string First, string Second, string Third) : IEquatable { public virtual bool Equals(ComputerSet? other) { return other is not null && (First == other.First || First == other.Second || First == other.Third) && (Second == other.First || Second == other.Second || Second == other.Third) && (Third == other.First || Third == other.Second || Third == other.Third); } public override int GetHashCode() { return First.GetHashCode() * Second.GetHashCode() * Third.GetHashCode(); } } }