/// <summary> /// Calculate all possible move permutations given a robots set of cards /// </summary> /// <param name="robot">Robot</param> /// <returns>List of permutations</returns> internal static List<List<ProgramCardType>> CalculateMovePermutations(Robot robot) { var permutations = new List<List<ProgramCardType>>(); // This is the list of cards that can be placed. Locked registers are not included in this list // and should be appended to the end of each list if necessary IEnumerable<ProgramCardType> cards = robot.CardsToPlace().Select(ProgramCard.GetCardTypeByPriority); var root = new PermutationNode(); BuildCardPermutationTree(root, cards); BuildCardPermutationList(permutations, root); return permutations; }
private static int PermutationCounts(Robot robot) { // BUG: This math does not match our function for calculating permutations. FWIW, I trust the code more than this math. // Calculate the number of unique permutations possible with the cards to place. // For example, if we need to place the following cards // (2) Rotate Left, (1) Rotate Right, (1) Move 1, (1) Move 2 and (2) Move 3 // Given there are 7 cards to place and the number of cards we need is 5 // we are calculating P(n,r) where n = 7 and r = 5. // Also, given Rotate Left is repeated twice we have x1 = 2 and x2 = 2 for the // Move 3 repetitions. // Permutations = P(n,r) / (x1!x2!) // Permutations = P(7,5) / (2!2!) // Permutations = (7! / (7 - 5)!) / (2!2!) // Permutations = (5040 / 2) / (4) // Permutations = 2520 / 4 // Permutations = 630 List<int> cardsToPlace = robot.CardsToPlace().ToList(); List<ProgramCardType> cardTypesToPlace = cardsToPlace.Select(ProgramCard.GetCardByPriority).ToList(); int n = cardTypesToPlace.Count(); int r = Math.Min(n, Constants.RobotRegisters); List<Tuple<ProgramCardType, int>> cardDuplicateCounts = Permutations.GetDuplicateItemCounts(cardTypesToPlace).ToList(); double dividend = (Permutations.Factorial(n) / Permutations.Factorial(n - r)); double divisor = cardDuplicateCounts.Aggregate<Tuple<ProgramCardType, int>, double>(1, (current, dupe) => current * Permutations.Factorial(dupe.Item2)); return (int)(dividend / divisor); }