AdventOfCode2023/day_7/solution.d

95 lines
2.6 KiB
D
Raw Normal View History

2023-12-07 06:07:31 +00:00
import std.stdio;
import std.algorithm;
import std.conv;
import std.array;
import std.string;
import std.ascii;
enum HandType : ubyte {
FiveOfAKind = 7,
FourOfAKind = 6,
FullHouse = 5,
ThreeOfAKind = 4,
TwoPair = 3,
OnePair = 2,
HighCard = 1
}
struct Hand {
ubyte[5] cards;
long bid;
HandType type;
}
HandType getType(ubyte[5] cards) {
ubyte[15] freq;
ubyte maxFreq = 0;
foreach (ubyte c; cards) {
freq[c]++;
if (freq[c] > maxFreq) maxFreq = freq[c];
}
ubyte jokerFreq = freq[1];
ubyte maxNonJokerFreq = freq[2..$].maxElement;
ubyte nonJokerCardTypes = cast(ubyte) freq[2..$].count!(n => n != 0);
if (maxNonJokerFreq + jokerFreq == 5) return HandType.FiveOfAKind;
if (maxNonJokerFreq + jokerFreq == 4) return HandType.FourOfAKind;
if (maxNonJokerFreq + jokerFreq == 3 && nonJokerCardTypes == 2) return HandType.FullHouse;
if (maxNonJokerFreq + jokerFreq == 3) return HandType.ThreeOfAKind;
if (maxNonJokerFreq + jokerFreq == 2 && nonJokerCardTypes == 3) return HandType.TwoPair;
if (maxNonJokerFreq + jokerFreq == 2) return HandType.OnePair;
return HandType.HighCard;
}
bool compareHands(Hand a, Hand b) {
if (a.type > b.type) return false;
if (b.type > a.type) return true;
for (size_t i = 0; i < 5; i++) {
if (a.cards[i] > b.cards[i]) return false;
if (b.cards[i] > a.cards[i]) return true;
}
return false;
}
Hand[] parseHands(string filename, bool weakJoker) {
Hand[] hands;
foreach (string line; File(filename).byLineCopy()) {
string[] parts = line.split();
Hand h;
h.bid = parts[1].to!long;
foreach (size_t i, char c; parts[0]) {
if (isDigit(c)) h.cards[i] = cast(ubyte) (c - '0');
else if (c == 'T') h.cards[i] = 10;
else if (c == 'J') h.cards[i] = weakJoker ? 1 : 11;
else if (c == 'Q') h.cards[i] = 12;
else if (c == 'K') h.cards[i] = 13;
else if (c == 'A') h.cards[i] = 14;
}
h.type = getType(h.cards);
hands ~= h;
}
return hands;
}
void computeRankedBidSum(string filename, bool weakJoker) {
Hand[] hands = parseHands(filename, weakJoker);
long[] bidsRanked = hands.sort!compareHands.map!(h => h.bid).array;
long sum = 0;
for (long i = 0; i < bidsRanked.length; i++) {
sum += (i + 1) * bidsRanked[i];
}
writeln(sum);
}
void part1() {
computeRankedBidSum("input.txt", false);
}
void part2() {
computeRankedBidSum("input.txt", true);
}
void main() {
part1();
part2();
}