// 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 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 packetPairs) { int sum = 0, index = 1; foreach (var packet in packetPairs) { if (packet.IsCorrectlyOrdered()) sum += index; index++; } return sum; } void InsertDividers(List packets) { PacketPair pair = GetDividers(); packets.Add(pair.Data.Item1); packets.Add(pair.Data.Item2); } PacketPair GetDividers() { return new PacketPair("[[2]]", "[[6]]"); } void PrintPacketPairs(List 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 ReadPackets(string filename) { List packets = new List(); 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 ReadPacketPairs(string filename) { List packets = new List(); 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(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 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 Values { get; set;} = new List(); 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; } }