I am writing a code that is supposed to act as a lottery. The lottery numbers available are 1-50, and there are 10 of them. The user is supposed to input one number and the program returns if the user's number matches one of the 10 random lottery numbers. I have gotten all of these parts down, but there is one problem; all 10 of the lottery numbers must be unique. I have gotten 10 unique numbers 1-50, but they weren't very random. The code I have written up to this point seems correct to me, except I know there is something missing (along with the fact that I can clean my code up a lot, but I'm focusing on the objective right now). Right now if I run the program it will return ten zeroes. I need each element in the lottery array to be a unique number from 1-50, and produce different sets of numbers each time i run the program. Any help would be appreciated.
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using std::cout; using std::cin; using std::endl;
void printOut(int[]);
void draw(int[]);
bool check();
int fillFunc[10];
int main()
{
const int arraySize = 10;
int win[arraySize] = {};
srand((unsigned)time(NULL));
draw(win);
cout << "Your lottery numbers are: ";
printOut(win);
}
void draw(int fillFunc[])
{
int i;
for (i = 0; i < 10; i++)
{
if (check() == true)
continue;
fillFunc[i] = 1 + rand() % 50;
}
}
void printOut(int fillFunc[])
{
for (int i = 0; i < 10; i++)
{
cout << " " << fillFunc[i];
}
cout << "\n";
}
bool check()
{
for (int i = 0; i < 10; ++i)
{
if (fillFunc[i] == i)
return true;
}
return false;
}
(also don't ask me why the array has the name "win", this is what my prof wants me to call it)
Because check() always return true. At the start, the array is filled with zeroes so check returns true as win[0]==0 and that remains true forever as nothing changes that value. So in draw you always branch to continue and never modify anything.
To solve the problem one way could be to shuffle the sequence of 1-50 and extract the first 10 values of the shuffled array. You can use the very simple Fisher-Yates algorithm.
To answer your question that you updated in the comments you need to consider a shuffling algorithm.
I will give you an idea of how to do this that is O(n) so you don't have to "loop" thru your current list of numbers and keep checking to see if the new number was already picked...
your lottery max number is 50 so make an array of size 50 that is as follows:
lotteryNumber[0]=1
lotteryNumber[1]=2
...
lotteryNumber[49]=50
to pick a number to put into your "selected" numbers array...
indexToLotteryNumbers = rand() % 50 - numbersPickedSoFar;
randomLotteryNumber[i++] = lotteryNumber[ indexToLotteryNumbers ];
// this is the key "trick"
swap(&lotteryNumber[ indexToLotteryNumbers ], &lotteryNumber[49-numbersPickedSoFar]);
numbersPickedSoFar++;
Theory
The random numbers are the indexes and not the actual values
By swapping the number you picked with the outer element you don't care if your random number generator picks the same index because it will be different the next time.
look at a small example...say you have 1 2 3 4
rand() generates "2"
so your first # is 2 (assume 1-based indexing here) now you swap the (4th) element for the (2nd) element now you have 1 4 3 |2
(here |2 means you can't pick that number again because it's outside the
random # generator range) but you reduce the random # generation from
1-4 to 1 thru 3
rand() generates "1" so your number is "1" and you swap that with the "outer" unpicked number 3 4 |1 2
rand() generates
"2" again! your lottery number is 4 this time... and so on.
I hope this makes sense.
This is what I would do, given your constraints. Rather than check if a number is unique while you are filling the array, just pass the array into the function that chooses the number so it can return a unique value.
I also removed the redundant global array. It could be a source of bugs if you forgot to pass the local array you were working with to any of the functions.
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int getUniqueNumber(int fillFunc[])
{
while(true)
{
//pick number
int val = 1 + rand() % 50;
//assume it's unique
bool unique = true;
for (int i = 0; i < 10; ++i)
{
//if another number matches, it isn't unique, choose again
if (fillFunc[i] == val)
{
unique = false;
break;
}
}
//if it is unique, return it.
if (unique)
{
return val;
}
}
//never reached, but avoids an all control paths must return a value warning.
return -1;
}
void draw(int fillFunc[])
{
for (int i = 0; i < 10; i++)
{
fillFunc[i] = getUniqueNumber(fillFunc);
}
}
void printOut(int fillFunc[])
{
for (int i = 0; i < 10; i++)
{
cout << " " << fillFunc[i];
}
cout << "\n";
}
int main()
{
srand((unsigned)time(NULL));
const int arraySize = 10;
int win[arraySize] = {};
draw(win);
cout << "Your lottery numbers are: ";
printOut(win);
return 0;
}
There are other, perhaps better, ways to select unique numbers in a range, but I went for simple to implement and explain. You can read about some other methods in these questions:
Unique random numbers in an integer array in the C programming language
Unique (non-repeating) random numbers in O(1)?
You only assign a value to fillFunc[i] when i is 10, which is an out of bounds access. Move the assignment to inside the loop.
You have other problems too. If you do continue, you just leave an entry in the array unset.
You should try adding a lot of output statements to your program so you can more easily understand what it's doing. If you prefer, use a debugger to step through it.
Related
This question already has answers here:
Unique (non-repeating) random numbers in O(1)?
(22 answers)
Closed 1 year ago.
My goal is creating an array of 5 unique integers between 1 and 20. Is there a better algorithm than what I use below?
It works and I think it has a constant time complexity due to the loops not being dependent on variable inputs, but I want to find out if there is a more efficient, cleaner, or simpler way to write this.
int * getRandom( ) {
static int choices[5] = {};
srand((unsigned)time(NULL));
for (int i = 0; i < 5; i++) {
int generated = 1 + rand() % 20;
for (int j = 0; j < 5; j++){
if(choices[j] == generated){
i--;
}
}
choices[i] = generated;
cout << choices[i] << endl;
}
return choices;
}
Thank you so much for any feedback. I am new to algorithms.
The simplest I can think about is just create array of all 20 numbers, with choices[i] = i+1, shuffle them with std::random_shuffle and take 5 first elements. Might be slower, but hard to introduce bugs, and given small fixed size - might be fine.
BTW, your version has a bug. You execute line choices[i] = generated; even if you find the generated - which might create a copy of generated value. Say, i = 3, generated is equal to element at j = 0, now your decrement i and assign choices[2] - which becomes equal to choices[0].
C++17 code with explanation of why and what.
If you have any questions left don't hesitate to ask, I'm happy to help
#include <iostream>
#include <array>
#include <string>
#include <random>
#include <type_traits>
// container for random numbers.
// by putting the random numbers + generator inside a class
// we get better control over the lifecycle.
// e.g. what gets called when.
// Now we know the generation gets called at constructor time.
class integer_random_numbers
{
public:
// use std::size_t for things used in loops and must be >= 0
integer_random_numbers(std::size_t number, int minimum, int maximum)
{
// initialize the random generator to be trully random
// look at documentation for <random>, it is the C++ way for random numbers
std::mt19937 generator(std::random_device{}());
// make sure all numbers have an equal chance. range is inclusive
std::uniform_int_distribution<int> distribution(minimum, maximum);
// m_values is a std::vector, which is an array of which
// the length be resized at runtime.
for (auto n = 0; n < number; ++n)
{
int new_random_value{};
// generate unique number
do
{
new_random_value = distribution(generator);
} while (std::find(m_values.begin(), m_values.end(), new_random_value) != m_values.end());
m_values.push_back(new_random_value);
}
}
// give the class an array index operator
// so we can use it as an array later
int& operator[](const std::size_t index)
{
// use bounds checking from std::vector
return m_values.at(index);
}
// reutnr the number of numbers we generated
std::size_t size() const noexcept
{
return m_values.size();
}
private:
// use a vector, since we specify the size at runtime.
std::vector<int> m_values;
};
// Create a static instance of the class, this will
// run the constructor only once (at start of program)
static integer_random_numbers my_random_numbers{ 5, 1, 20 };
int main()
{
// And now we can use my_random_numbers as an array
for (auto n = 0; n < my_random_numbers.size(); ++n)
{
std::cout << my_random_numbers[n] << std::endl;
}
}
Generate 5 random numbers from 1 to 16, allowing duplicates
Sort them
Add 1 to the 2nd number, 2 to the 3rd, 3 to 4th, and 4 to the 5th.
The last step transforms the range from [1,16] to [1,20] by remapping the possible sequences with duplicates into sequences with unique integers. [1,2,10,10,16], for example, becomes [1,3,12,13,20]. The transformation is completely bijective, so you never need to discard and resample.
Preface: Currently reteaching myself C++ so please excuse some of my ignorance.
The challenge I was given was to write a program to search through a static array with a function and return the indices of the number you were searching for. This only required 1 function and minimal effort so I decided to make it more "complicated" to practice more of the things I have learned thus far. I succeeded for the most part, but I'm having issues with my if statements within my for loop. I want them to check 2 separate spots within the array passed to it, but it is checking the same indices for both of them. I also cannot seem to get the indices as an output. I can get the correct number of memory locations, but not the correct values. My code is somewhat cluttered and I understand there are more efficient ways to do this. I would love to be shown these ways as well, but I would also like to understand where my error is and how to fix it. Also, I know 5 won't always be present within the array since I'm using a pseudo random number generator.
Thank you in advance.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
// This is supposed to walk throught the array both backwards and forwards checking for the value entered and
// incrementing the count so you know the size of the array you need to create in the next function.
int test(int A[], int size, int number) {
int count = 0;
for (int i = 0; i <= size; i++, size--)
{
if (A[i] == number)
count++;
// Does not walk backwards through the array. Why?
if (A[size] == number)
count++;
}
cout << "Count is: " << count << endl;
return (count);
}
// This is a linear search that creates a pointer array from the previous "count" variable in function test.
// It should store the indices of the value you are searching for in this newly created array.
int * search(int A[], int size, int number, int arr_size){
int *p = new int[arr_size];
int count =0;
for(int i = 0; i < size; i++){
if(A[i]==number) {
p[count] = i;
}
count++;
}
return p;
}
int main(){
// Initializing the array to zero just to be safe
int arr[99]={0},x;
srand(time(0));
// Populating the array with random numbers in between 1-100
for (int i = 0; i < 100; i++)
arr[i]= (rand()%100 + 1);
// Was using this to check if the variable was actually in the array.
// for(int x : arr)
// cout << x << " ";
// Selecting the number you wish to search for.
// cout << "Enter the number you wish to search for between 1 and 100: ";
// cin >> x;
// Just using 5 as a test case.
x = 5;
// This returns the number of instances it finds the number you're looking for
int count = test(arr, (sizeof(arr)/4), x);
// If your count returns 0 that means the number wasn't found so no need to continue.
if(count == 0){
cout << "Your number was not found " << endl;
return 0;
}
// This should return the address array created in the function "search"
int *index = search(arr, (sizeof(arr)/4), x, count);
// This should increment through the array which address you assigned to index.
for(int i=0; i < count; i++) {
// I can get the correct number of addresses based on count, just not the indices themselves.
cout << &index[i] << " " << endl;
}
return 0;
}
I deeply appreciate your help and patience as well as I want to thank you again for your help.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
My assignment is to have the user type in how many elements are in an array then enter integer number to be put in the array. I then have to sort through the array and find the largest number and print out the elements of the array but if there is a repeat then only print that number one time. I also have to print out the number of times each element in the array occurs. For example if the user types in that there is 5 elements then enters 2, 1, 2, -3, 2 then it should print -3 with 1 count, 1 with 1 count, and 2 with 3 count. So far I have it so it will print out the elements and delete the repeats but I cant get it to print out the correct number of occurrences for each element. This is my code so far.
void findRepeats(int numbers[], int num)
{
int instances = 0;
cout << "Number" << " " << "Occurrences" << endl;
for (int i = 0; i < num; i++)
{
bool matching = false;
instances = 1;
for (int j = 0; (j < i); j++)
{
if (numbers[i] == numbers[j])
{
instances++;
matching = true;
}
}
if (!matching)
cout << numbers[i] << " " << instances << endl;
}
}
Right now its saying all number occur only 1 time
One approach that you could take, is to sort the numbers first, before deciding how many duplicates there are. That way, it will be easier to avoid printing results for the same number more than once, and you also won't have to loop through the entire array for each number.
void findRepeats(int numbers[], int num);
int main(){
int array[] = {2, 1, 2, -3, 2};
findRepeats(array,5);
}
void findRepeats(int numbers[], int num) {
//sort the array first
std::sort(numbers, numbers + num);
int last = numbers[0];
int count = 0;
cout << "Number of Occurrences\n";
for (int i = 0; i < num; i++) {
if (last == numbers[i]) {
++count;
} else {
cout << last << " " << count << '\n';
count = 1;
}
last = numbers[i];
}
if (count > 0) {
cout << last << " " << count << '\n';
}
}
prints:
Number of Occurrences
-3 1
1 1
2 3
I would use map or unordered_map to, well..., map the integer to the number of it's occurrences. It makes things quite simple, as it basically takes care of the duplicates for you.
#include <iostream>
#include <unordered_map>
using namespace std;
void reportCounts(const int numbers[], const size_t size){
unordered_map<int, unsigned int> counts;
//unfortunately range-for here would a little PIA to apply
//or at least I don't know convenient way
for(size_t i = 0; i < size; ++i) {
counts [ numbers[i] ]++; //increase `count` of i-th number
}
//print results
for(auto count : counts ){
cout << count.first << ' ' << count.second << endl;
}
}
int main(){
int array[] = {2, 1, 2, -3, 2};
reportCounts(array,5);
}
Since it's an assignment I am leaving figuring out the c++ shenaningans to you and http://cppreference.com. Keywords are map, map::iterator and maybe associative container which map in an example of.
I do understand that it might be harder to understand than plain implementation of some algorithm, but this is probably close to optimal solution in modern c++, and putting effort into understanding how and why it works should prove beneficial. One should notice how much less of code had to be written, and no algorithm had to be invented. Less implementation time, less place to make mistakes, less testing.
Search your array. For every integer, either record it, or increment your count of it. Repeat process till done, then print it.
How? you say? One approach would be to use parallel arrays to store the unique integers found, and another to store the count of integers. Then print the unique integers and their counts.
Code example of simple search algorithm:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void print(vector<int> valueArray,vector<int> countArray){
for(unsigned int i = 0; i < valueArray.size(); ++i){
cout<<"Found value "<<valueArray[i]<<": "<<countArray[i]<<" times."<<endl;
}
}
void findRepeats(vector<int> testArray,vector<int> &valueArray,vector<int> &countArray){
for(unsigned int i = 0; i < testArray.size(); ++i){
if(valueArray.size() == 0){
valueArray.push_back(testArray[i]);
countArray.push_back(1);
}else{
bool newEntry = true;
for(unsigned int j = 0; j < valueArray.size(); ++j){
if(testArray[i] == valueArray [j]){
countArray[j]++;
newEntry = false;
break;//After find, break out of j-for-loop to save time.
}
}
if(newEntry){
valueArray.push_back(testArray[i]);
countArray.push_back(1);
}
}
}
}
int main(){
vector<int> testArray; //To store all integers entered.
vector<int> valueArray; //To store non-copied integers, dynamically, else handle it yourself.
vector<int> countArray; //To count increments of numbers found, dynamically, else handle it yourself.
testArray = {0,2,5,4,1,3,6,2,5,9,8,7,4,1,2,6,5,4,8,3,2,1,5,8,6,9,8,7,4,4,5,6,8,2,1,3,0,0,1,2,0,2,5,8};//Dummy data.
findRepeats(testArray,valueArray,countArray);//Function to find statistics on testArray.
cout<<"\nPrinting found characters, and number of times found: "<<endl;
print(valueArray,countArray);
return 0;
}
Output would be something like:
Printing found characters, and number of times found:
Found value 0: 4 times.
Found value 2: 7 times.
Found value 5: 6 times.
Found value 4: 5 times.
Found value 1: 5 times.
Found value 3: 3 times.
Found value 6: 4 times.
Found value 9: 2 times.
Found value 8: 6 times.
Found value 7: 2 times.
In the above, I used vectors for simplicity, but if you must do so with c-style arrays, one approach would be to create all three vectors the same size, and keep one integer counter for number of indices used in the valueArray and countArray; they should share, since they're related 1 to 1. And you will need to pass it to the findRepeats function as well.
Having arrays of the same size will ensure that your values and counts will fit in your array; this would happen if every number entered was unique.
I am new to C++, I have a problem of array manipulation. I have an array of X with length 100, I need to fill the value of X with integer value of 1 to 10 (1,2,3,4,5,6,7,8,9,10) randomly.
I know that there will be duplicate, maybe like 1 printed ten times, etc, but that's really what I want.
Here is what I have:
an array of X:
int X[100];
Here is my code snippet:
int* X = NULL;
int* val = NULL;
int length1= 100;
int length2= 10;
X = new int[length1];
val = new int[length2];
int i;
int j;
for (i = 0; i < isi; i++) {
val[i] = i;
for (j = 0; j < length1; j++) {
if (j > i) {
X[j] = val[i];
} else {
X[j] = val[0];
}
cout << "X[" << j << "] = " << X[j] << "\n";
Sleep(1);
}
}
Code above makes the array X from index 0 to 99 has value of 0, then index 0 to 99 has value of 1 and so the other index until the index 0 to 99 has value of 9.
This is not what I want, what I want is to make it (if it is not random) index 0 to 9 has value of 0, then 10 to 19 has value of 1 ... until index 90 to 99 has value of 9. Hope my explanation clear.
I have come to a question in stackoverflow: How would you make an array of 10000 with only values of 1-1000 inclusive?
But still can't resolve my problem my self.
Can someone please give me solution to this.
Thank you in advance
#include <stdlib.h>
int main(int argc, char **argv) {
int r[100];
for (int i = 0; i < 100; ++i) {
r[i] = rand() % 10 + 1;
}
}
For some output, you can #include <iostream> and then std::cout << "r[" << i << "] = " << r[i] << "\n" inside the loop after each assignment.
If you want to seed the random number generator for a different sequence each time, then #include <time.h> and then srand(time(NULL)) before your first call to rand.
You can also use generate function:
#include <iostream>
#include <algorithm>
#include <random>
using namespace std;
int main()
{
int arr[100];
random_device rd;
default_random_engine dre(rd());
uniform_int_distribution<int> uid(0,9);
generate(arr, arr + sizeof(arr) / sizeof(int), [&] () { return uid(dre); });
for (int a : arr)
cout << a << " ";
}
Here are two ways to solve this problem - since this is a learning experience, only pseudo code (and relevant links) are provided. Each "task" can be looked up and solved separately. Note that neither method uses a secondary array.
If the amount of each number in the final result does not need to be the same (eg. 2 might appear 17 times) then consider the following loop-and-assign-random approach. A standard C for-each loop is sufficient.
# for every index pick a random value in [0, 10) and assign it
for i in 0 to last array index:
array[i] = random in range 0, 10
If the amount of numbers need to be the same, then consider filling the array and then shuffling it. The modulus operator is very handy here. (This assumes the array length is a multiple of the group size.)
# fill up array as 0,1,2,3,4,5,6,7,8,9,0,1,2.. (will be 10 groups)
for i in 0 to last array index:
array[i] = i % 10
# and randomly rearrange order
shuffle array
For the shuffle see Fisher-Yates, which even shows a C implementation - there are "more C++" ways, but this is a good technique to learn and practice with loops. (One cool property about Fisher-Yates is that as soon an item is swapped into the current index it is at the final swap location - thus the shuffle loop can be modified to shuffle and immediately perform an action such as displaying the value.)
In both cases a random function should be used; else the numbers will not be .. random.
To loop over the items of a collection the most natural C++ loop is the range based for loop.
In order to assign something to each item, the formal item name should be a reference, thus:
for( auto& item : X )
{
// E.g. assign to item here.
}
This serves up each item of the array, in order, to the code marked by a comment.
There are two different random generators in C++, the old C library one, which is just a pair of functions, and the more general and modern but also not-so-easy-to-grok C++11 thingy. I suggest you google it and try out things. Ask new more specific question if/when stuck.
I think others have pointed it out but you have to first write the pre-compiler directive #include <ctime> and then use the srand function. Most would say don't use that but since you and I are at the basics our teachers, respectively, start us off with that. And it might work with your compiler as well.
Here is a link to learn more about it. I would have commented but I can't.
http://www.cplusplus.com/reference/cstdlib/srand/
My problem is a bit hard to explain, so I will do my best. I'm writing a program that will take a target number and a list of other numbers. I want it to add all possible combinations of numbers from the list until a combination of numbers from the list sums to be the same as the target number. For example, if the target number is 6 and the list provided has the numbers <2, 3, 4, 5>, then the program will print the solution being 2+4=6.
I currently have the program set up with 4 nested loops where the outermost loop checks combinations with the first number as constant. The second loop holds the second number constant, and likewise for the other two. If the target number was 20 for the above list, the program would check in the following manner:
2
2+3
2+3+4
2+3+4+5
2+3+5
2+4
2+4+5
2+5
3
3+4
3+4+5
3+5
4
4+5
5
Then it would return a message saying no solutions were found. This works okay for small lists, but would not work very well if the list contained many small numbers and the target number was a high one. Since the program only has four loops, it can only add 4 numbers at most.
I can't help but thinking that there must be a better way to do this, because for longer lists, the only solution would be to make more nested loops, which isn't practical. Is there a way to go through all combinations of a list of numbers without nested loops?
I hope that this was easy to understand. If you'd like to see my code, let me know. Thank you for your help!
You might use a recursive approach like this:
#include <iostream>
#include <vector>
using namespace std;
vector<bool> active_pos;
vector<int> input;
int recurse (int current_sum, int target_sum, int length) {
if (length < 0) {
return -1;
}
for (int i = 0; i < input.size(); i++) {
if (active_pos[i]) {
continue;
}
active_pos[i] = true;
int tmp_sum = current_sum + input[i];
if (tmp_sum == target_sum) {
return tmp_sum;
}
int next_sum = recurse(tmp_sum, target_sum, length-1);
if (next_sum == target_sum) {
return next_sum;
}
active_pos[i] = false;
}
return -1;
}
int main(int argc, const char **argv) {
input.push_back(2);
input.push_back(3);
input.push_back(4);
input.push_back(5);
input.push_back(6);
int length = input.size();
active_pos.resize(length);
int res = recurse(0, 10, length);
cout << "Result is: " << res << endl;
cout << "Used numbers are: " << endl;
for (int j = 0; j < length; j++) {
if (active_pos[j]) {
cout << input[j] << " ";
}
}
cout << endl;
}
The function recurse() calls itself and decrements the length parameters by one for each time. A vector keeps track of the values which are already taken.
If an instance of recurse() finds a matching sum, it returns that value. If not, it returns -1. If the final result is -1, no matches were found.
I would approach this from the other direction....add all of the numbers from the list together, and if it doesn't equal the target value, your done....if the addition of the list is larger than the target, then start to remove items from the start of you list until you match the target value. If you don't match, (skips by the target value) and the addition value become smaller than your target value, then handle that scenario appropriately.
This should only require 1 loop.
You could represent each combination as N one-bit values, set if that element should be in the combination. Then iterating over all combinations is equivalent to counting from 1 to 2N, with an inner loop to add up the values corresponding to the set bits.
If the set size is 64 or less, then you do this very easily with a uint64_t loop counter. If it's larger, then you probably won't live long enough to see the result anyway.