AOC2023: optimize hand score calculation

This commit is contained in:
Bananymous 2023-12-07 09:03:09 +02:00
parent a872efdef2
commit 536bb74d53
1 changed files with 33 additions and 39 deletions

View File

@ -1,5 +1,6 @@
#include <BAN/Vector.h> #include <BAN/Vector.h>
#include <BAN/String.h> #include <BAN/String.h>
#include <BAN/Swap.h>
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
@ -62,44 +63,40 @@ i64 hand_score(const Hand& hand, bool joker)
{ {
if (isdigit(c)) if (isdigit(c))
cnt[c - '0' + 0]++; cnt[c - '0' + 0]++;
else if (c == 'J') else if (joker && c == 'J')
joker_count++; joker_count++;
else else
cnt[c - 'A' + 10]++; cnt[c - 'A' + 10]++;
} }
if (!joker) i64 freq_max1 = 0;
i64 freq_max2 = 0;
for (size_t i = 0; i < 36; i++)
{ {
cnt['J' - 'A' + 10] = joker_count; if (cnt[i] > freq_max1)
joker_count = 0; {
freq_max2 = freq_max1;
freq_max1 = cnt[i];
}
else if (cnt[i] > freq_max2)
{
freq_max2 = cnt[i];
}
} }
freq_max1 += joker_count;
for (size_t i = 0; i < 36; i++) if (freq_max1 == 5)
if (cnt[i] + joker_count >= 5) return 6'000'000 + hand_score_no_type(hand, joker);
return 6'000'000 + hand_score_no_type(hand, joker); if (freq_max1 == 4)
return 5'000'000 + hand_score_no_type(hand, joker);
for (size_t i = 0; i < 36; i++) if (freq_max1 == 3 && freq_max2 == 2)
if (cnt[i] + joker_count >= 4) return 4'000'000 + hand_score_no_type(hand, joker);
return 5'000'000 + hand_score_no_type(hand, joker); if (freq_max1 == 3)
return 3'000'000 + hand_score_no_type(hand, joker);
for (size_t i = 0; i < 36; i++) if (freq_max1 == 2 && freq_max2 == 2)
for (size_t j = 0; j < 36; j++) return 2'000'000 + hand_score_no_type(hand, joker);
if (i != j && cnt[i] + joker_count >= 3 && cnt[j] >= 2) if (freq_max1 == 2)
return 4'000'000 + hand_score_no_type(hand, joker); return 1'000'000 + hand_score_no_type(hand, joker);
for (size_t i = 0; i < 36; i++)
if (cnt[i] + joker_count >= 3)
return 3'000'000 + hand_score_no_type(hand, joker);
for (size_t i = 0; i < 36; i++)
for (size_t j = 0; j < 36; j++)
if (i != j && cnt[i] + joker_count >= 2 && cnt[j] >= 2)
return 2'000'000 + hand_score_no_type(hand, joker);
for (size_t i = 0; i < 36; i++)
if (cnt[i] + joker_count >= 2)
return 1'000'000 + hand_score_no_type(hand, joker);
return hand_score_no_type(hand, joker); return hand_score_no_type(hand, joker);
} }
@ -113,11 +110,10 @@ i64 puzzle(FILE* fp, bool joker)
BAN::StringView line(buffer); BAN::StringView line(buffer);
if (line.size() < 7) if (line.size() < 7)
continue; continue;
MUST(hands.emplace_back(
Hand hand; line.substring(0, 5),
hand.hand = line.substring(0, 5); parse_i64(line.substring(6))
hand.bid = parse_i64(line.substring(6)); ));
MUST(hands.push_back(hand));
} }
// Very slow sorting algorithm // Very slow sorting algorithm
@ -129,9 +125,7 @@ i64 puzzle(FILE* fp, bool joker)
i64 r_score = hand_score(hands[j], joker); i64 r_score = hand_score(hands[j], joker);
if (r_score > l_score) if (r_score > l_score)
{ {
Hand tmp = BAN::move(hands[i]); BAN::swap(hands[i], hands[j]);
hands[i] = BAN::move(hands[j]);
hands[j] = BAN::move(tmp);
l_score = r_score; l_score = r_score;
} }
} }