Add day 23
This commit is contained in:
172
Days/Day23.cs
Normal file
172
Days/Day23.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
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<string, HashSet<string>>();
|
||||
|
||||
// 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<ComputerSet>();
|
||||
|
||||
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<string, HashSet<string>>();
|
||||
|
||||
// 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<string> 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<string>? GenerateLargestSet(HashSet<string> set, int targetSize, List<string> 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<ComputerSet>
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
3380
Inputs/Day23.txt
Normal file
3380
Inputs/Day23.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user