103 lines
3.1 KiB
C#
103 lines
3.1 KiB
C#
// #define Day21
|
|
#if Day21
|
|
using AoC2021;
|
|
|
|
var states = File.ReadAllLines("day21/input")
|
|
.Select(l => new State() {pos = int.Parse(l[l.Length-1].ToString()) - 1, score = 0})
|
|
.ToList();
|
|
|
|
var states2 = states.Select(s => s.Copy()).ToList();
|
|
|
|
var diceCombinations = 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());
|
|
diceCombinations.ForEachAsList(b => Console.WriteLine($"{b.Key}: {b.Value}"));
|
|
|
|
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);
|
|
|
|
|
|
//------------------
|
|
|
|
Stack<CompleteState> stack = new Stack<CompleteState>();
|
|
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);
|
|
}
|
|
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<int> 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 |