#define Day21 using System.Diagnostics; using System.Threading.Channels; using AoC2021; #if Day21 var states = File.ReadAllLines("day21/input") .Select(l => new State() {pos = int.Parse(l[l.Length-1].ToString()) - 1, score = 0}) .ToList(); // states = new List() { // new State() {pos = 3, score = 0}, // new State() {pos = 7, score = 0}, // }; var states2 = states.Select(s => s.Copy()).ToList(); var bla = Enumerable.Range(1, 3).SelectMany(x => Enumerable.Range(1, 3).SelectMany(y => Enumerable.Range(1, 3).Select(z => new {x = x, y = y, z = z}))) .Select(p => p.x + p.y + p.z).GroupBy(x => x).ToDictionary(x => x.Key, x => x.Count()); //ForEachAsList(p => Console.WriteLine(p)); bla.ForEachAsList(b => Console.WriteLine($"{b.Key}: {b.Value}")); // System.Environment.Exit(0); int curPlayer = 0; int dieThrows = 0; int deterministic = 99; while (states[GetOtherPlayer(curPlayer)].score < 1000) { dieThrows += 3; var sumDie = GetDeterministic100Die().Take(3).Sum(); states[curPlayer].pos += sumDie; states[curPlayer].pos %= 10; states[curPlayer].score += states[curPlayer].pos + 1; curPlayer = GetOtherPlayer(curPlayer); } var minScore = states.Select(s => s.score).Min(); Console.WriteLine(minScore * dieThrows); //------------------ Stopwatch sw = new Stopwatch(); sw.Start(); Stack stack = new Stack(); stack.Push(new CompleteState(0, new StateRec(states2[0].pos, states2[0].score), new StateRec(states2[1].pos, states2[1].score), 1)); long countWin0 = 0; long countWin1 = 0; while (stack.Count > 0) { (int cur, StateRec p0, StateRec p1, long winTimes) = stack.Pop(); StateRec curP = cur == 0 ? p0 : p1; AddState(Add(curP, 3), cur, p0, p1, winTimes * 1); AddState(Add(curP, 4), cur, p0, p1, winTimes * 3); AddState(Add(curP, 5), cur, p0, p1, winTimes * 6); AddState(Add(curP, 6), cur, p0, p1, winTimes * 7); AddState(Add(curP, 7), cur, p0, p1, winTimes * 6); AddState(Add(curP, 8), cur, p0, p1, winTimes * 3); AddState(Add(curP, 9), cur, p0, p1, winTimes * 1); } sw.Stop(); Console.WriteLine(sw.Elapsed); Console.WriteLine(countWin0); Console.WriteLine(countWin1); StateRec Add(StateRec s, int die) { int newPos = (s.pos + die) % 10; return new StateRec(newPos, s.score + newPos + 1); } IEnumerable GetDeterministic100Die() { while (true) { deterministic = (deterministic + 1) % 100; yield return deterministic + 1; } } int GetOtherPlayer(int player) => player == 0 ? 1 : 0; void AddState(StateRec stateRec, int curPlayer, StateRec p0, StateRec p1, long winTimes) { if (stateRec.score >= 21) { if (curPlayer == 0) { countWin0 += winTimes; } else { countWin1 += winTimes; } } else { if (curPlayer == 0) { stack.Push(new CompleteState(GetOtherPlayer(curPlayer), stateRec, p1, winTimes)); } else { stack.Push(new CompleteState(GetOtherPlayer(curPlayer), p0, stateRec, winTimes)); } } } class State { public int pos { get; set; } public int score { get; set; } public State Copy() { return new State() {pos = pos, score = score}; } public override string ToString() { return $"Pos: {pos}, Score: {score}"; } } record StateRec(int pos, int score); record CompleteState(int curPlayer, StateRec player0, StateRec player1, long winTimes); #endif