Files
2023-12-07 22:30:15 -05:00

195 lines
4.7 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#define DEFAULT_FILE "input.txt"
#define STRBUF_LEN 200
#define ISDIGIT(X) (X >= '0' && X <= '9')
typedef struct _hand
{
char cards[5]; // just for debugging
int strength;
int substrengths[5];
int bid;
} hand;
#define NUM_CARDS 13
#define NUM_HANDS 1000
const char strengthlist[NUM_CARDS] = { '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' };
// This function could be faster I'm sure.
// Instead of searching through an array,
// the characters could be mapped with
// a lookup table.
// I'm lazy to do this right now.
int parse_substrength(char c)
{
int i = 0;
for (i = 0; i < NUM_CARDS; i++)
{
if (c == strengthlist[i]) return i;
}
}
int parse_strength(char *hand)
{
int hashmap[NUM_CARDS] = {0};
int i = 0;
for (i = 0; i < 5; i++)
{
int substrength = parse_substrength(hand[i]);
hashmap[substrength]++;
}
int most_duplicates = 0;
int second_most_duplicates = 0;
for (i = 0; i < NUM_CARDS; i++)
{
if (hashmap[i] >= most_duplicates)
{
second_most_duplicates = most_duplicates;
most_duplicates = hashmap[i];
} else if (hashmap[i] >= second_most_duplicates)
{
second_most_duplicates = hashmap[i];
}
}
if (most_duplicates == 5) return 6; // Five of a kind
if (most_duplicates == 4) return 5; // Four of a kind
if (most_duplicates == 3 && second_most_duplicates == 2) return 4; // Full house
if (most_duplicates == 3) return 3; // Three of a kind
if (most_duplicates == 2 && second_most_duplicates == 2) return 2; // Two pair
if (most_duplicates == 2) return 1; // Two of a kind
return 0;
}
// Returns true if hand A beats hand B
bool hand_beats(hand a, hand b)
{
if (a.strength != b.strength) return (a.strength > b.strength);
int i = 0;
for (i = 0; i < NUM_CARDS; i++)
{
if (a.substrengths[i] != b.substrengths[i])
{
int suba = a.substrengths[i];
int subb = b.substrengths[i];
bool a_beats_b = suba > subb;
return (a_beats_b);
}
}
return false;
}
int parse_num(char *str)
{
int num = 0;
while (ISDIGIT(*str))
{
num = (num * 10) + (*str - '0');
str++;int strength[1000] = {0};
int payout[1000] = {0};
}
return num;
}
void sort(hand *hands)
{
// Insertion sort, because I'm too lazy.
// Other sorting algorithms would be faster.
// Try quicksort.
int a = 0;
int b = 0;
for (a = NUM_HANDS - 1; a >= 0; a--)
{
for (b = NUM_HANDS - 1; b >= a; b--) {
if (hand_beats(hands[a], hands[b]))
{
hand h = hands[a];
hands[a] = hands[b];
hands[b] = h;
}
}
}
}
int main(int argc, char **argv)
{
// Get filename as an argument, if there is one
char *path = (argc > 1) ? argv[1] : DEFAULT_FILE;
if (!path)
{
printf("Requires input file.\n");
return 1;
}
FILE *file = fopen(path, "r");
char strbuf[STRBUF_LEN] = {0};
if (!file)
{
printf("Could not find file.");
return 1;
}
// ************************************
// Begin Challenge
// ************************************
hand hands[NUM_HANDS];
hand sorted_hands[NUM_HANDS];
uint16_t i = 0;
uint16_t k = 0;
while (fgets(strbuf, STRBUF_LEN, file))
{
hands[i].strength = parse_strength(strbuf);
for (k = 0; k < 5; k++)
{
hands[i].cards[k] = strbuf[k];
hands[i].substrengths[k] = parse_substrength(strbuf[k]);
}
hands[i].bid = parse_num(strbuf + 6);
i++;
}
printf("\n");
sort(hands);
uint64_t winnings = 0;
for (i = NUM_HANDS - 1; i <= NUM_HANDS; i--)
{
printf("%c%c%c%c%c",
hands[i].cards[0],
hands[i].cards[1],
hands[i].cards[2],
hands[i].cards[3],
hands[i].cards[4]);
printf(" i: %.3d str: %.2d, %.2d %.2d %.2d %.2d %.2d, bid: %.3d\n",
i + 1,
hands[i].strength,
hands[i].substrengths[0],
hands[i].substrengths[1],
hands[i].substrengths[2],
hands[i].substrengths[3],
hands[i].substrengths[4],
hands[i].bid
);
winnings += hands[i].bid * (i + 1);
}
printf("winnings: %lu\n", winnings);
return 0;
}