/// <summary> /// Finds the smart group by testing and mixing both 1-2-3 sorting and 7-7-7 sorting. /// Returns the grouping with the least total value of ungrouped cards. /// </summary> public static CardGrouping GetSmartGroups(IList <Card> cards) { var allPossibleGroups = new List <IList <Card> >(); var cardsOneTwoThreeClone = cards.CloneList(); while (cardsOneTwoThreeClone.Count > 0) { var card = cardsOneTwoThreeClone[0]; var oneTwoThreeGroups = GetAllOneTwoThreeGroups(cards, card); if (oneTwoThreeGroups.Count > 0) { var largestGroup = oneTwoThreeGroups[0]; cardsOneTwoThreeClone.RemoveAll(largestGroup.Contains); allPossibleGroups.AddRange(oneTwoThreeGroups); } else { cardsOneTwoThreeClone.RemoveAt(0); } } var cardsSevenSevenSevenClone = cards.CloneList(); while (cardsSevenSevenSevenClone.Count > 0) { var card = cardsSevenSevenSevenClone[0]; var sevenSevenSevenGroups = GetAllSevenSevenSevenGroups(cards, card); if (sevenSevenSevenGroups.Count > 0) { var largestGroup = sevenSevenSevenGroups[0]; cardsSevenSevenSevenClone.RemoveAll(largestGroup.Contains); allPossibleGroups.AddRange(sevenSevenSevenGroups); } else { cardsSevenSevenSevenClone.RemoveAt(0); } } var currentGrouping = new GroupingCandidate(); var bestGrouping = new GroupingCandidate(); FindBestGrouping(allPossibleGroups, currentGrouping, bestGrouping); var retVal = new CardGrouping(cards); foreach (var group in bestGrouping.Groups) { retVal.Groups.Add(group); foreach (var card in group) { retVal.Ungrouped.Remove(card); } } return(retVal); }
/// <summary> /// Recursive function used by GetSmartGroups. /// </summary> private static void FindBestGrouping(IList <IList <Card> > allPossibleGroups, GroupingCandidate currentGrouping, GroupingCandidate bestGrouping) { foreach (var possibleGroup in allPossibleGroups) { var compatible = true; for (var i = 0; i < currentGrouping.Groups.Count; i++) { if (!currentGrouping.Groups[i].IsCompatible(possibleGroup)) { compatible = false; break; } } if (compatible) { currentGrouping.Push(possibleGroup); FindBestGrouping(allPossibleGroups, currentGrouping, bestGrouping); if (currentGrouping.Value > bestGrouping.Value) { bestGrouping.Clear(); foreach (var group in currentGrouping.Groups) { bestGrouping.Push(group); } } currentGrouping.Pop(); } } }