I probably should have just tried replacing the J's with every possible card, but alas...this terrible thing works.
This commit is contained in:
2023-12-07 21:13:13 -06:00
parent 11a8465853
commit 0ba5d244f5
5 changed files with 1264 additions and 0 deletions

View File

@ -42,6 +42,8 @@
<EmbeddedResource Include="inputs\05a.txt" />
<EmbeddedResource Include="inputs\06.txt" />
<EmbeddedResource Include="inputs\06a.txt" />
<EmbeddedResource Include="inputs\07.txt" />
<EmbeddedResource Include="inputs\07a.txt" />
</ItemGroup>
<ItemGroup>

1000
inputs/07.txt Normal file

File diff suppressed because it is too large Load Diff

5
inputs/07a.txt Normal file
View File

@ -0,0 +1,5 @@
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483

244
src/07.cs Normal file
View File

@ -0,0 +1,244 @@
using System.Diagnostics;
using aoc2023.Util;
using Math = System.Math;
namespace aoc2023;
internal class Day07 : Day
{
private static readonly char[] order = new[]
{
'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'
};
private Dictionary<List<int>, int> hands = new();
internal override void Parse()
{
var lines = Util.Parsing.ReadAllLines($"{GetDay()}");
foreach (var line in lines)
{
var split = line.Split(' ');
List<int> hand = new();
foreach (var card in split[0])
{
hand.Add(order.IndexOf(card));
}
hands.Add(hand, int.Parse(split[1]));
}
}
private int GetHandValue(List<int> hand)
{
Dictionary<int, int> cardCounts = new();
foreach (var card in hand)
{
if (!cardCounts.TryAdd(card, 1))
{
cardCounts[card]++;
}
}
// five of a kind
if (cardCounts.Count == 1)
{
return 7;
}
// four of a kind
if (cardCounts.Any(c => c.Value == 4))
{
return 6;
}
// full house
if (cardCounts.Count == 2 && cardCounts.ContainsValue(2) && cardCounts.ContainsValue(3))
{
return 5;
}
// three of a kind
if (cardCounts.Count == 3 && cardCounts.ContainsValue(3) && cardCounts.Count(c => c.Value == 1) == 2)
{
return 4;
}
// two pair
if (cardCounts.Count(c => c.Value == 2) == 2 && cardCounts.ContainsValue(1))
{
return 3;
}
// one pair
if (cardCounts.Count(c => c.Value == 2) == 1 && cardCounts.Count(c => c.Value == 1) == 3)
{
return 2;
}
return 1;
}
private int GetHandValuePart2(List<int> hand)
{
Dictionary<int, int> cardCounts = new();
int numWilds = 0;
foreach (var card in hand)
{
if (card == -1)
{
numWilds++;
}
else if (!cardCounts.TryAdd(card, 1))
{
cardCounts[card]++;
}
}
if (numWilds == 0)
{
return GetHandValue(hand);
}
// five of a kind
if (cardCounts.Any(c => c.Value + numWilds == 5) || numWilds == 5)
{
return 7;
}
// four of a kind
if (cardCounts.Any(c => c.Value + numWilds == 4))
{
return 6;
}
// full house
{
int wilds = numWilds;
bool hasTwo = false;
bool hasThree = false;
foreach (var cc in cardCounts)
{
if (cc.Value + wilds >= 3 && !hasThree)
{
wilds -= Math.Max(0, 3 - cc.Value);
hasThree = true;
}
else if (cc.Value + wilds >= 2 && !hasTwo)
{
wilds -= Math.Max(0, 2 - cc.Value);
hasTwo = true;
}
}
if (hasTwo && hasThree)
{
return 5;
}
}
// three of a kind
if (cardCounts.Any(c => c.Value + numWilds == 3))
{
return 4;
}
// one pair
if (cardCounts.Count(c => c.Value == 2) == 1 || numWilds >= 1)
{
return 2;
}
return 1;
}
private bool HandWinsTie(List<int> hand, List<int> other)
{
for (int j = 0; j < hand.Count; j++)
{
if (hand[j] > other[j])
{
return true;
}
if (other[j] > hand[j])
{
break;
}
}
return false;
}
List<(List<int> hand, int bet, int value)> SortHands(Dictionary<List<int>, int> h, Func<List<int>, int> valueFunc)
{
List<(List<int> hand, int bet, int value)> ordered = new();
foreach (var hand in h)
{
bool inserted = false;
var value = valueFunc(hand.Key);
for (int i = 0; i < ordered.Count && !inserted; i++)
{
if (value > ordered[i].value)
{
ordered.Insert(i, (hand.Key, hand.Value, value));
inserted = true;
break;
}
if (value == ordered[i].value)
{
if (HandWinsTie(hand.Key, ordered[i].hand))
{
ordered.Insert(i, (hand.Key, hand.Value, value));
inserted = true;
break;
}
}
}
if (!inserted)
{
ordered.Add((hand.Key, hand.Value, value));
}
}
return ordered;
}
internal override string Part1()
{
var ordered = SortHands(hands, GetHandValue);
long total = 0;
for (int i = 0; i < ordered.Count; i++)
{
total += (ordered.Count - i) * ordered[i].bet;
}
return $"Total winnings: <+white>{total}";
}
internal override string Part2()
{
Dictionary<List<int>, int> handsp2 = [];
foreach (var hand in hands)
{
var l = new List<int>(hand.Key);
for (int i = 0; i < l.Count; i++)
{
if (l[i] == order.IndexOf('J'))
{
l[i] = -1;
}
}
handsp2.Add(l, hand.Value);
}
var ordered = SortHands(handsp2, GetHandValuePart2);
long total = 0;
for (int i = 0; i < ordered.Count; i++)
{
total += (ordered.Count - i) * ordered[i].bet;
}
return $"Total winnings: <+white>{total}";
}
}

View File

@ -11,4 +11,17 @@ public static class Extensions
list.Add(elem);
}
}
public static int IndexOf<T>(this ICollection<T> list, T elem) where T : IEquatable<T>
{
for (int idx = 0; idx < list.Count; idx++)
{
if (list.ElementAt(idx).Equals(elem))
{
return idx;
}
}
return -1;
}
}