diff --git a/2020.csproj b/2020.csproj
index f2f965e..0763a40 100644
--- a/2020.csproj
+++ b/2020.csproj
@@ -71,6 +71,9 @@
PreserveNewest
+
+ PreserveNewest
+
diff --git a/23input.txt b/23input.txt
new file mode 100644
index 0000000..88666bb
--- /dev/null
+++ b/23input.txt
@@ -0,0 +1 @@
+538914762
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
index 8bc120b..5bdc916 100644
--- a/Program.cs
+++ b/Program.cs
@@ -25,6 +25,7 @@
Q20.Go();
Q21.Go();
Q22.Go();
+ Q23.Go();
Util.Log($"Total time={(System.DateTime.Now - start).TotalMilliseconds}ms");
}
}
diff --git a/Q23.cs b/Q23.cs
new file mode 100644
index 0000000..b2078dc
--- /dev/null
+++ b/Q23.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace _2020
+{
+ class Q23
+ {
+ static readonly List list = new List();
+
+ public static void Go()
+ {
+ var start = DateTime.Now;
+ MakeList();
+ Util.Log($"Q23 MakeList took {(DateTime.Now - start).TotalMilliseconds}ms");
+ var p1start = DateTime.Now;
+ Part1();
+ Util.Log($"Q23 part1 took {(DateTime.Now - p1start).TotalMilliseconds}ms");
+ var p2start = DateTime.Now;
+ Part2();
+ Util.Log($"Q23 part2 took {(DateTime.Now - p2start).TotalMilliseconds}ms");
+
+ Util.Log($"Q23 took {(DateTime.Now - start).TotalMilliseconds}ms");
+ }
+
+ static void MakeList()
+ {
+ var text = File.ReadAllText("23input.txt");
+ foreach (var ch in text)
+ {
+ list.Add(Convert.ToInt32(ch.ToString()));
+ }
+ }
+
+ static int mod(int x, int m)
+ {
+ int r = x;
+ if (r >= x)
+ {
+ r = x % m;
+ }
+ return r < 0 ? r + m : r;
+ }
+
+ static void Part1()
+ {
+ var cupList = new List(list);
+ var currentCupVal = cupList[0];
+ var currentCupIdx = 0;
+ var pickedUp = new int[3];
+ for (int move = 0; move < 100; move++)
+ {
+ for (int i = currentCupIdx + 1, pickedUpIdx = 0; pickedUpIdx < 3; pickedUpIdx++)
+ {
+ if (i >= cupList.Count)
+ {
+ i = 0;
+ }
+
+ pickedUp[pickedUpIdx] = cupList[i];
+ cupList.RemoveAt(i);
+ }
+
+ var destCupVal = currentCupVal - 1;
+ var destCupIdx = cupList.IndexOf(destCupVal);
+ while (destCupIdx < 0)
+ {
+ destCupVal = mod(destCupVal - 1, cupList.Count + pickedUp.Length + 1);
+ destCupIdx = cupList.IndexOf(destCupVal);
+ }
+
+ cupList.InsertRange(destCupIdx + 1, pickedUp);
+ currentCupVal = cupList[mod(cupList.IndexOf(currentCupVal) + 1, cupList.Count)];
+ currentCupIdx = cupList.IndexOf(currentCupVal);
+ }
+
+ var startIdx = cupList.IndexOf(1);
+ var scoreStr = "";
+ for (var idx = startIdx + 1; scoreStr.Length < cupList.Count - 1; idx++)
+ {
+ scoreStr += cupList[idx % cupList.Count].ToString();
+ }
+
+ Util.Log($"Q23Part1: labels={scoreStr}");
+ }
+
+ static void Part2()
+ {
+ var cupList = new List(list);
+ var highestVal = cupList.Aggregate(0, (result, curr) => curr > result ? curr : result);
+ for (int i = cupList.Count, next = highestVal + 1; i < 1000000; i++, next++)
+ {
+ cupList.Add(next);
+ }
+
+ var currentCupVal = cupList[0];
+ var currentCupIdx = 0;
+ var pickedUp = new int[3];
+ var start = DateTime.Now;
+ var lastMove = 0;
+ for (int move = 0; move < 10000000; move++)
+ {
+ for (int i = currentCupIdx + 1, pickedUpIdx = 0; pickedUpIdx < 3; pickedUpIdx++)
+ {
+ if (i >= cupList.Count)
+ {
+ i = 0;
+ }
+
+ pickedUp[pickedUpIdx] = cupList[i];
+ cupList.RemoveAt(i);
+ }
+
+ var destCupVal = currentCupVal - 1;
+ var destCupIdx = cupList.IndexOf(destCupVal);
+ while (destCupIdx < 0)
+ {
+ destCupVal = mod(destCupVal - 1, cupList.Count + pickedUp.Length + 1);
+ destCupIdx = cupList.IndexOf(destCupVal);
+ }
+
+ cupList.InsertRange(destCupIdx + 1, pickedUp);
+ currentCupVal = cupList[mod(cupList.IndexOf(currentCupVal) + 1, cupList.Count)];
+ currentCupIdx = cupList.IndexOf(currentCupVal);
+
+ var dt = DateTime.Now - start;
+ var dtSeconds = dt.TotalSeconds;
+ if (dtSeconds >= 1.0)
+ {
+ start = DateTime.Now;
+ var rate = (move - lastMove) / dtSeconds;
+ lastMove = move;
+ var remainingMoves = 10000000 - move;
+ var endTime = DateTime.Now + TimeSpan.FromSeconds(remainingMoves / rate);
+ Util.Log($"Current rate: {rate:N1} mps, {remainingMoves:N} moves remaining. Should be done by {endTime}");
+ }
+ }
+
+ var oneIdx = cupList.IndexOf(1);
+ Util.Log($"Q23Part2: next two={cupList[(oneIdx + 1) % cupList.Count]}, {cupList[(oneIdx + 2) % cupList.Count]}, multiplied={1L * cupList[(oneIdx + 1) % cupList.Count] * cupList[(oneIdx + 2) % cupList.Count]}");
+ }
+ }
+}