/// <summary> /// print what the circle looks like right now /// </summary> /// <param name="player">The player who just made a turn</param> /// <param name="firstMarble">The first marble in the circle.</param> /// <param name="currentMarble">The current active marble</param> private static void printCircle(Player player, Marble firstMarble, Marble currentMarble) { if (player == null) { Console.Write("[---] "); } else { Console.Write($"[{player.Number:000}] "); } var printingMarble = firstMarble; do { if (printingMarble == currentMarble) { Console.Write($"({printingMarble.Score})"); } else { Console.Write($" {printingMarble.Score} "); } printingMarble = printingMarble.Next; } while (printingMarble != firstMarble); Console.WriteLine(String.Empty); }
/// <summary> /// Inserts a marble longo the next position /// </summary> /// <param name="marble"></param> public void Insert(Marble marble) { Next.Previous = marble; marble.Next = Next; marble.Previous = this; Next = marble; }
internal void InsertCW(Marble newMarble) { var oldCw = CW; this.CW = newMarble; newMarble.CCW = this; oldCw.CCW = newMarble; newMarble.CW = oldCw; }
/// <summary> /// Return the marble a certain number of marbles previous to this one /// </summary> /// <param name="currentMarble">The marble to count back from</param> /// <param name="thisManyBack">The number of marbles to count back</param> /// <returns>The marble</returns> private static Marble GetMarblesBack(Marble currentMarble, long thisManyBack) { Marble ret = currentMarble; for (long i = 0; i < thisManyBack; i++) { ret = ret.Previous; } return(ret); }
/// <summary> /// Play the game /// </summary> /// <param name="playerCount">The number of players playing</param> /// <param name="lastMarble">How many marbles</param> /// <param name="printMoves">flag to say ig it should print each move or not</param> /// <returns>The highest score of any of the players once the game has completed</returns> public static (long player, long score) PlayGame(long playerCount, long lastMarble, bool printMoves = false) { //let's start with marble 0; it's a single marble circle. var currentMarble = new Marble(0); var firstMarble = currentMarble; var players = CreatePlayers(playerCount); long currentPlayer = 0; if (printMoves) { printCircle(null, firstMarble, currentMarble); } //for each marble, in order for (long marbleNumber = 1; marbleNumber <= lastMarble; marbleNumber++) { //get the next marble var nextMarble = new Marble(marbleNumber); if (nextMarble.IsScoringMarble) { //do the scoring logic players[currentPlayer].OwnedMarbles.Add(nextMarble); nextMarble = GetMarblesBack(currentMarble, 7); currentMarble = nextMarble.Next; nextMarble = nextMarble.Previous.RemoveNext(); players[currentPlayer].OwnedMarbles.Add(nextMarble); } else { currentMarble.Next.Insert(nextMarble); currentMarble = nextMarble; } if (printMoves) { printCircle(players[currentPlayer], firstMarble, currentMarble); } //find the next player currentPlayer = GetNextPlayerIndex(currentPlayer, playerCount); } //game over, who's got the highest score? var highscore = players.Max(x => x.OwnedMarbles.Sum(y => y.Score)); var winner = players.First(x => x.MarbleScore == highscore).Number; return(winner, highscore); }
static void Main(string[] args) { using (var sr = new StreamReader("input.txt")) { var input = sr.ReadToEnd(); var regex = new Regex(@"(?<numberOfPlayers>\d+) .* worth (?<lastMarbleValue>\d+)"); var match = regex.Match(input); int numberOfPlayers = int.Parse(match.Groups["numberOfPlayers"].Value); int lastMarbleValue = int.Parse(match.Groups["lastMarbleValue"].Value); var players = new List <Player>(); for (int i = 1; i <= numberOfPlayers; i++) { players.Add(new Player(i)); } var marbles = new LinkedList <Marble>(); var firstMarble = new Marble(0); var currentMarbleNode = marbles.AddFirst(firstMarble); for (int currentMarbleNumber = 1; currentMarbleNumber <= lastMarbleValue; currentMarbleNumber++) { if (currentMarbleNumber % 23 == 0) { var playerGettingPoints = players.ElementAt(currentMarbleNumber % numberOfPlayers); var marbleToDelete = GoBack7(marbles, currentMarbleNode); playerGettingPoints.NumberOfPoints += currentMarbleNumber + marbleToDelete.Value.Value; currentMarbleNode = marbleToDelete.Next ?? marbles.First; marbles.Remove(marbleToDelete); } else { var marbleToInsertAfter = currentMarbleNode.Next ?? marbles.First; currentMarbleNode = marbles.AddAfter(marbleToInsertAfter, new Marble(currentMarbleNumber)); } } //Excercise 1 Console.WriteLine($"Excercise 1 - max score: {players.Max(x => x.NumberOfPoints)}"); for (int currentMarbleNumber = lastMarbleValue + 1; currentMarbleNumber <= lastMarbleValue * 100; currentMarbleNumber++) { if (currentMarbleNumber % 23 == 0) { var playerGettingPoints = players.ElementAt(currentMarbleNumber % numberOfPlayers); var marbleToDelete = GoBack7(marbles, currentMarbleNode); playerGettingPoints.NumberOfPoints += currentMarbleNumber + marbleToDelete.Value.Value; currentMarbleNode = marbleToDelete.Next ?? marbles.First; marbles.Remove(marbleToDelete); } else { var marbleToInsertAfter = currentMarbleNode.Next ?? marbles.First; currentMarbleNode = marbles.AddAfter(marbleToInsertAfter, new Marble(currentMarbleNumber)); } } //Excercise 2 Console.WriteLine($"Excercise 2 - max score: {players.Max(x => x.NumberOfPoints)}"); } }
public static long A(int numPlayers, int maxMarble) { long[] scores = new long[numPlayers]; int currentPlayer = 0; //first marble Marble current = new Marble(0); current.CW = current; current.CCW = current; // the rest of the marbles for (int marble = 1; marble <= maxMarble; marble++) { var newMarble = new Marble(marble); if (marble % 23 == 0) { scores[currentPlayer] += marble; var toRemove = current.CCW.CCW.CCW.CCW.CCW.CCW.CCW; toRemove.CW.CCW = toRemove.CCW; toRemove.CCW.CW = toRemove.CW; scores[currentPlayer] += toRemove.Value; current = toRemove.CW; } else { current.CW.InsertCW(newMarble); current = newMarble; } currentPlayer = (currentPlayer + 1) % numPlayers; if (false) { //Debug output, compare to example on webpage var initial = current; while (initial.Value != 0) { initial = initial.CW; } Console.Write($"[{(currentPlayer == 0 ? numPlayers : currentPlayer),2}]"); do { if (initial.Value == current.Value) { Console.Write($"({initial.Value,2})"); } else { Console.Write($" {initial.Value,2} "); } initial = initial.CW; } while (initial.Value != 0); Console.WriteLine(""); } } return(scores.Max()); }
static void Main(string[] args) { int playerNumber = 455; int lastMarbleValue = 7122300; var marblesInCircle = new LinkedList <Marble>(); marblesInCircle.AddFirst(new Marble(0)); marblesInCircle.AddLast(new Marble(1)); var playerScores = new Dictionary <int, long>(); for (int i = 0; i < playerNumber; i++) { playerScores[i] = 0; } bool gameEnd = false; int roundCount = 2; LinkedListNode <Marble> currentMarble = marblesInCircle.Last; var sw = Stopwatch.StartNew(); while (!gameEnd) { // point score if (roundCount % 23 == 0) { var additionalMarbleToTake = GetNthCounterClockwiseElement(currentMarble, 7); if (additionalMarbleToTake.Next != null) { currentMarble = additionalMarbleToTake.Next; } else { currentMarble = marblesInCircle.First; } marblesInCircle.Remove(additionalMarbleToTake); int currentPlayerIndex = roundCount % playerNumber; playerScores[currentPlayerIndex] += additionalMarbleToTake.Value.Value + roundCount; } else // standard placing { var newMarbleToAdd = new Marble(roundCount); if (currentMarble.Next == null) { currentMarble = marblesInCircle.AddAfter(marblesInCircle.First, newMarbleToAdd); } else { currentMarble = marblesInCircle.AddAfter(currentMarble.Next, newMarbleToAdd); } } if (roundCount == lastMarbleValue) { gameEnd = true; } roundCount++; } sw.Stop(); var playerWithMaxPoint = playerScores.Aggregate((l, r) => l.Value > r.Value ? l : r); Console.WriteLine($"Winner: player {playerWithMaxPoint.Key} with value {playerWithMaxPoint.Value}"); Console.WriteLine($"Time: {sw.ElapsedMilliseconds} ms"); Console.ReadKey(); }
public Marble(long score) { Score = score; //default next and previous to self. a circle of one. Next = Previous = this; }