Complete Day 7 Part 2
This commit is contained in:
209
07/07-part2.c
Normal file
209
07/07-part2.c
Normal file
@@ -0,0 +1,209 @@
|
||||
#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] = { 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', '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 = 1; 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];
|
||||
}
|
||||
}
|
||||
|
||||
int js = hashmap[0];
|
||||
|
||||
// I'm sure there's a better way to do this.
|
||||
if (most_duplicates == 5) return 6; // Five of a kind
|
||||
if (most_duplicates + js == 5) return 6; // Five of a kind, jokers
|
||||
|
||||
if (most_duplicates == 4) return 5; // Four of a kind
|
||||
if (most_duplicates + js == 4) return 5; // Four of a kind, jokers
|
||||
|
||||
if (most_duplicates == 3 && second_most_duplicates == 2) return 4; // Full house
|
||||
if (most_duplicates == 2 && second_most_duplicates == 2 && js == 1) return 4; // Full house, jokers
|
||||
if (most_duplicates == 3 && second_most_duplicates == 1 && js == 1) return 4; // Full house, jokers
|
||||
|
||||
if (most_duplicates == 3) return 3; // Three of a kind
|
||||
if (most_duplicates + js == 3) return 3; // Three of a kind
|
||||
|
||||
if (most_duplicates == 2 && second_most_duplicates == 2) return 2; // Two pair
|
||||
if (most_duplicates == 2 && second_most_duplicates + js == 2) return 2; // Two pair
|
||||
|
||||
if (most_duplicates + js == 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;
|
||||
}
|
||||
Reference in New Issue
Block a user