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