This question already has answers here:
srand() — why call it only once?
(7 answers)
Closed 4 years ago.
I am having trouble with shuffling a deck of cards in C++.
I have a deck of cards class. Within the class I have a vector of objects, which are the cards within the deck, and I am trying to shuffle the elements within the vector to shuffle the cards. However, the function I wrote to do it appears to be just shifting everything over every iteration instead of swapping it with another random element within the vector. I'm sure its something really simple and stupid that I am missing, but I just haven't been able to figure it out yet. Any help would be greatly appreciated.
Thanks.
void shuffle(int seed = 0)
{
for (int i = 0; i < 100; i += 1)
{
for (unsigned int i = 0; i < deck.size(); i++)
{
card *swap = deck[i];
srand(time(NULL) + seed);
int temp = rand() % 52;
deck[i] = deck[temp];
deck[temp] = swap;
}
cout << "shuffled deck: ";
for (unsigned int i = 0; i < deck.size(); i++)
cout << deck[i]->compare() << " ";
cout << endl;
}
}
This is being called within a probability function I made, inside a loop. The seed for the shuffle function is the iteration of the loop.
This is a sample of part of the output in one iteration
Initialize your RNG just once, for example in your main() function
srand(time(NULL));
Then one of simplest methods of shuffling is just swap each item from the end to the beginning with a random element from those preceding it. Note the item to swap can be the same to be swapped – this way the item can also stay where it already is.
void shuffle()
{
for (int i = 0; i < 100; i ++)
{
for (unsigned int n = deck.size(); n > 1; --n)
{
unsigned swapPosition = rand() % n;
card *swap = deck[n-1];
deck[n-1] = deck[swapPosition];
deck[swapPosition] = swap;
}
cout << "shuffled deck: ";
for (unsigned int n = 0; n < deck.size(); n++)
cout << deck[n]->compare() << " ";
cout << endl;
}
}
Related
c++
When printing to console, if function execution is sequential it would seem logical the ordered array would be printed after calling insertionSort, however order list does not print until next loop. Any help would be appreciated.
#include <stdio.h>
#include <iostream>
#include <array>
using namespace std;
void insertionSort(int* array, int size) {
for (int i = 1; i < size; i++) {
int key = i - 1;
while (i > 0 && array[key] > array[i] ) {
int tmp = array[i];
array[i] = array[key];
array[key] = tmp;
i -= 1;
key -= 1;
}
}
}
const int ARRAY_MAXSIZE = 5;
int main(void) {
int *array = (int*)calloc(ARRAY_MAXSIZE, sizeof(int));
int input;
cout << "Enter 5 digits\n";
for (int size=0; size < ARRAY_MAXSIZE; size++) {
cout << size << " index ";
cin >> input;
array[size] = input;
insertionSort(array, size);
for (int j=0; j <= size; j++) {
cout << array[j];
}
cout << '\n';
}
}
Console Entry
This is a classic off-by-one error. Your insertionSort expects you to pass the number of elements to sort via the parameter size. But your main loop is always holding a value that is one less than the size immediately after adding an element.
I want to say that bugs like this are easily discovered by stepping through your program's execution with a debugger. If you don't know how to use a debugger, start learning now. It is one of the most important tools used by developers.
Anyway, the quick fix is to change your function call to:
insertionSort(array, size + 1);
However, as Paul McKenzie pointed out in comments, it's a bit crazy to do this every time you add a new element because your function sorts an entire unsorted array. Your array is always nearly sorted except for the last element. You only need to call that function once after your input loop is done:
// Read unsorted data
for (int size = 0; size < ARRAY_MAXSIZE; size++) {
cout << size << " index ";
cin >> input;
array[size] = input;
}
// Sort everything
insertionSort(array, ARRAY_MAXSIZE);
// Output
for (int j = 0; j < ARRAY_MAXSIZE; j++) {
cout << array[j];
}
cout << '\n';
But if you want every insertion to result in a sorted array, you can "slide" each new value into place after inserting it. It's similar to a single iteration of your insertion-sort:
// Sort the last element into the correct position
for (int i = size; i >= 1 && array[i] > array[i - 1]; i--)
{
std::swap(array[i], array[i - 1]);
}
Even better, you don't need to swap all those values. You simply read the value, then shuffle the array contents over to make room, then stick it in the right spot:
// Read next value
cin >> input;
// Shuffle elements to make room for new value
int newPos = size;
while (newPos > 0 && array[newPos - 1] > input) {
array[newPos] - array[newPos - 1];
newPos--;
}
// Add the new value
array[newPos] = input;
I want a function or loop to run through the array and print each element out until it has printed 10 elements. In which case, a new line is started and the printing continues. eg. 1 2 3 4 5
6 7 8 9 10
This is for a program that works an array like a 50's housewife performing many calculations and alterations to said array.
This is my current attack on the logic behind my issue.
int main()
{
test = new int[100];
for (int i = 0; i < 100; i++){
//Set array to rand
test[i] = rand() % 44 + 55;
}
printf("original List\n");
for (int i = 0; i < 100; i++){
// print original order
printf("%d\n", test[i]);
}
sortArr;
// function call sort array ascend
printf("\Sorted List\n");
for (int i = 0;i < 100;i++) {
// print sorted order
printf("%d , ", test[i]);
int temp;
//temp counter for width of printout
for (temp = 0;temp < 10;temp++) cout<< "\n" << endl;
sum += test[i];
}
Expected is a block of output consisting of 100 array elements in a grid with a width of 10 elements per line.
Actual result is a mess of new line loops and further headache to me.
Pretty common issue just use a modulus based on the index i:
for (int i = 0;i < 100;i++) {
printf("%d , ", test[i]);
if ((i + 1) % 10 == 0) {
printf("\n");
}
}
If you want nicely formatted output however you'll need:
#include <iomanip>
and
std::cout << std::setw(/*max_len*/) << test[i];
The simplest solution would be to print the delimiter (i%10 == 0) ? "\n" : ", ". You correctly recognized that taking the remainder on every iteration of the loop is inefficient, and wanted to write one that would print ten elements followed by a newline.
The trick there is to write an inner loop that increments a second counter, j, do all your output within the inner loop, and then update i at the bottom of the outer loop. A simplified example:
#include <array>
#include <iostream>
#include <stdlib.h>
#include <time.h>
using std::cout;
int main()
{
constexpr size_t ARRAY_LEN = 100;
std::array<int, ARRAY_LEN> test;
{
// Quick and dirty initialization of the random seed to the lowest 30
// or so bits of the system clock, which probably does not really have
// nanosecond precision. It’ll do for this purpose.
timespec current_time;
timespec_get( ¤t_time, TIME_UTC );
srand(current_time.tv_nsec);
}
for (int i = 0; i < test.size(); i++){
//Set array to rand
test[i] = rand() % 44 + 55;
}
for ( int i = 0, j = 0;
i < test.size();
i += j ) {
for ( j = 0; j < 10 && i + j < test.size(); ++j ) {
cout << test[i + j] << ' ';
}
cout << '\n';
}
return EXIT_SUCCESS;
}
Note that the version you wrote does not initialize the standard library’s random seed, so you get the same (poorly-distributed) random numbers. You could write a version that uses the much superior STL random-number generators and perhaps <chrono>, instead of the C versions, but that’s a bit outside the scope of your question.
The purpose of my code is to add the elements of a vector together into one integer. This is for Problem #1 on Project Euler:
https://projecteuler.net/problem=1
Here is my code:
int main()
{
int max_count = 1000; //The upper bound
//Loop for filling vector
for (int i = 1; i <= max_count; ++i){
int counter[max_count];
if (counter[i] % 3 == 0|| counter[i] % 5 == 0){
vector <int> start_point = {};
start_point.push_back (counter[i]);
for (auto& n : start_point){
int sum_of_elems = 0;
sum_of_elems += n;
cout << sum_of_elems;
}
}
}
return 0;
}
Currently, my code is outputting the following and I cannot figure out why.
32766143547943202305202750000-4646761603276630-76434810000-76434582500-464677056327662448-4646770403276632766-46467703232766327666032766230586999-970904238-95777621723084852023084852032766-970904244-46467688032766230624075-970911300230826120-1916976912327663276623063434032766230634681-957776214230826120140084992032766-970911280327660003276603276630-4646761603276623058081332766-464676440327663276632766230831712230745153065793306031200003276623074515300-191647711200023084852023074515365793360036000002308224802307451533657937207200-46467616032766000023083171232766230595552230831712032766327660-46467619232766230577342230822480230829920000-46467616032766230822480230829960-46467264032766230540223001920409600-46467247232766327661920409600-46467220832766000000000011072962560230556921230818160-4646738403276619204096000000230510592-1572142422000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001920169263100000170147416279176918919693827240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
You're reinitializing your sum variable on each loop, so you end up just printing the individual values. You're also mixing looping and summing, which is complicating your code; either skip the vector entirely (just have a summing loop), or fill it completely, then sum it.
I can't give much more useful advice because you've got a lot of associated problems here. You declare counter without initializing it, then read from uninitialized memory to populate start_point.
Point is, most of your variables need to be declared outside the loops (so they're not repeatedly reinitialized from scratch on each loop), your output should be after the loops, and counter needs real data so you're not invoking undefined behavior.
Removing vectors and other unnecessary variables, the code can be simplified to:
#include <iostream>
int main()
{
int max_count = 1000; //The upper bound
int sumOfMultiples = 0;
for (int i = 1; i < max_count; ++i)
if (i % 3 == 0 || i % 5 == 0)
sumOfMultiples = sumOfMultiples + i;
std::cout << "Sum of Multiples of 3 and 5 below 1000 is: " << sumOfMultiples << "\n";
return 0;
}
Output is:
Sum of Multiples of 3 and 5 below 1000 is: 233168
as the title says I'm attempting to compare elements in an array. My intent is to have the user enter 3 integers into the program, thereafter it should increment through this array comparing the the 1st number to the 2nd, and so forth and swapping the element's from order of lowest to highest.
My issue currently is that it will swap the first and second elements but the third causes an integer overflow due to me comparing and assigning an integer in an index higher than the initialized array can hold.
I'm currently drawing a blank as to how I could still compare these numbers in this manner without causing it to overflow.
A hint or perhaps a whole different perspective would be appreciated.
#include "E:/My Documents/Visual Studio 2017/std_lib_facilities.h"
int main()
{
cout << "Enter three integers: \n";
int numbersArray[3];
int temp = 0; //This lets us hold our integers temporarily so we can swap them around in the array
//This enters integers as elements in the array
for (int i = 0; i < 3; i++)
{
cin >> numbersArray[i];
}
//This should swap the elements from smallest to greatest
for (int i = 0; i = 3; i++)
{
if (numbersArray[i] > numbersArray[i+1])
temp = numbersArray[i];
numbersArray[i] = numbersArray[i+1];
numbersArray[i+1] = temp;
//swap(numbersArray[i], numbersArray[++i]);
}
//This prints the index's containing the elements in the array
for (int i = 0; i < 3; i++)
{
cout << numbersArray[i] << ' ';
}
cout << endl;
keep_window_open();
return 0;
}
You will need to modify this to suit your needs, but this should get you on the right track. One important thing to investigate is how you decided to sort the elements. Your sorting needs to be looped, otherwise, you won't necessarily sort the entire array (depending on your inputs).
#include <iostream>
using namespace std;
int main()
{
cout << "Enter three integers: \n";
int numbersArray[3];
int temp = 0; //This lets us hold our integers temporarily so we can swap them around in the array
//This enters integers as elements in the array
for (int i = 0; i < 3; i++)
{
cin >> numbersArray[i];
}
for(int loop = 0; loop <3; loop++){
//This should swap the elements from smallest to greatest
for (int i = 0; i < 2; i++)
{
if (numbersArray[i] > numbersArray[i+1]){
temp = numbersArray[i];
numbersArray[i] = numbersArray[i+1];
numbersArray[i+1] = temp;
}
//swap(numbersArray[i], numbersArray[++i]);
}
}
//This prints the index's containing the elements in the array
for (int i = 0; i < 3; i++)
{
cout << numbersArray[i] << ' ';
}
cout << endl;
return 0;
}
Disclaimer: I know that parallel arrays are awful and should be avoided and that selection sort is not the most efficient sort, but in this case that's the way the boss man wants it done. I have looked at a lot of different websites and none that really seem to nail down an answer. Also, it is probably good to point out that I am new to C++ and only know fairly basic coding and debugging.
I have two simple parallel arrays and am trying to design a simple selection sort that sorts one of the arrays, and then swaps the elements in the second array accordingly. I have the selection sort part working, but it does not seem to swap the elements in my second array correctly.
Here is what my output looks like:
1 (jibberish)
2 (jibberish)
3 (jibberish)
4 (jibberish)
5 (jibberish)
Where I have (jibberish) the console does not form any identifiable letter, just odd shapes (if it's helpful, the last element that is output is a heart).
Here's what it is supposed to look like:
1 a
2 b
3 c
4 d
5 e
Now I realize that I could easily run a selection sort on the second array in this scenario, but my point is to get the second array to swap elements respective to what the selection sort does to the first array.
Is there any way to keep these arrays lined up correctly? I've been trying to solve this issue for most of the day and I'm sure it's a fairly simple thing to figure out, but my brain is shot.
Below is my code, thanks in advance for looking at it.
#include "stdafx.h"
#include <iostream>
using namespace std;
//Function Prototypes
void sort(int num[], char alph[], int size);
//Selection sort function
void sort(int num[], char alph[], int size)
{
int startScan;
int minIndex;
int minValue;
for (startScan = 0; startScan < (size - 1); startScan++) //Moves through the elements
{
minIndex = startScan;
minValue = num[startScan];
int index = 0;
for (index = startScan + 1; index < size; index++) //Compares the elements
{
if (num[index] < minValue)
{
minValue = num[index];
minIndex = index;
}
}
num[minIndex] = num[startScan];
num[startScan] = minValue;
alph[minIndex] = alph[startScan];
alph[startScan] = alph[index];
}
}
//Main
int _tmain(int argc, _TCHAR* argv[])
{
int num[] = {5, 3, 1, 4, 2};
char alph[] = { 'e', 'c', 'a', 'd', 'b' };
int const SIZE = 5;
//Prints out unsorted array
cout << "This is the unsorted arrays." << endl;
cout << endl;
for (int count = 0; count < SIZE; count++)
{
cout << num[count] << " \t ";
cout << alph[count] << endl;
}
cout << endl;
cout << endl;
//Calls the sort function
sort(num, alph, SIZE);
//Prints out the sorted array
cout << "This is the sorted array." << endl;
cout << endl;
for (int count = 0; count < SIZE; count++)
{
cout << num[count] << " \t";
cout << alph[count] << endl;
}
//Pause
char temp[50];
cin >> temp;
return 0;
}
EDIT: I edited the
alph[minIndex] = num[startScan]
issue so it reads correctly now as:
alph[minIndex] = alph[startScan]
I am now getting this as an output:
1 (jibberish)
2 (jibberish)
3 (jibberish)
4 (jibberish)
5 e
EDIT 2: I edited the line of code under my previous edit and the arrays are now lining up properly and I am no longer getting a bunch of jibberish for outputs. Below is the edited sort function of my code:
//NOTICE temp VARIABLE CHANGES!
void sort(int num[], char alph[], int size)
{
int startScan;
int minIndex;
int minValue;
int temp;
for (startScan = 0; startScan < (size - 1); startScan++) //Moves through the elements
{
minIndex = startScan;
minValue = num[startScan];
temp = alph[startScan];
int index = 0;
for (index = startScan + 1; index < size; index++) //Compares the elements
{
if (num[index] < minValue)
{
minValue = num[index];
minIndex = index;
temp = alph[index];
}
}
num[minIndex] = num[startScan];
num[startScan] = minValue;
alph[minIndex] = alph[startScan];
alph[startScan] = temp;
}
}
The best solution might be to change your
num[minIndex] = num[startScan];
num[startScan] = minValue;
char temp=alph[minIndex];
alph[minIndex] = alph[startScan];
alph[startScan] = temp;
to this which does the job and really can't be made any simpler.
std::swap(num[minIndex], num[startScan]);
std::swap(alph[minIndex],alph[startScan]);
See this line:
alph[minIndex] = num[startScan];
Second faulty line:
alph[startScan] = alph[index];
It should be:
alph[startScan] = alph[minIndex];
By the time the code exits of the inner loop, size has a value of one beyond the array size.
My advice: Use an IDE and the debugger to follow up code execution and examine variables. Also, my first hint should have gotten you looking at incorrect indexes. C++ does not care to check array bounds by default. You usually get garbage when getting out of bounds or following a incorrect pointer. You can remedy the first problem by selecting a compiler option to check for array bounds. That will slow down your application during development time but can be removed once everything works correctly.