Added solution for "Day 7: Camel Cards", part 2
This commit is contained in:
		
							parent
							
								
									3f74b7c664
								
							
						
					
					
						commit
						6b5048b7ef
					
				| @ -39,12 +39,13 @@ type | ||||
|   TCardHand = class | ||||
|   private | ||||
|     FHand: string; | ||||
|     FType: TCardHandType; | ||||
|     FType, FJokerType: TCardHandType; | ||||
|     FBid: Cardinal; | ||||
|     function GetCardValue(const ACard: Char): Cardinal; | ||||
|     procedure CalcCountersFromHand(constref counters: TCardCounters); | ||||
|     function CalcTypeFromCounters(constref counters: TCardCounters): TCardHandType; | ||||
|     function CalcJokerTypeFromCounters(constref counters: TCardCounters): TCardHandType; | ||||
|   public | ||||
|     constructor Create(const ALine: string); | ||||
|     function CompareTo(constref AOther: TCardHand): Integer; | ||||
|     property Bid: Cardinal read FBid; | ||||
|   end; | ||||
| 
 | ||||
| @ -53,8 +54,20 @@ type | ||||
|   { TCardHandComparer } | ||||
| 
 | ||||
|   TCardHandComparer = class(TInterfacedObject, specialize IComparer<TCardHand>) | ||||
|   protected | ||||
|     function CompareCardValue(constref AHand1, AHand2: TCardHand): Integer; | ||||
|     function GetCardValue(const ACard: Char): Cardinal; virtual; | ||||
|   public | ||||
|     function Compare(constref AHand1, AHand2: TCardHand): Integer; | ||||
|     function Compare(constref AHand1, AHand2: TCardHand): Integer; virtual; | ||||
|   end; | ||||
| 
 | ||||
|   { TJokerCardHandComparer } | ||||
| 
 | ||||
|   TJokerCardHandComparer = class(TCardHandComparer) | ||||
|   protected | ||||
|     function GetCardValue(const ACard: Char): Cardinal; override; | ||||
|   public | ||||
|     function Compare(constref AHand1, AHand2: TCardHand): Integer; override; | ||||
|   end; | ||||
| 
 | ||||
|   { TCamelCards } | ||||
| @ -75,33 +88,14 @@ implementation | ||||
| 
 | ||||
| { TCardHand } | ||||
| 
 | ||||
| function TCardHand.GetCardValue(const ACard: Char): Cardinal; | ||||
| begin | ||||
|   if not TryStrToDWord(ACard, Result) then | ||||
|     case ACard of | ||||
|       'A': Result := 14; | ||||
|       'K': Result := 13; | ||||
|       'Q': Result := 12; | ||||
|       'J': Result := 11; | ||||
|       'T': Result := 10; | ||||
|       else Result := 0; | ||||
|     end; | ||||
| end; | ||||
| 
 | ||||
| constructor TCardHand.Create(const ALine: string); | ||||
| procedure TCardHand.CalcCountersFromHand(constref counters: TCardCounters); | ||||
| var | ||||
|   split: TStringArray; | ||||
|   counters: TCardCounters; | ||||
|   counter: TCardCounter; | ||||
|   i: Integer; | ||||
|   c: Char; | ||||
|   found: Boolean; | ||||
| begin | ||||
|   split := ALine.Split(' '); | ||||
|   FHand := split[0]; | ||||
|   FBid := StrToDWord(split[1]); | ||||
| 
 | ||||
|   counters := TCardCounters.Create; | ||||
|   counters.Clear; | ||||
| 
 | ||||
|   // Creates a counter for each different card value and counts cards per card value. | ||||
|   for c in FHand do | ||||
| @ -127,45 +121,131 @@ begin | ||||
|       counters.Add(counter); | ||||
|     end; | ||||
|   end; | ||||
| end; | ||||
| 
 | ||||
| function TCardHand.CalcTypeFromCounters(constref counters: TCardCounters): TCardHandType; | ||||
| begin | ||||
|   // Determines the hand type from the counters. | ||||
|   case counters.Count of | ||||
|     1: FType := htFiveOfAKind; | ||||
|     1: Result := htFiveOfAKind; | ||||
|     2: | ||||
|       if (counters[0].Count = 4) or (counters[1].Count = 4) then | ||||
|         FType := htFourOfAKind | ||||
|         Result := htFourOfAKind | ||||
|       else | ||||
|         FType := htFullHouse; | ||||
|         Result := htFullHouse; | ||||
|     3: | ||||
|       if (counters[0].Count = 3) or (counters[1].Count = 3) or (counters[2].Count = 3) then | ||||
|         FType := htThreeOfAKind | ||||
|         Result := htThreeOfAKind | ||||
|       else | ||||
|         FType := htTwoPair; | ||||
|     4: FType := htOnePair; | ||||
|     5: FType := htHighCard; | ||||
|         Result := htTwoPair; | ||||
|     4: Result := htOnePair; | ||||
|     5: Result := htHighCard; | ||||
|   end; | ||||
| end; | ||||
| 
 | ||||
|   counters.Free; | ||||
| end; | ||||
| 
 | ||||
| function TCardHand.CompareTo(constref AOther: TCardHand): Integer; | ||||
| function TCardHand.CalcJokerTypeFromCounters(constref counters: TCardCounters): TCardHandType; | ||||
| var | ||||
|   i: Integer; | ||||
|   i, maxCount, maxCountIndex, jokerIndex: Integer; | ||||
|   jokerCounter, counter: TCardCounter; | ||||
| begin | ||||
|   Result := Ord(FType) - Ord(AOther.FType); | ||||
|   i := 1; | ||||
|   while (Result = 0) and (i <= FHand.Length) do | ||||
|   if counters.Count > 1 then | ||||
|   begin | ||||
|     Result := GetCardValue(FHand[i]) - GetCardValue(AOther.FHand[i]); | ||||
|     Inc(i); | ||||
|     // Finds Jokers and the best card value. | ||||
|     maxCount := 0; | ||||
|     jokerIndex := -1; | ||||
|     for i := 0 to counters.Count - 1 do | ||||
|     begin | ||||
|       if counters[i].Card = 'J' then | ||||
|       begin | ||||
|         jokerIndex := i; | ||||
|         jokerCounter := counters[i]; | ||||
|       end | ||||
|       else if maxCount < counters[i].Count then | ||||
|       begin | ||||
|         maxCount := counters[i].Count; | ||||
|         maxCountIndex := i; | ||||
|       end; | ||||
|     end; | ||||
| 
 | ||||
|     // Uses Jokers for the best card value. | ||||
|     if jokerIndex >= 0 then | ||||
|     begin | ||||
|       counter := counters[maxCountIndex]; | ||||
|       Inc(counter.Count, jokerCounter.Count); | ||||
|       counters[maxCountIndex] := counter; | ||||
|       counters.Delete(jokerIndex); | ||||
|     end; | ||||
|   end; | ||||
| 
 | ||||
|   Result := CalcTypeFromCounters(counters); | ||||
| end; | ||||
| 
 | ||||
| constructor TCardHand.Create(const ALine: string); | ||||
| var | ||||
|   split: TStringArray; | ||||
|   counters: TCardCounters; | ||||
| begin | ||||
|   split := ALine.Split(' '); | ||||
|   FHand := split[0]; | ||||
|   FBid := StrToDWord(split[1]); | ||||
| 
 | ||||
|   counters := TCardCounters.Create; | ||||
|   CalcCountersFromHand(counters); | ||||
|   FType := CalcTypeFromCounters(counters); | ||||
|   FJokerType := CalcJokerTypeFromCounters(counters); | ||||
|   counters.Free; | ||||
| end; | ||||
| 
 | ||||
| { TCardHandComparer } | ||||
| 
 | ||||
| function TCardHandComparer.CompareCardValue(constref AHand1, AHand2: TCardHand): Integer; | ||||
| var | ||||
|   i: Integer; | ||||
| begin | ||||
|   Result := 0; | ||||
|   i := 1; | ||||
|   while (Result = 0) and (i <= AHand1.FHand.Length) do | ||||
|   begin | ||||
|     Result := GetCardValue(AHand1.FHand[i]) - GetCardValue(AHand2.FHand[i]); | ||||
|     Inc(i); | ||||
|   end; | ||||
| end; | ||||
| 
 | ||||
| function TCardHandComparer.GetCardValue(const ACard: Char): Cardinal; | ||||
| begin | ||||
|   if not TryStrToDWord(ACard, Result) then | ||||
|     case ACard of | ||||
|       'A': Result := 14; | ||||
|       'K': Result := 13; | ||||
|       'Q': Result := 12; | ||||
|       'J': Result := 11; | ||||
|       'T': Result := 10; | ||||
|       else Result := 0; | ||||
|     end; | ||||
| end; | ||||
| 
 | ||||
| function TCardHandComparer.Compare(constref AHand1, AHand2: TCardHand): Integer; | ||||
| begin | ||||
|   Result := AHand1.CompareTo(AHand2); | ||||
|   Result := Ord(AHand1.FType) - Ord(AHand2.FType); | ||||
|   if Result = 0 then | ||||
|     Result := CompareCardValue(AHand1, AHand2); | ||||
| end; | ||||
| 
 | ||||
| { TJokerCardHandComparer } | ||||
| 
 | ||||
| function TJokerCardHandComparer.GetCardValue(const ACard: Char): Cardinal; | ||||
| begin | ||||
|   if ACard = 'J' then | ||||
|     Result := 1 | ||||
|   else | ||||
|     Result := inherited GetCardValue(ACard); | ||||
| end; | ||||
| 
 | ||||
| function TJokerCardHandComparer.Compare(constref AHand1, AHand2: TCardHand): Integer; | ||||
| begin | ||||
|   Result := Ord(AHand1.FJokerType) - Ord(AHand2.FJokerType); | ||||
|   if Result = 0 then | ||||
|     Result := CompareCardValue(AHand1, AHand2); | ||||
| end; | ||||
| 
 | ||||
| { TCamelCards } | ||||
| @ -189,6 +269,7 @@ end; | ||||
| procedure TCamelCards.Finish; | ||||
| var | ||||
|   comparer: TCardHandComparer; | ||||
|   jokerComparer: TJokerCardHandComparer; | ||||
|   i: Integer; | ||||
| begin | ||||
|   comparer := TCardHandComparer.Create; | ||||
| @ -197,6 +278,13 @@ begin | ||||
| 
 | ||||
|   for i := 0 to FHands.Count - 1 do | ||||
|     Inc(FPart1, FHands[i].Bid * (i + 1)); | ||||
| 
 | ||||
|   jokerComparer := TJokerCardHandComparer.Create; | ||||
|   FHands.Sort(jokerComparer); | ||||
|   jokerComparer.Free; | ||||
| 
 | ||||
|   for i := 0 to FHands.Count - 1 do | ||||
|     Inc(FPart2, FHands[i].Bid * (i + 1)); | ||||
| end; | ||||
| 
 | ||||
| function TCamelCards.GetDataFileName: string; | ||||
|  | ||||
| @ -62,7 +62,7 @@ end; | ||||
| 
 | ||||
| procedure TCamelCardsFullDataTestCase.TestPart2; | ||||
| begin | ||||
|   AssertEquals(-1, FSolver.GetResultPart2); | ||||
|   AssertEquals(254115617, FSolver.GetResultPart2); | ||||
| end; | ||||
| 
 | ||||
| { TCamelCardsExampleTestCase } | ||||
| @ -79,7 +79,7 @@ end; | ||||
| 
 | ||||
| procedure TCamelCardsExampleTestCase.TestPart2; | ||||
| begin | ||||
|   AssertEquals(-1, FSolver.GetResultPart2); | ||||
|   AssertEquals(5905, FSolver.GetResultPart2); | ||||
| end; | ||||
| 
 | ||||
| initialization | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user