Dealing from a deck of cards (non repeating cards) - c++

This is a function I have created to try to deal n cards from a deck class of cards. When a card is dealt, it is supposed to be 'removed' from the deck (i.e. can't be dealt again). I thought I solved this by using pointers, and by drawing from the back of the deck minus the amount of cards I have dealt so far. If I call the function again, I need to be drawing from the deck that has cards missing, and since I am not shuffling the deck at any point I thought this method would work.
'dealt' is defined earlier in my code, and starts at 0.
Card is a class that holds a certain suit and value.
I put a sample output of the hands dealt when I call the dealNumber function 6 times and n = 5.
ST CK D3 HJ D9
HK DK SA SQ DT
HK S4 D2 C9 H5
HK H6 H7 H2 H4
HK HK SK S8 C5
HK H9 S3 D8 H8
The 'deck' is ordered this way however:
S6 S2 S7 D7 S9 CQ D4 CA CJ SJ HQ DQ D5 HA DA C4 HT H3 CT D6 C2 S5 H8 D8 S3 H9 C7
C5 S8 SK HK C8 H4 H2 H7 H6 C3 H5 C9 D2 S4 C6 DT SQ SA DK DJ D9 HJ D3 CK ST
The first hand I deal is correct, but the others are not. 'dealt' should be carried over through the deck class regardless, so where am I going wrong?
Hand* Deck::dealingNumber(int p){
Card* dealtCards = new Card[p];
Card* oldDeck = deck;
for (int i = 0; i<n; i++){
dealtCards[i] = deck[(51-dealt)-i];
}
dealt = dealt+n;
deck = new Card[52-dealt];
for (int i = 0; i < 51-dealt;i++){
deck[i] = oldDeck[i];
}
delete[] oldDeck;
PokerHand* hand = new PokerHand(dealtCards);
return hand;

You have an off-by-one error in your second for loop:
for (int i = 0; i < 52 /* change from 51 to 52 */ - dealt; i++){
deck[i] = oldDeck[i];
}

I would take a very different approach using 2 arrays. The first array holds the deck and the second array holds a dealt/not dealt flag.
char cards[52][3]; // 52 cards # 3 characters each
int dealtFlag[52]; // 0=not dealt, 1=dealt
Then choose a random number from 0-51, check that dealtFlag[randNum] is zero, and use that card if it is zero. If it is 1, get a new random number and try again.

Not sure this itself is the problem. Anyway this is a problem:
Modify
for (int i = 0; i < 51-dealt;i++){
deck[i] = oldDeck[i];
}
to
for (int i = 0; i < 52-dealt;i++){
deck[i] = oldDeck[i];
}
Using STL classes for your purpose will be much more simpler.
But personally, I would prefer a stack using linked list or similar.

Related

C++ Arduino: adding and getting values from hashmap returns garbage values

I've got a small program on my Arduino, in which I use the HashMap lib from Wiring framework.
Anyways, the HashMap is of key type char *, and value type char * as well.
I read some keys and values from a file and I try to add them to the map. I read them as Strings, and then I use the .c_str() method to convert them into char *.
When I then print the map, I get very weird values, which I think might be garbage from the memory?
Anyone knows how can I fix that, and why that happens? I was thinking it might have to do something with the temporary values in the memory returned by .c_str(), but I'm not sure. Any help?
Here is the code: (st is just a string and I split it into two, where the : is).
String msgC = st.substring(0, st.indexOf(":") - 1);
const char* messageCode = msgC.c_str();
String msg = st.substring(st.indexOf(":") + 1);
const char* message = msg.c_str();
hashMap[messageCode] = message;
When I print the 'message' and 'messageCode' into the console, they are fine.
Output when I print the hashmap:
Key: rently wiping, hig& Value: B0 D8 0 BE A0 9B 86:Wipers currently wiping, hig&
Key: Value: ⸮pers currently wiping, high speed.
Key: Value: ⸮
EDIT:
When I use String types of the hashMap key and values, I get more strange behavior:
if (dataFile) {
String st;
while (dataFile.available() > 0) {
char s = char(dataFile.read());
if (s!='\n'){
st = st+s;
}
else{
String msgC = st.substring(0, st.indexOf(":") - 1);
String msg = st.substring(st.indexOf(":") + 1);
Serial.print(msgC + " " + msg);
hashMap[msgC] = msg;
st = "";
}
}
Now the first three pairs of msgC and msg are read and stored fine. But the rest get split mid sentence or are not loaded at all. The output from the Serial.print:
1D0 834 B0 D8 0 A0 A0 9B 8 Wipers are off.
1D0 834 B0 D8 0 A8 A0 9B 8 Wipers on, single wipe.
1D0 834 B0 D8 0 A1 A0 9B 8 Wipers are on, not wiping.
(Up until here it's ok)
currently wiping, low speed.
currently wiping, low speed.
tly wiping, medium speed.
tly wiping, medium speed.
urrently wiping, high speed.
urrently wiping, high speed.
Weird stuff. And this did not happen when I used char * in the HashMap, and I did not change anything else in the code. How come that changing the type of HashMap keys and values could affect this reading from a file?
You are adding only pointer to data into hashmap:
String msg = st.substring(st.indexOf(":") + 1);
const char* message = msg.c_str();
hashMap[messageCode] = message;
Once msg is destroyed, the memory pointed by message becomes free for usage, so it is Undefined Behavior.
Your hash map should actually contains String values instead of char*.

how to sum multiple calculations with one string

I would need some universal string of commands, so I could insert it in cells A4, C4, D4, E4 and get those desired numbers across all the other similar cells like these.
So far I tried stuff like: =IF(A1 = A2; SUM(A1 * A2); "1") but still not close with that.
What exactly do you want to do?
Not sure why you reference A11 in your formula, or what you expect from SUM(A1 * A2) (do you want A1+A2? or A1*A2?)
Let's assume you want A4 = 1 if A1 = 1 or A2 = 1 and A4 = 0 otherwise. Then type in A4:
=IF(OR(A1=1; A2=1); 1; 0)
Then copy (or right-drag) A4 and paste it in C4, D4 and E4; the formula will adjust to these columns and work the same.
Please clarify your goal if you want better help :)

Establishing a connection between data given using istringstream and struct/vector

I have the following data in a file, let the columns be [A B C D E]:
a1 b1 c1 d1 e1
a2 b2 c2 d2 e2
a3 b3 c3 d3 e3
.....
All are integers. A is just the serial number. let B be a node having only max of 4 terminals. C represents which terminal of B is taken. Similarly, D is a node having max of 4 terminals and E represents the terminal of D choosen. example: c1 of b1 is connected to e2 of d2.
I have successfully read the data from the files line by line using istringstream and getline as below:
while (getline(infile, line))
{
int i=0;
istringstream iss(line); // string stream
while(getline(iss, temp[i]))
{
cout<< temp[i] << endl;
++i;
};
}
I am not able to conclude on how to save the connections mentions above line to line. I am new to c++ and would appreciate any ideas and implementation. Thanks!
you can just declare a vector<vector<int>> nameVector,(give it a size) and inside of while you put the data. Or be more specific on what you want.

Evaluating Bridge Hands in C++

I am working on a program that is supposed to read in a file (each line in the file represents a hand of 13 cards) and evaluate each bridge hand.
I will ask my specific questions at the end, but because there is a good bit to this program I am going to include all the instructions so you get an idea of what is required.
Here is the text file that will be read in:
2C QD TC AD 6C 3D TD 3H 5H 7H AS JH KH
3C 4C 2D AC QC 7S 7C TD 9C 4D KS 8D 6C
2C 3C KC JC 4C 8C 7C QC AC 5C 9C 6C TC
5H 3S 4D KC 9S 3D 4S 8H JC TC 8S 2S 4C
2S 5D 6S 8S 9D 3C 2H TH
2H 6D %S 8S 7S 4D 3H 4S KS QH JH 5C 9S
2C QD TC AD 6C 3D TD 3C 5H 7H AS JH KD QS
2C QD TC AD 6C 3D TD 2C 5D 7H AS JH KD
2H 6D TS 8Z 7S 4D 3H 4S KS QD JH 5C 9S
With each pair representing a card (the value and the suit).
Legal values include:
2-9
T(10), A(Ace), K(King), Q(Queen), and J(Jack)
And suits:
C(Clubs), S(Spades), D(Diamonds), and H(Hearts)
Once the file is read in, each hand must be sorted first by suit and then by the rank within the suit (aces are high). When the sorting is complete, each hand must be evaluated using the following rules:
Aces = 4
Kings = 3
Queens = 2
Jacks = 1
voids (no cards in a suit) = 3
singletons (one card in a suit) = 2
doubletons (two cards in a suit) = 1
long suits (more than 5 cards in a suit) = 1 count for each card over 5 in number
After being evaluated, each hand should be displayed in the following format:
Example Input:
2C QD TC AD 6C 3D TD 3H 5H 7H AS JH KH
Example Output:
Clubs 10 6 2
Diamonds A Q 10 3
Hearts K J 7 5 3
Spades A
Points = 16
Here are a few specifics about what the program must include:
1. A data structure to hold cards in an ordered manner.
2. A function to read in the hand.
3. A function to evaluate the hand (with support functions).
4. A function to display the hand.
Here is what little code I've been able to come up with. In case it's not clear, the comments are steps I think will need to be done in order for the program to work properly. Right now all it does is open the file, and yes I will be removing the "File is Open" message, I just wanted to be sure the file was actually being open.
//#include <program3.h>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
//Create Array
//char bridgeHands[];
//Open file, if it doesn't exist, exit the program
ifstream bridgeFile;
bridgeFile.open("prog3.dat");
if(!bridgeFile) {
cerr << "Open Failure" << endl;
exit(1);
}
else {
//Read file into array
//Sort array
//Evaluate hands
//Display hands
cout << "File is open" << endl;
}
return 0;
}
I guess my specific question at the moment is this. How do I need to go about creating and loading the array? I have never worked with loading an array from input that is in pairs. Also, how does this work with the data structure?
I'm sure you can tell by now that I'm extremely new at this and am learning as I go (pretty much everything I know how to do in C++ is written in that code), so any help is greatly appreciated. Thank you for your time.
There are a lot of open questions in my mind. First and
foremost: should each hand be on a separate line, or is it just
the next 13 cards, regardless of line breaks. This changes the
way you read hands. In either case, your input file has errors
which must be detected: in the first case, the fifth and seventh
lines have an incorrect format, and in the second, the number of
cards isn't a multiple of 13, so there must be an error
somewhere.
Anyway, the proper way to approach this is to define types
(classes) for the cards and the hand, and defined a user defined
operator>> for each, with the operator>> for hands using the
one for cards. For example:
std::istream& operator>>( std::istream& source, Card& object)
{
char value;
char suit;
source >> std::ws; // skip leading whitespace.
source.get(value); // these do _not_ skip whitespace
source.get(suit);
if ( source ) { // no errors on input...
// Map the characters to the internal representation and write
// them into `object`. This operator may have to be a friend
// to do this.
//
// If one of the characters isn't legal:
// source.setstate( std::ios_base::failbit );
}
return source;
}
For the hand, if your input is line oriented, the best solution
is probably to use std::getline to read the line, then
std::istringstream to parse it. Make sure you check that
there is nothing but white space left once you've read the 13
cards. (If the input ignores line endings, then just reading 13
cards should be sufficient.) Regardless of the strategy, be
sure the check for errors after each read, before using the
values you've read. So you're loop (either on the
std::istringstream or the original source, depending) might
look something like:
int i = 0;
while ( i != 13 && source >> dest[i] ) {
++ i;
}
if ( i == 13 ) {
// Input of 13 cards succeeded...
}
Finally: You're input contains errors (probably intentionally,
to ensure that you test them correctly). Which means the
simplest form of the outer loop won't work correctly (since it
will stop at the first error). If we suppose line oriented
input globally, but the >> operator for hand ignores line
endings and just looks for the next 13 Card:
std::string line;
int lineNumber = 0;
while ( std::getline( source, line ) ) {
++ lineNumber;
std::istringstream parser( line );
if ( parser >> hand >> std::ws && parser.get() == EOF) {
// Line is good, hand contains the instance to be evaluated
} else {
std::cerr << "Input format error in line " << lineNumber << std::endl;
}
}
Concering the condition in the if: we read a hand, then skip
white space; if that succeeds, we verify that we have reached
end of file (otherwise, there's extra garbage at the end of the
line). You can give a more detailed error message if you
separate these different operations out, although to indicate
which card is in error, you'll have to input the 13 cards
directly at this level, rather than using the >> for Hand.
One other suggestion: I would choose an internal representation
which made processing simple, with mapping functions for input
and output. This is probably two enums: one for values (with
the values in the order of their ranking), one for suits (also
in the order of their ranking). This will make the sorting
and the counting significantly easier, and mapping functions are
very easy: for small sets like these, nothing more than an array
with the legal representations: on input, a linear search, and
on output, just index. (Note that this may result in the value
2 having the numeric value 0 internally, since it will be
the first value of the enum.)
Use the ifstream::getline() function for reading and parsing the file. At this link you also find a nice example how you might read the file directly into a std::array:
#include <iostream>
#include <sstream>
#include <vector>
#include <array>
int main()
{
std::istringstream input("abc|def|gh");
std::vector<std::array<char, 4>> v;
// note: the following loop terminates when std::ios_base::operator bool()
// on the stream returned from getline() returns false
for (std::array<char, 4> a; input.getline(&a[0], 4, '|'); ) {
v.push_back(a);
}
for (auto& a : v) {
std::cout << &a[0] << '\n';
}
}
But take a close look whether this is suitable for your case. As an alternative you could omit the last parameter of getline so you really get the lines one by one. Then you'd have to parse these lines using std::string::find() and std::string::substr().

C++ case declaration? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
I am trying to adapt a digital electronics problem to a C++ STL based program.
Originally I have 4 inputs C1, C2, C3, C4. This means I have a total of 16 combinations:
0000
0001
.
.
.
1111
I have a multimap defined by
typedef std::pair<int, int> au_pair; //vertices
typedef std::pair<int, int> acq_pair; //ch qlty
typedef std::multimap<int, acq_pair> au_map;
typedef au_map::iterator It_au;
The no. of simulations depend on the size of the au_map.
For eg: if the au_map.size() = 5 I will have C1, C2, C3, C4, C5. and therefore 2^5 = 32 cases.
For example:
If theau_map.size()=4, I need to simulate my algorithm for 16 cases.
for(It_au it = a_map.begin(); it != a_map.end(); it++)
{
acq_pair it1 = it->second;
//case 0:
//C3 = 0, C2 = 0, C1 = 0, C0 = 0
//Update it1.second with corresponding C values
//simulate algorithm
//case 1:
//C3 = 0, C2 = 0, C1 = 0, C0 = 1
//simulate
.........
//case 15:
//C3 = 1, C2 = 1, C1 = 1, C0 = 1
//simulate
}
Not the best idea. Right now you're doing a lot of useless work by manually setting your C1-C4 and by writing some simulation routines right in your for loop.
Automate it.
Use some abstract State-Simulator mapper (where Simulator actually stands for some concrete functional object).
typedef char State;
struct basic_simulator {
// You could also pass some other parameters to your
// simulator
virtual void operator()(...) = 0
};
struct concrete_simulator : public basic_simulator {
virtual void operator()(...) {
// Do something concrete
// Trolololo
}
};
typedef basic_simulator Simulator;
And in this case your actual wrapper would look like std::map<State, Simulator*> map;
What you need to do next do means getting C1-C4 values from your state which is defined as char. Use bitwise operators.
All your states could be defined as 0-15 numbers converted to binary (2 -> 0010). So to get C1-C4 values you would simply have to make appropriate shifts:
// C1 C2 C3 C4
// -----------
// 1 1 1 1
State state = 15;
for (int i = 3; i >= 0; i--) {
// State of some of the inputs, defined by one bit
InputState C_xx = ((state >> i) & 1);
}
Now simply map all those 0-15 states to appropriate simulating functor:
std::map<State, Simulator*> mapper;
// Generally speaking, you should use some sort of
// smart pointer here
mapper[0] = new concrete_simulator(...);
mapper[1] = ...
What is really cool that you could have only, let's say, 3 or four concrete simulators which would be mapped to some states accordingly.
In this case invoking actual simulation would mean something like:
// Fire appropriate simulation object
(*(mapper[actual_state]))(...);
and making every possible simulation means iterating over every map element.
Update: the same technique could be used for states where you have more than 4 inputs / single input state can have more than two possible values.
Just write an appropriate mapping function and state generator.
Hum... why not letting a for loop enumerate the various combinations for you ?
for (size_t i = 0; i != 16; ++i)
{
bool const c1 = i & 1;
bool const c2 = i & 2;
bool const c3 = i & 4;
bool const c4 = i & 8;
// your algorithm
}
A bit easier than setting them by hand.