project-euler

https://projecteuler.net/
Log | Files | Refs | README

Euler_54.cpp (6076B)


      1 #include <algorithm>
      2 #include <fstream>
      3 #include <functional>
      4 #include <unordered_set>
      5 
      6 #include "Euler.h"
      7 
      8 struct hand
      9 {
     10     int handValue;
     11     std::vector<int> cardValues;
     12 };
     13 
     14 struct game
     15 {
     16     hand hands[2];
     17 };
     18 
     19 char order[] = {'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'};
     20 
     21 bool isFlush(std::vector<std::string>& hand)
     22 {
     23     char c = hand[0][1];
     24 
     25     for (uint64_t i = 1; i < hand.size(); ++i)
     26         if (hand[i][1] != c)
     27             return false;
     28 
     29     return true;
     30 }
     31 
     32 bool isStraight(std::vector<int> indices)
     33 {
     34     for (uint64_t i = 1; i < indices.size(); ++i)
     35         if (indices[i] != indices[i - 1] - 1)
     36             return false;
     37 
     38     return true;
     39 }
     40 
     41 std::vector<int> getCardValues(std::vector<std::string>& hand)
     42 {
     43     std::vector<int> indices;
     44 
     45     for (uint64_t i = 0; i < hand.size(); ++i) {
     46         for (int j = 0; j < 13; ++j)
     47         {
     48             char c = hand[i][0];
     49             if (c == order[j])
     50             {
     51                 indices.push_back(j);
     52                 break;
     53             }
     54         }
     55     }
     56 
     57     std::sort(indices.begin(), indices.end(), std::greater<int>());
     58 
     59     return indices;
     60 }
     61 
     62 int determineNoOfRepeats(std::unordered_set<int>& us, std::vector<int>& cardValues, int t, int def, int high)
     63 {
     64     for (int j : us)
     65     {
     66         int total = 0;
     67 
     68         for (uint64_t k = 0; k < cardValues.size(); ++k)
     69             if (j == cardValues[k])
     70                 ++total;
     71 
     72         if (total == t)
     73             return high;
     74     }
     75 
     76     return def;
     77 }
     78 
     79 int determineRepeat(std::unordered_set<int>& us, std::vector<int>& cardValues, int rep, bool skip)
     80 {
     81     for (int j : us)
     82     {
     83         int total = 0;
     84 
     85         for (uint64_t k = 0; k < cardValues.size(); ++k)
     86             if (j == cardValues[k])
     87                 ++total;
     88 
     89         if (total == rep)
     90         {
     91             if (skip)
     92                 skip = false;
     93             else
     94                 return j;
     95         }
     96     }
     97 
     98     return -1;
     99 }
    100 
    101 void determinePriorityOrder(hand& h, std::unordered_set<int>& us)
    102 {
    103     if (h.handValue == 4 || h.handValue == 0)
    104         return;
    105 
    106     std::vector<int> values(h.cardValues);
    107     int rep1, rep2, no = 0;
    108 
    109     switch(h.handValue)
    110     {
    111     case 1:
    112         rep1 = determineRepeat(us, h.cardValues, 2, false);
    113 
    114         for (uint64_t i = 0; i < h.cardValues.size(); ++i) {
    115             if (h.cardValues[i] == rep1)
    116                 std::swap(h.cardValues[no++], h.cardValues[i]);
    117         }
    118 
    119         std::sort(h.cardValues.begin() + 2, h.cardValues.end(), std::greater<int>());
    120         break;
    121     case 2:
    122         rep1 = determineRepeat(us, h.cardValues, 2, true);
    123         rep2 = determineRepeat(us, h.cardValues, 2, false);
    124 
    125         if (rep2 > rep1)
    126             std::swap(rep1, rep2);
    127 
    128         for (uint64_t i = 0; i < h.cardValues.size(); ++i)
    129         {
    130             if (h.cardValues[i] == rep1)
    131                 std::swap(h.cardValues[no++], h.cardValues[i]);
    132         }
    133 
    134         for (uint64_t i = 0; i < h.cardValues.size(); ++i)
    135             if (h.cardValues[i] == rep2)
    136                 std::swap(h.cardValues[no++], h.cardValues[i]);
    137         break;
    138     case 3:
    139         rep1 = determineRepeat(us, h.cardValues, 3, false);
    140 
    141         for (uint64_t i = 0; i < h.cardValues.size(); ++i) {
    142             if (h.cardValues[i] == rep1)
    143                 std::swap(h.cardValues[no++], h.cardValues[i]);
    144         }
    145 
    146         std::sort(h.cardValues.begin() + 3, h.cardValues.end(), std::greater<int>());
    147         break;
    148     case 6:
    149         rep1 = determineRepeat(us, h.cardValues, 3, false);
    150         for (uint64_t i = 0; i < h.cardValues.size(); ++i)
    151             if (h.cardValues[i] == rep1)
    152                 std::swap(h.cardValues[no++], h.cardValues[i]);
    153 
    154         break;
    155     case 7:
    156         rep1 = determineRepeat(us, h.cardValues, 4, false);
    157 
    158         for (uint64_t i = 0; i < h.cardValues.size(); ++i)
    159             if (h.cardValues[i] == rep1)
    160                 std::swap(h.cardValues[no++], h.cardValues[i]);
    161         break;
    162     }
    163 }
    164 
    165 game determineHands(std::vector<std::string>& cards)
    166 {
    167     game g;
    168 
    169     std::vector<std::string> hands[2];
    170 
    171     hands[0] = std::vector<std::string>(cards.begin(), cards.begin() + 5);
    172     hands[1] = std::vector<std::string>(cards.begin() + 5, cards.end());
    173 
    174     for (int i = 0; i < 2; ++i)
    175     {
    176         g.hands[i].cardValues = getCardValues(hands[i]);
    177 
    178         if (isFlush(hands[i]))
    179         {
    180             g.hands[i].handValue = isStraight(g.hands[i].cardValues) ? (g.hands[i].cardValues[4] == 12 ? 9 : 8) : 5;
    181         }
    182         else
    183         {
    184             std::unordered_set<int> us;
    185 
    186             for (int j : g.hands[i].cardValues)
    187                 us.insert(j);
    188 
    189             switch(us.size())
    190             {
    191             case 2:
    192                 g.hands[i].handValue = determineNoOfRepeats(us, g.hands[i].cardValues, 4, 6, 7);
    193                 break;
    194             case 3:
    195                 g.hands[i].handValue = determineNoOfRepeats(us, g.hands[i].cardValues, 3, 2, 3);
    196                 break;
    197             case 4:
    198                 g.hands[i].handValue = 1;
    199                 break;
    200             case 5:
    201                 g.hands[i].handValue = isStraight(g.hands[i].cardValues) ? 4 : 0;
    202                 break;
    203             }
    204 
    205             determinePriorityOrder(g.hands[i], us);
    206         }
    207 
    208 
    209     }
    210 
    211     return g;
    212 }
    213 
    214 bool determineWinner(game g) //assumes no draws
    215 {
    216     if (g.hands[0].handValue > g.hands[1].handValue)
    217         return false;
    218 
    219     if (g.hands[1].handValue > g.hands[0].handValue)
    220         return true;
    221 
    222     for (uint64_t i = 0; i < g.hands[0].cardValues.size(); ++i)
    223     {
    224         if (g.hands[0].cardValues[i] > g.hands[1].cardValues[i])
    225             return false;
    226 
    227         if (g.hands[1].cardValues[i] > g.hands[0].cardValues[i])
    228             return true;
    229     }
    230 
    231     return true;
    232 }
    233 
    234 int Euler::PokerHands()
    235 {
    236     int scores[2] = {0, 0};
    237 
    238     std::ifstream fin;
    239     fin.open("files/p054_poker.txt");
    240 
    241     for (std::string line; std::getline(fin, line);) {
    242         std::vector<std::string> tokens = EulerUtility::strTokenizer(line, ' ');
    243         ++scores[determineWinner(determineHands(tokens))];
    244     }
    245 
    246     fin.close();
    247 
    248     return scores[0];
    249 }