// See https://aka.ms/new-console-template for more information using System.Numerics; var exampleData = new ProblemData("example-input.txt"); Console.WriteLine("Grove Coordinates, Example: " + exampleData.GetGroveCoordinates(1,1)); var puzzleData = new ProblemData("puzzle-input.txt"); Console.WriteLine("Grove Coordinates, Puzzle: " + puzzleData.GetGroveCoordinates(1,1)); Console.WriteLine("Grove Coordinates, Example Decrypted: " + exampleData.GetGroveCoordinates(811589153, 10)); Console.WriteLine("Grove Coordinates, Puzzle Decrypted: " + puzzleData.GetGroveCoordinates(811589153, 10)); class Item { public Item(BigInteger value) { Value = value; } public BigInteger Value { get; set; } public override string ToString() { return Value.ToString(); } } class CircularList { public List Items; public CircularList() { Items = new List(); } public void Add(Item item) { Items.Add(item); } public void Move(int oldIndex, int newIndex) { if (oldIndex == newIndex) return; var temp = Items[oldIndex]; if (newIndex == 0) { Items.RemoveAt(oldIndex); Items.Add(temp); } else if (newIndex == Items.Count - 1) { Items.RemoveAt(oldIndex); Items.Insert(0, temp); } else { Items.RemoveAt(oldIndex); Items.Insert(newIndex, temp); } } public static void PrintList(CircularList list) { for (int ci = 0; ci < list.Items.Count; ci++) { if (ci != 0) Console.Write(", "); Console.Write(list.Items[ci]); } Console.WriteLine(); } public static CircularList GetMixedList(CircularList source, BigInteger decryptionKey, int mixes) { var newList = new CircularList(); for (int i = 0; i < source.Items.Count; i++) { source.Items[i].Value *= decryptionKey; newList.Items.Add(source.Items[i]); } for (int mixNum = 0; mixNum < mixes; mixNum++) { if (DebugPrint) Console.WriteLine("Starting mix {0} of {1}", mixNum + 1, mixes); for (int i = 0; i < source.Items.Count; i++) { if (DebugPrint) Console.WriteLine("|- Mixing item {0} of {1}", i + 1, source.Items.Count); var item = source.Items[i]; int currentIndex = newList.Items.IndexOf(item); int direction = item.Value > 0 ? 1 : -1; int newIndex = currentIndex; BigInteger max = BigInteger.Abs(item.Value) % (source.Items.Count-1); for (BigInteger j = 0; j < max; j++) { if (direction == 1 && newIndex == source.Items.Count - 1) newIndex = 1; else if (direction == -1 && newIndex == 0) newIndex = source.Items.Count - 2; else newIndex += direction; } newList.Move(currentIndex, newIndex); } } return newList; } public static bool DebugPrint { get; set; } = false; } class ProblemData { private CircularList Numbers { get; set; } public CircularList GetMixedList(BigInteger decryptionKey, int mixes) { return CircularList.GetMixedList(Numbers, decryptionKey, mixes); } public BigInteger GetGroveCoordinates(BigInteger decryptionKey, int mixes) { BigInteger sum = 0; var list = GetMixedList(decryptionKey, mixes); int index = list.Items.FindIndex(x => x.Value == 0); for (int i = 0; i <= 3000; i++) { if (i % 1000 == 0) { sum += list.Items[index].Value; } if (index == list.Items.Count-1) { index = 0; } else { index++; } } return sum; } public ProblemData(string filename) { Numbers = new CircularList(); using (StreamReader reader = System.IO.File.OpenText(filename)) { while (!reader.EndOfStream) { var line = reader.ReadLine(); if (line == null) throw new InvalidDataException(); var value = Int32.Parse(line); Numbers.Add(new Item(value)); } } } }