3

I'm facing a problem. I'm learning c++. I took a poker context ; The goal is to get a certain hand range from a string length ; the string represents all starting hands in a poker game , in the order stronger first.

 string hand = "AA,KK,QQ,JJ,AKs,AKo,AQs,AQo,TT,AJs,ATs,AJo,KQs,KJs,KTs,QJs,ATo,QTs,JTs,A9s,A9o,KQo,A8s,A8o,A7s,A7o,A6s,A6o,A5s,A5o,A4s,99,A4o,A3s,A2s,KJo,J9s,T9s,Q9s,QJo,KTo,Q9o,88,77,66,QTo,A3o,A2o,JTo,K9s,K8s,K7s,K6s,K5s,K4s,K3s,K2s,Q8s,Q7s,Q6s,Q5s,K9o,J8s,T8s,98s,97s,87s,86s,76s,96s,75s,65s,64s,J9o,T9o,55,54s,53s,52s,K8o,43s,32s,42s,J7s,T7s,K7o,44,33,22,Q4s,Q3s,Q2s,J6s,J5s,T6s,T5s,J4s,K6o,Q8o,J8o,T8o,98o,97o,87o,85s,K5o,K4o,K3o,K2o,95s,74s,76o,65o,54o,84s,94s,Q7o,J7o,T7o,Q6o,J3s,T4s,J2s,Q5o,T3s,T2s,Q4o,J6o,86o,T6o,96o,93s,Q3o,74o,84o,75o,64o,T2o,94o,53o,93o,63o,43o,92o,73o,83o,52o,82o,42o,62o,72o,J5o,63s,92s,73s,Q2o,J4o,83s,85o,82s,T5o,95o,J3o,62s,T4o,J2o,72s,T3o,32o";

The length of the string hand is 662 ; To get the range we need to exclude a percentage of the starting hand and exclude a percentage of the ending hand .

So if I need the last 10% hands, I will exclude first 90% . if I need between 30% and 60% , I will exclude first 29% and last 39% .

It's difficult because the string cannot cut anywhere, a good output should be for example 72o,J5o,63s,92s,73s,Q2o,J4o,83s, with or without the comma to the end, this is not the most important.

I tried to create a substring like this :

  int startpos = 0;
  int stoppos= (662 * 7) / 100;
  string str2 = hand.substr(startpos, stoppos);
  cout <<  str2 << endl;

But this not the answer to the range problem. It gets only the first X%, and the cut is bad , output is : AA,KK,QQ,JJ,A and should be : AA,KK,QQ,JJ,AKs

I spent many hours on this. I'm open for advice, directions, and even a solution ..

Regards, gui

Jan
  • 5,688
  • 3
  • 27
  • 44
  • 2
    Why are you using a string? Why not a list of strings? (eg, `{"AA", "KK", "QQ", ...}`) The last 10% of the list would then be hand[595] through hand[661]. – user3553031 Jul 18 '15 at 18:50
  • Just looking at the substring length isn't going to work because each card is 2 or 3 characters, and there is a comma after all but the last card. At first glance, I would figure out how many commas to skip, and then search for the appropriate start and end points based on that information. – Logicrat Jul 18 '15 at 18:52
  • @ user3553031 i don't undertand how you can achieve it in this way – guillaume importexport Jul 18 '15 at 18:52
  • @guillaumeimportexport You have a list of variable-width strings represented as a comma-separated list in a string. This is essentially a sequential-access container. You want to extract a subsequence from this list, which is a bit of a pain. Why not use a random-access container? Or am I misunderstanding your problem? – user3553031 Jul 18 '15 at 19:06
  • @ user3553031 i am beginer , concret example is welcome :) – guillaume importexport Jul 18 '15 at 19:14

3 Answers3

4

Here's one way to do it: take your string, convert it to a sequence, discard parts of the sequence you are uninterested in, then convert that back to a string.

So here's how I would do this in Python:

start, stop = 30, 60
hands = 'AA,KK,QQ,JJ,AKs,AKo,AQs,AQo,TT,AJs,ATs,AJo,KQs,KJs,KTs,QJs,\
ATo,QTs,JTs,A9s,A9o,KQo,A8s,A8o,A7s,A7o,A6s,A6o,A5s,A5o,A4s,99,A4o,A3s,A2s,\
KJo,J9s,T9s,Q9s,QJo,KTo,Q9o,88,77,66,QTo,A3o,A2o,JTo,K9s,K8s,K7s,K6s,K5s,K4s,\
K3s,K2s,Q8s,Q7s,Q6s,Q5s,K9o,J8s,T8s,98s,97s,87s,86s,76s,96s,75s,65s,64s,J9o,\
T9o,55,54s,53s,52s,K8o,43s,32s,42s,J7s,T7s,K7o,44,33,22,Q4s,Q3s,Q2s,J6s,J5s,\
T6s,T5s,J4s,K6o,Q8o,J8o,T8o,98o,97o,87o,85s,K5o,K4o,K3o,K2o,95s,74s,76o,65o,\
54o,84s,94s,Q7o,J7o,T7o,Q6o,J3s,T4s,J2s,Q5o,T3s,T2s,Q4o,J6o,86o,T6o,96o,93s,\
Q3o,74o,84o,75o,64o,T2o,94o,53o,93o,63o,43o,92o,73o,83o,52o,82o,42o,62o,72o,\
J5o,63s,92s,73s,Q2o,J4o,83s,85o,82s,T5o,95o,J3o,62s,T4o,J2o,72s,T3o,32o'

hands = hands.split(',')
hands = hands[start * len(hands) / 100 : stop * len(hands) / 100]
print ','.join(hands)

With help from two Stackoverflow threads here and here, I translated the Python code to (admittedly not idiomatic) C++:

#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

vector<string> &split(const string &s, char delim, vector<string> &elems) {
  stringstream ss(s);
  string item;
  while (getline(ss, item, delim)) {
    elems.push_back(item);
  }
  return elems;
}

vector<string> split(const string &s, char delim) {
  vector<string> elems;
  split(s, delim, elems);
  return elems;
}

int main() {
  // percentage markers to keep, 30% -- 60% here
  int start = 30, stop = 60;
  string hands = "AA,KK,QQ,JJ,AKs,AKo,AQs,AQo,TT,AJs,ATs,AJo,KQs,KJs,KTs,QJs,\
ATo,QTs,JTs,A9s,A9o,KQo,A8s,A8o,A7s,A7o,A6s,A6o,A5s,A5o,A4s,99,A4o,A3s,A2s,\
KJo,J9s,T9s,Q9s,QJo,KTo,Q9o,88,77,66,QTo,A3o,A2o,JTo,K9s,K8s,K7s,K6s,K5s,K4s,\
K3s,K2s,Q8s,Q7s,Q6s,Q5s,K9o,J8s,T8s,98s,97s,87s,86s,76s,96s,75s,65s,64s,J9o,\
T9o,55,54s,53s,52s,K8o,43s,32s,42s,J7s,T7s,K7o,44,33,22,Q4s,Q3s,Q2s,J6s,J5s,\
T6s,T5s,J4s,K6o,Q8o,J8o,T8o,98o,97o,87o,85s,K5o,K4o,K3o,K2o,95s,74s,76o,65o,\
54o,84s,94s,Q7o,J7o,T7o,Q6o,J3s,T4s,J2s,Q5o,T3s,T2s,Q4o,J6o,86o,T6o,96o,93s,\
Q3o,74o,84o,75o,64o,T2o,94o,53o,93o,63o,43o,92o,73o,83o,52o,82o,42o,62o,72o,\
J5o,63s,92s,73s,Q2o,J4o,83s,85o,82s,T5o,95o,J3o,62s,T4o,J2o,72s,T3o,32o";

  vector<string> hands_ = split(hands, ',');
  start = start * hands_.size() / 100;
  stop = stop * hands_.size() / 100;

  stringstream buffer;
  for (size_t i = start; i < stop; ++i) {
    if(i != start)
      buffer << ',';
    buffer << hands_[i];
  }
  string output = buffer.str();

  cout << output << endl;
  return 0;
}
Community
  • 1
  • 1
Roshan Mathews
  • 5,788
  • 2
  • 26
  • 36
2

Another approach: find the indexes of the substring we're interested in, and extract that substring. Not much shorter, though.

#include <algorithm>
#include <iostream>
#include <string>

using namespace std;

int main() {
  // percentage markers to keep, 30% -- 60% here
  int start = 30, stop = 60;
  string hands = "AA,KK,QQ,JJ,AKs,AKo,AQs,AQo,TT,AJs,ATs,AJo,KQs,KJs,KTs,QJs,\
ATo,QTs,JTs,A9s,A9o,KQo,A8s,A8o,A7s,A7o,A6s,A6o,A5s,A5o,A4s,99,A4o,A3s,A2s,\
KJo,J9s,T9s,Q9s,QJo,KTo,Q9o,88,77,66,QTo,A3o,A2o,JTo,K9s,K8s,K7s,K6s,K5s,K4s,\
K3s,K2s,Q8s,Q7s,Q6s,Q5s,K9o,J8s,T8s,98s,97s,87s,86s,76s,96s,75s,65s,64s,J9o,\
T9o,55,54s,53s,52s,K8o,43s,32s,42s,J7s,T7s,K7o,44,33,22,Q4s,Q3s,Q2s,J6s,J5s,\
T6s,T5s,J4s,K6o,Q8o,J8o,T8o,98o,97o,87o,85s,K5o,K4o,K3o,K2o,95s,74s,76o,65o,\
54o,84s,94s,Q7o,J7o,T7o,Q6o,J3s,T4s,J2s,Q5o,T3s,T2s,Q4o,J6o,86o,T6o,96o,93s,\
Q3o,74o,84o,75o,64o,T2o,94o,53o,93o,63o,43o,92o,73o,83o,52o,82o,42o,62o,72o,\
J5o,63s,92s,73s,Q2o,J4o,83s,85o,82s,T5o,95o,J3o,62s,T4o,J2o,72s,T3o,32o";

  int nhands = count(hands.begin(), hands.end(), ',');
  start = start * nhands / 100;     // percentage -> comma count
  stop = stop * nhands / 100;       // percentage -> comma count

  int start_ = start, stop_ = stop; // copies
  int i = 0, substr_start, substr_end;

  for (i = 0; i < hands.length() && start_ > 0; ++i) {
    if (hands[i] == ',')
      start_--;
  }
  substr_start = i;

  stop_ -= start - 1;               // already counted 'start' commas
  for (; i < hands.length() && stop_ > 0; ++i) {
    if (hands[i] == ',')
      stop_--;
  }
  substr_end = i;

  cout << hands.substr(substr_start, substr_end - substr_start - 1) << endl;
  return 0;
}
Roshan Mathews
  • 5,788
  • 2
  • 26
  • 36
1

I just want to point out that the percentage of the string is different from the percentage of hands.

Different hands are more or less common than others. Specifically, Offsuit hands (e.g. AKo) are three times more likely to occur than the suited versions (AKs), and pairs are half as likely as offsuit hands. This is because of the combinatorics of pulling cards out of a deck.

For pairs there are C(4,2) = 6 possible combinations for each rank.

For suited hands, only the suit varies, so there are 4 possible combinations.

For offsuit hands, there are four suits possible for the first card, but only three for the second (otherwise it would be suited), so there are 12 combinations.

In order to get the proper percentage, in terms of likelihood of the hand being dealt, you need to weight the hands accordingly.

Andrew Prock
  • 6,900
  • 6
  • 40
  • 60