Files
AdventOfCode/2022/Day13CSharp/Program.cs
2025-11-30 20:28:10 -05:00

335 lines
8.6 KiB
C#

// See https://aka.ms/new-console-template for more information
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Markup;
Part01();
Console.WriteLine();
Part02();
void Part01()
{
Console.WriteLine("!! === Part 1 === !!");
Console.WriteLine(" === Example Data ===");
var examplePackets = ReadPacketPairs("example-input.txt");
//PrintPackets(examplePackets);
Console.WriteLine("Sum of combined pair indices: " + GetSumOfOrderedPairs(examplePackets));
Console.WriteLine(" === Puzzle Data ===");
var puzzlePackets = ReadPacketPairs("puzzle-input.txt");
//PrintPackets(puzzlePackets);
Console.WriteLine("Sum of combined pair indices: " + GetSumOfOrderedPairs(puzzlePackets));
}
void Part02()
{
Console.WriteLine("!! === Part 2 === !!");
Console.WriteLine(" === Example Data ===");
var examplePackets = ReadPackets("example-input.txt");
InsertDividers(examplePackets);
examplePackets.Sort();
PrintPart02Sln(examplePackets);
Console.WriteLine(" === Puzzle Data ===");
var puzzlePackets = ReadPackets("puzzle-input.txt");
InsertDividers(puzzlePackets);
puzzlePackets.Sort();
PrintPart02Sln(puzzlePackets);
}
void PrintPart02Sln(List<IComparable> packets)
{
var dividers = GetDividers();
int first = -1;
int second = -1;
int index = 1;
foreach (var packet in packets)
{
if (packet.CompareTo(dividers.Data.Item1) == 0) first = index;
if (packet.CompareTo(dividers.Data.Item2) == 0) second = index;
index++;
}
Console.WriteLine("Dividers at {0} and {1}. Key: {2}", first, second, first * second);
}
int GetSumOfOrderedPairs(List<PacketPair> packetPairs)
{
int sum = 0, index = 1;
foreach (var packet in packetPairs)
{
if (packet.IsCorrectlyOrdered()) sum += index;
index++;
}
return sum;
}
void InsertDividers(List<IComparable> packets)
{
PacketPair pair = GetDividers();
packets.Add(pair.Data.Item1);
packets.Add(pair.Data.Item2);
}
PacketPair GetDividers()
{
return new PacketPair("[[2]]", "[[6]]");
}
void PrintPacketPairs(List<PacketPair> packets)
{
Console.WriteLine("- Printing packets -");
foreach (var packet in packets) Console.WriteLine(String.Format("{0} {1} correctly ordered.", packet.ToString(), packet.IsCorrectlyOrdered() ? "is" : "is NOT"));
//foreach (var packet in packets)
//{
// Console.WriteLine(packet.Data.Item1.ToString());
// Console.WriteLine(packet.Data.Item2.ToString());
// Console.WriteLine();
//}
Console.WriteLine("- Done -");
}
List<IComparable> ReadPackets(string filename)
{
List<IComparable> packets = new List<IComparable>();
foreach (var pair in ReadPacketPairs(filename))
{
if (pair == null) throw new InvalidDataException();
packets.Add(pair.Data.Item1);
packets.Add(pair.Data.Item2);
}
return packets;
}
List<PacketPair> ReadPacketPairs(string filename)
{
List<PacketPair> packets = new List<PacketPair>();
using (StreamReader reader = System.IO.File.OpenText(filename))
{
while (!reader.EndOfStream)
{
// Read the next two lines
string? left = reader.ReadLine();
string? right = reader.ReadLine();
if (left == null || right == null) throw new InvalidDataException();
packets.Add(new PacketPair(left, right));
// Read the empty line
reader.ReadLine();
}
}
return packets;
}
class PacketPair
{
public PacketPair(string dataLeft, string dataRight)
{
ListData left = Parse(dataLeft);
ListData right = Parse(dataRight);
Data = new Tuple<IComparable, IComparable>(left, right);
}
private int Parse(ListData list, string data, int currentIndex)
{
if (data[currentIndex] != '[') throw new InvalidDataException();
for (int i = currentIndex+1; i < data.Length; i++)
{
if (data[i] == ',') continue;
if (data[i] == '[')
{
ListData newList = new ListData();
// Found a list
i = Parse(newList, data, i);
list.Values.Add(newList);
}
else if (Char.IsDigit(data[i]))
{
int strlen = 0;
for (int j = i; Char.IsDigit(data[j]); j++,strlen++);
list.Values.Add(new IntegerData(Int32.Parse(data.Substring(i, strlen))));
while (data[i] != ',' && data[i] != ']') i++;
if (data[i] == ',')
{
// Move to the next piece of data
continue;
}
else if (data[i] == ']')
{
// We're done with the values of this object, we can exit
return i;
}
}
else if (data[i] == ']')
{
return i;
}
}
throw new InvalidDataException();
}
private ListData Parse(string data)
{
ListData list = new ListData();
Parse(list, data, 0);
return list;
}
public Tuple<IComparable, IComparable> Data {get; set;}
public bool IsCorrectlyOrdered()
{
return Data.Item1.CompareTo(Data.Item2) <= 0;
}
public override string ToString()
{
return Data.Item1.ToString() + " vs " + Data.Item2.ToString();
}
}
class IntegerData : IComparable
{
public IntegerData(int value)
{
Value = value;
}
public int Value { get; set;}
public int CompareTo(object? right)
{
var integerData = right as IntegerData;
var listData = right as ListData;
if (integerData != null)
{
return Value.CompareTo(integerData.Value);
}
else if (listData != null)
{
ListData leftList = new ListData();
leftList.Values.Add(this);
return leftList.CompareTo(listData);
}
else
{
throw new InvalidDataException();
}
}
public override string ToString()
{
return Value.ToString();
}
}
class ListData : IComparable
{
public List<IComparable> Values { get; set;} = new List<IComparable>();
public int CompareTo(object? obj)
{
var integerData = obj as IntegerData;
var listData = obj as ListData;
if (integerData != null)
{
ListData rightList = new ListData();
rightList.Values.Add(integerData);
return CompareLists(this, rightList);
}
else if (listData != null)
{
return CompareLists(this, listData);
}
else
{
throw new InvalidDataException();
}
}
int CompareLists(ListData left, ListData right)
{
if (left.Values.Count == 0 && right.Values.Count == 0)
{
return 0;
}
else if (left.Values.Count == 0)
{
return -1;
}
else if (left.Values.Count > 0 && right.Values.Count == 0)
{
return 1;
}
else
{
for (int i = 0; ; i++)
{
if (i < left.Values.Count && i < right.Values.Count)
{
var result = left.Values[i].CompareTo(right.Values[i]);
if (result != 0) return result;
}
else if (i == left.Values.Count && i == right.Values.Count)
{
return 0;
}
else if (i >= left.Values.Count)
{
return -1;
}
else if (i >= right.Values.Count)
{
return 1;
}
else
{
throw new InvalidOperationException();
}
}
}
}
public override string ToString()
{
string str = "";
str += '[';
for (int i = 0; i < Values.Count; i++)
{
if (i > 0) str += ',';
str += Values[i].ToString();
}
str += "]";
return str;
}
}