Advertisement
aaaaaa123456789

JV programming challenges, week 5, challenge 2

Dec 16th, 2013
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.80 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "common.h"
  5.  
  6. #define get_bits(value, position, bits) (((value) >> (position)) & ((1 << (bits)) - 1))
  7. #define set_bits(value, position, bits, update) \
  8.   ((value) ^= (get_bits(value, position, bits) ^ (update)) << (position))
  9.  
  10. struct game_result {
  11.   unsigned wins;
  12.   unsigned losses;
  13.   unsigned ties;
  14. };
  15.  
  16. unsigned char * get_hand_from_input(unsigned char, unsigned char);
  17. struct game_result calculate_result_frequencies(const char *, const char *, const char *);
  18. unsigned long long calculate_mask(const char *);
  19. struct game_result try_hands(const char *, const char *, const char *, unsigned char, unsigned char, unsigned long long);
  20. unsigned char generate_card(unsigned char);
  21. unsigned char determine_winner(const char *, const char *, const char *);
  22. unsigned char * create_hand_from_cards(const char *);
  23. unsigned char parse_card(const char *);
  24. unsigned score_hand(unsigned char *, unsigned);
  25. unsigned get_hand_characteristic(unsigned);
  26. unsigned score_characteristic(unsigned);
  27. unsigned search_insert(unsigned, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char);
  28.  
  29. int main (void) {
  30.   unsigned char * hand1 = NULL;
  31.   unsigned char * hand2 = NULL;
  32.   unsigned char * community = NULL;
  33.   while (!hand1) {
  34.     printf("Enter player 1's hand (2 cards): ");
  35.     hand1 = get_hand_from_input(2, 2);
  36.     if (!hand1) printf("Invalid hand.\n");
  37.   }
  38.   while (!hand2) {
  39.     printf("Enter player 2's hand (2 cards): ");
  40.     hand2 = get_hand_from_input(2, 2);
  41.     if (!hand2) printf("Invalid hand.\n");
  42.   }
  43.   while (!community) {
  44.     printf("Enter up to 5 community cards: ");
  45.     community = get_hand_from_input(0, 5);
  46.     if (!community) printf("Invalid input.\n");
  47.   }
  48.   unsigned long long mask = calculate_mask(hand1) | calculate_mask(hand2) | calculate_mask(community);
  49.   unsigned char card, count = 0;
  50.   for (card = 0; card < 64; card ++) if (mask & (1ULL << card)) count ++;
  51.   if ((strlen((char *) hand1) + strlen((char *) hand2) + strlen((char *) community)) != count) {
  52.     printf("There are duplicate cards in the input.\n");
  53.     return 1;
  54.   }
  55.   struct game_result odds = calculate_result_frequencies(hand1, hand2, community);
  56.   free(hand1);
  57.   free(hand2);
  58.   free(community);
  59.   double p1, p2, tie;
  60.   unsigned total;
  61.   total = odds.wins + odds.losses + odds.ties;
  62.   p1 = ((double) odds.wins) * 100 / total;
  63.   p2 = ((double) odds.losses) * 100 / total;
  64.   tie = ((double) odds.ties) * 100 / total;
  65.   printf("P1 win:% 11.6f%%\nP2 win:% 11.6f%%\nDraw  :% 11.6f%%\n", p1, p2, tie);
  66.   return 0;
  67. }
  68.  
  69. unsigned char * get_hand_from_input (unsigned char min_cards, unsigned char max_cards) {
  70.   char * line = get_line(NULL);
  71.   unsigned char * hand = create_hand_from_cards(line);
  72.   free(line);
  73.   if (!hand) return NULL;
  74.   if ((strlen((char *) hand) < min_cards) || (strlen((char *) hand) > max_cards)) {
  75.     free(hand);
  76.     return NULL;
  77.   }
  78.   return hand;
  79. }
  80.  
  81. struct game_result calculate_result_frequencies (const char * player1, const char * player2, const char * community) {
  82.   if (!community) community = "";
  83.   if (strlen(player1) != 2) return (struct game_result) {.wins = 0, .losses = 0, .ties = 0};
  84.   if (strlen(player2) != 2) return (struct game_result) {.wins = 0, .losses = 0, .ties = 0};
  85.   if (strlen(community) > 5) return (struct game_result) {.wins = 0, .losses = 0, .ties = 0};
  86.   if (strlen(community) == 5) {
  87.     unsigned char result = determine_winner(player1, player2, community);
  88.     switch (result) {
  89.       case 0: return (struct game_result) {.wins = 0, .losses = 0, .ties = 1};
  90.       case 1: return (struct game_result) {.wins = 1, .losses = 0, .ties = 0};
  91.       case 2: return (struct game_result) {.wins = 0, .losses = 1, .ties = 0};
  92.     }
  93.     return (struct game_result) {.wins = 0, .losses = 0, .ties = 0};
  94.   }
  95.   unsigned long long mask = calculate_mask(player1) | calculate_mask(player2) | calculate_mask(community);
  96.   return try_hands(player1, player2, community, strlen(community), 0, mask);
  97. }
  98.  
  99. unsigned long long calculate_mask (const char * cards) {
  100.   unsigned long long mask = 0;
  101.   const char * card;
  102.   for (card = cards; *card; card ++) mask |= 1ULL << *card;
  103.   return mask;
  104. }
  105.  
  106. struct game_result try_hands (const char * player1, const char * player2, const char * community,
  107.                               unsigned char position, unsigned char base, unsigned long long mask) {
  108.   struct game_result accumulated = {.wins = 0, .losses = 0, .ties = 0};
  109.   struct game_result next_result;
  110.   unsigned char cards[6];
  111.   unsigned char card, value, result;
  112.   cards[5] = 0;
  113.   memcpy(cards, community, position);
  114.   for (card = base; card < (48 + position); card ++) {
  115.     value = generate_card(card);
  116.     if (mask & (1ULL << value)) continue;
  117.     cards[position] = value;
  118.     if (position == 4) {
  119.       result = determine_winner(player1, player2, cards);
  120.       switch (result) {
  121.         case 0: accumulated.ties ++; break;
  122.         case 1: accumulated.wins ++; break;
  123.         case 2: accumulated.losses ++;
  124.       }
  125.     } else {
  126.       next_result = try_hands(player1, player2, cards, position + 1, card + 1, mask);
  127.       accumulated.wins += next_result.wins;
  128.       accumulated.ties += next_result.ties;
  129.       accumulated.losses += next_result.losses;
  130.     }
  131.   }
  132.   return accumulated;
  133. }
  134.  
  135. unsigned char generate_card (unsigned char index) {
  136.   return ((index / 13) << 4) | ((index % 13) + 2);
  137. }
  138.  
  139. unsigned char determine_winner (const char * player1, const char * player2, const char * community) {
  140.   char p1hand[8];
  141.   char p2hand[8];
  142.   memcpy(p1hand, player1, 2);
  143.   memcpy(p2hand, player2, 2);
  144.   memcpy(p1hand + 2, community, 6);
  145.   memcpy(p2hand + 2, community, 6);
  146.   unsigned score1 = score_hand(p1hand, 7);
  147.   unsigned score2 = score_hand(p2hand, 7);
  148.   if (score1 > score2) return 1;
  149.   if (score2 > score1) return 2;
  150.   return 0;
  151. }
  152.  
  153. unsigned char * create_hand_from_cards (const char * card_list) {
  154.   if ((!card_list) || (!*card_list)) {
  155.     char * empty = malloc(1);
  156.     *empty = 0;
  157.     return empty;
  158.   }
  159.   char ** card_names = tokenize_string(card_list, NULL, 1);
  160.   unsigned char * hand = malloc(1);
  161.   unsigned length;
  162.   unsigned char card;
  163.   for (length = 0; card_names[length]; length ++) {
  164.     card = parse_card(card_names[length]);
  165.     if (!card) {
  166.       free(hand);
  167.       free(card_names);
  168.       return NULL;
  169.     }
  170.     hand[length] = card;
  171.     hand = realloc(hand, length + 2);
  172.   }
  173.   free(card_names);
  174.   hand[length] = 0;
  175.   return hand;
  176. }
  177.  
  178. unsigned char parse_card (const char * card) {
  179.   if (strlen(card) != 2) return 0;
  180.   unsigned char value;
  181.   if ((*card >= '2') && (*card <= '9'))
  182.     value = *card - '0';
  183.   else
  184.     switch (*card) {
  185.       case 'T': case 't': value = 10; break;
  186.       case 'J': case 'j': value = 11; break;
  187.       case 'Q': case 'q': value = 12; break;
  188.       case 'K': case 'k': value = 13; break;
  189.       case 'A': case 'a': value = 14; break;
  190.       default: return 0;
  191.     }
  192.   switch(card[1]) {
  193.     case 'C': case 'c':                break;
  194.     case 'D': case 'd': value |= 0x10; break;
  195.     case 'H': case 'h': value |= 0x20; break;
  196.     case 'S': case 's': value |= 0x30; break;
  197.     default: return 0;
  198.   }
  199.   return value;
  200. }
  201.  
  202. unsigned score_hand(unsigned char * cards, unsigned count) {
  203.   if (!count) return score_hand(cards, strlen((char *) cards));
  204.   if (count < 5) return 0;
  205.   if (count == 5) {
  206.     unsigned hand = 0;
  207.     unsigned char card_pos;
  208.     for (card_pos = 0; card_pos < 5; card_pos ++) {
  209.       hand <<= 6;
  210.       hand |= cards[card_pos];
  211.     }
  212.     hand = get_hand_characteristic(hand);
  213.     if (!hand) return 0;
  214.     return score_characteristic(hand);
  215.   }
  216.   unsigned combination[5] = {0, 1, 2, 3, 4};
  217.   unsigned max_score = 0;
  218.   unsigned score;
  219.   signed char index, ii;
  220.   unsigned char card_values[5];
  221.   while (1) {
  222.     for (index = 4; index >= 0; index --) {
  223.       combination[index] ++;
  224.       for (ii = index + 1; ii < 5; ii ++) combination[ii] = combination[ii - 1] + 1;
  225.       if (combination[4] < count) break;
  226.     }
  227.     if (index < 0) return max_score;
  228.     for (ii = 0; ii < 5; ii ++) card_values[ii] = cards[combination[ii]];
  229.     score = score_hand(card_values, 5);
  230.     if (score > max_score) max_score = score;
  231.   }
  232. }
  233.  
  234. unsigned get_hand_characteristic (unsigned hand) {
  235.   unsigned characteristic = 0;
  236.   unsigned char lastsuit = get_bits(hand, 4, 2);
  237.   unsigned char rank, suit, position, count;
  238.   for (position = 0; position < 5; position ++) {
  239.     rank = hand & 15;
  240.     if ((rank < 2) || (rank == 15)) return 0;
  241.     suit = get_bits(hand, 4, 2);
  242.     hand >>= 6;
  243.     if (lastsuit != suit) lastsuit = 4;
  244.     count = get_bits(characteristic, 2 * rank - 4, 2);
  245.     if (count == 3) {
  246.       set_bits(characteristic, 2 * rank - 4, 2, 0);
  247.       set_bits(characteristic, 28, 4, rank);
  248.     } else
  249.       set_bits(characteristic, 2 * rank - 4, 2, count + 1);
  250.   }
  251.   if (lastsuit != 4) set_bits(characteristic, 28, 4, 1);
  252.   return characteristic;
  253. }
  254.  
  255. unsigned score_characteristic (unsigned characteristic) {
  256.   if (characteristic == 0x01000055) return 0x400005;
  257.   if (characteristic == 0x11000055) return 0x800005;
  258.   if (characteristic >= 0x20000000)
  259.     return 0x700000 | (get_bits(characteristic, 28, 4) << 4) | search_insert(characteristic, 1, 1, 0, 0, 0);  
  260.   unsigned char counts = 0;
  261.   unsigned char current, pos;
  262.   for (pos = 0; pos < 13; pos ++) {
  263.     current = get_bits(characteristic, 2 * pos, 2);
  264.     if (current) counts += 1 << (3 * (current - 1));
  265.   }
  266.   switch (counts) {
  267.     case 0110:
  268.       return 0x600000 | search_insert(characteristic, 2, 1, 0, 3, 1);
  269.     case 0102:
  270.       return 0x300000 | search_insert(characteristic, 1, 2, 0, 3, 2);
  271.     case 0021:
  272.       return 0x200000 | search_insert(characteristic, 2, 2, 1, 1, 0);
  273.     case 0013:
  274.       return 0x100000 | search_insert(characteristic, 1, 3, 0, 2, 3);
  275.     case 0005:
  276.       break;
  277.     default:
  278.       return 0;
  279.   }
  280.   unsigned score = search_insert(characteristic, 1, 5, 0, 0, 0);
  281.   if (!((score + 0x1234) % 0x11111))
  282.     return ((get_bits(characteristic, 28, 4) == 1) ? 0x800000 : 0x400000) + ((score + 0x1234) / 0x11111);
  283.   if (get_bits(characteristic, 28, 4) == 1) score += 0x500000;
  284.   return score;
  285. }
  286.  
  287. unsigned search_insert (unsigned characteristic, unsigned char target_count, unsigned char amount, unsigned char base,
  288.                         unsigned char special, unsigned char special_position) {
  289.   unsigned char pos, current;
  290.   unsigned score = 0;
  291.   for (pos = 12; (pos < 13) && (special || amount); pos --) {
  292.     current = get_bits(characteristic, pos * 2, 2);
  293.     if (!current) continue;
  294.     if (current == special) {
  295.       set_bits(score, 4 * special_position, 4, pos + 2);
  296.       special = 0;
  297.       continue;
  298.     }
  299.     if (amount && (current == target_count)) {
  300.       amount --;
  301.       set_bits(score, 4 * (base + amount), 4, pos + 2);
  302.     }
  303.   }
  304.   return score;
  305. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement