Entering 20 numbers into an array with no duplicates - c++

int main()
{
int theArray [20] = {0};
int userInput = 0;
int populateCount = 0;
cout << "Enter 20 integers between 10 and 100 inclusive. " << endl;
while (populateCount < 20)
{
cin >> userInput;
theArray[populateCount] = {userInput};
if (userInput<10||userInput>100)
{
cout << "That is not a legal input. " << endl;
populateCount - 2;
}
else
{
populateCount++;
}
}
cout << "\n";
for (int i = 0; i < 20; i++)
{
cout << theArray[i] << endl;
}
}
I've got the baseline of my code done. The user enters twenty numbers and they're added to the array. If it's less than 10 or greater than 100 it's not a legal input, I subtract from the count, and they're allowed to go again. Then after the user finishes plugging in numbers it prints the array. However, I've been trying different if statements inside the array to eliminate duplicates, such as (if theArray[i] == theArray[i+1] then [i+1] = 0) I suppose that could work if I incorporated a sort to get all the 0's at the end, but is there a more efficient way to do this?

Before I go to the answer I suggest we clean it up slightly to make the problem more clear and remove other confusion.
Misconception
The statement populateCount - 2 has no effect.. instead you are simply not incrementing populateCount which is why the loop doesn't advance.
I would suggest something of this format within the loop. It puts the 'happy' path first, which will also make for some clearer ways to handle the second part.
if (userInput >= 10 && userInput <= 100 ) {
theArray[populateCount++] = userInput;
}
else {
std::cout << userInput << " is not legal input, must enter value "
<< "between 10 and 100. " << std::endl;
}
Preface
Before we attack the problem first let's refactor so that we can break it down to a single function so that as we work we don't disturb everything else as well as gain flexibility for testing and simplify readability.
Refactor
/* this code is responsible for doing what is needed to
* only insert unique items */
bool insert( const int& input, int* array, int num_elements ) {
// the fun part!
// more to follow shortly
};
/* gets user input forcing input to be between min and max */
int getUserInput(int min, int max) {
bool found = false;
int result = 0;
/* this can be done with less code but this makes it easy
* to see whats going on */
while ( !found ) {
cout << "Please enter a value between " << min << " and " << max << "." << endl;
cin >> result;
if ( result >= min && result <= max ) {
found = true; //yes we could break or return from here
} else {
cout << result << " invalid. "<< endl;
}
}
return result;
};
void printArray( const int* array, const int& size ) {
for (int i = 0; i < size; i++)
{
cout << array[i] << endl;
}
};
int main()
{
const int totalElements = 20;
int theArray [totalElements] = {0};
int userInput = 0;
int populateCount = 0;
int minVal = 10;
int maxVal = 100;
cout << "Enter " << totalElements << " integers between "
<< minVal << " and " << maxVal << " inclusive. " << endl;
while ( populateCount < numElements )
{
//this will percievably loop until it's good
userInput = getUserInput(minVal, maxVal);
if ( insert( userInput, theArray, populateCount ) )
++populateCount; //increments if we did insert it
}
}
cout << endl;
printArray( theArray, totalElements );
}
Attacking the problem
Ok so now our problem is simple, we just have to write the insert function. There are a couple of choices here, you can check each element in turn which as you said can be slow, O(n), or we could sort the array to make it quick, O(log n) + cost of sorting. Other possibilities I presume aren't available are using a std::set instead of an array, or using STL to do the work of sorting and finding. Note that in these modes insert won't actually do an insertion if the number is already present.
Another unique idea is to use an array of bools size max-min, and simply flag the index of input-min as true when you find it. This will be fast at the cost of size depending upon the gap between min and max. (this is essentially a hash function)
The advantage we are at from a refactor is that you can in turn write and try each of these solutions and even feed them the same canned input now that we've refactored so that you can try and time each one. For timing I would heavily suggest you add lots of numbers and consider greatly expanding the min and max to understand the scalability of each choice

Related

Find the smallest value in a vector

I am pretty new when it comes to programming with STL and I thought I was getting the hang of it. But I am a little perplexed about this one bit. My goal is to take in 5 values, then print out my values, print the highest value among them, print the average, and print the lowest among them ( my problem ). It seems that my variable "low" is given the value of 0 and I do not know why this is. I have tested to see if my values are being read in and to my knowledge, they are. So if anyone could please enlighten me to why I cannot seem to get the proper lowest value, I would greatly appreciate it. Thank you for your time.
vector<double> vecList;
int x = 0;
double high = 0;
double low = 0;
double sum = 0;
cout << "Enter Integer Values, then press Ctrl(z) to Quit:" << endl;
for (int i=0; i < 5; i++)
{
cin >> x;
sum = sum + x;
vecList.push_back(x);
}
vector<double>::iterator intVecIter;
cout <<"List contains: ";
for (intVecIter = vecList.begin(); intVecIter != vecList.end(); ++intVecIter)
cout << *intVecIter << " ";
for (int i=0; i < 5; i++)
{
if(vecList[i] > high)
{
high = vecList[i];
}
// prints out "0"
if(low > vecList[i])
{
low = vecList[i];
}
}
cout << endl << "Largest: "<< fixed << setprecision(2) << high << endl;
cout << "Smallest: "<< fixed << setprecision(2) << low << endl;
cout << "Average: " << fixed << setprecision(2)<< (sum/5);
return 0;
Since you are trying to learn STL, take a look at the algorithms library and it has some helper functions which will give the min, max and sum (accumulate is the actual function name) for a given range.
you need to initalize low to a big value not 0, otherwise this
if(low > vecList[i])
is never true

Mysterious Stack Overflow

So I wrote a program that utilizes the euclid algorithm to find GCD's of 2 ints.
The user enters one int (n), then the program takes every possible integer combination between 8 and n, finds their respective GCD's (recursively), and prints which GCD calculations required the most modulus operations.
I got the program working, but I get a stack overflow at around n=50, and it needs to work to at least 3000.
I've reviewed my code for a while and cannot find the problem.
#include<iostream>
#include <math.h>
using namespace std;
int cost, gcd, greatestCost, n, beginningA, beginningB, finalA, finalB, finalGCD, iteration;
void findGCD(int num1, int num2, int startingCost) {
//findGCD
//finds GCD of every combination (a,b) from i to n
//prints those with the greatest number of modulus operations
int a = num1;
int b = num2;
cost = startingCost;
cost++;
if (b%a > 0) {
//cout << "gcd(" << b << "," << a << ") = ";
findGCD(b%a, a, cost);
}
else {
gcd = a;
if (cost > greatestCost) {
greatestCost = cost;
finalA = beginningA;
finalB = beginningB;
finalGCD = gcd;
}
//cout << "gcd(" << b << "," << a << ") = " << gcd << " With a cost of: " << cost << endl;
//do next iteration (2,8), (3,8) etc...
if (++beginningA <= beginningB) { //beginning A goes from 1-i first
findGCD(beginningA, beginningB, 0);
}
else {
if (beginningA <= n) { //begin next cycle with new b value (1,9), (2,9) while b <= n
beginningA = 1; //reset to 1 so it will increment from 1-i again
cout << "At i=" << iteration++ << "; gcd(" << finalA << "," << finalB << ") = " << finalGCD <<
" took " << greatestCost << " modulus operations" << endl;
findGCD(beginningA, ++beginningB, 0);
}
else //When it tries to continue iterating with a number > n
//print the last, most intensive, iteration and stop
cout << "At i=" << iteration++ << "; gcd(" << finalA << "," << finalB << ") = " << finalGCD <<
" took " << greatestCost << " modulus operations" << endl;
}
}
}
int main() {
greatestCost = 0; //cost of the iteration with the most modulus operations
beginningA = 1;
beginningB = 8;
iteration = 8;
cout << "Enter an integer greater than 8 " << endl; //receive n from user
cin >> n;
if (n <= beginningB) //begin GCD search, granted user input > 8
cout << "Error!!! integer must be greater than 8";
else
findGCD(beginningA, beginningB, 0); //algorithm begins at (1,8)
return 0;
}
At this point the only thing I can think of as the problem is something I've done in C++ that I shouldn't (I am new to C++ and transferred over from java)
Sample Output
Things I've tried:
splitting the gcd function into 2
passing only references through the functions
First of all your explanation is unclear, from you code I understood that for every 8<=i<=n you take all possible x, y where y<=i and x<=y and calculate which gcd require most steps.
I've rewritten your code so that findGCD only finds gcd of 2 number, while incrementing some global cost variable.
#include<iostream>
#include <math.h>
using namespace std;
int cost, gcd, greatestCost, n, beginningA, beginningB, finalA, finalB, finalGCD, iteration;
int findGCD(int a, int b) {
cost++;
if (b%a > 0)
return findGCD(b%a, a);
else
return a;
}
int main() {
greatestCost = 0; //cost of the iteration with the most modulus operations
beginningA = 1;
beginningB = 8;
iteration = 8;
cout << "Enter an integer greater than 8 " << endl; //receive n from user
cin >> n;
if (n <= beginningB) //begin GCD search, granted user input > 8
cout << "Error!!! integer must be greater than 8";
else {
for ( int i = beginningB; i <= n; i++ ) {
int greatestCost = 0, gcd0 = 1, i0 = 0, j0 = 0;
for ( int t = beginningB; t <= i; t++ )
for ( int j = 1; j <= t; j++ ) {
cost = 0;
int gcd = findGCD(j, t);
if ( cost > greatestCost ) {
greatestCost = cost;
gcd0 = gcd;
i0 = t;
j0 = j;
}
}
cout << "At i=" << i << "; gcd(" << j0 << "," << i0 << ") = " << gcd0 <<
" took " << greatestCost << " modulus operations" << endl;
}
}
return 0;
}
The stack overflow you're getting is caused by using too deeply recursive calls: Every time you call a function a new stack frame (holding local variables, parameters and possibly other stuff) is created in the (call) stack. This frame is freed only when returning (normally or via exception) from the function. But with recursive calls you don't return from the first function call before returning from the second, which in turn only returns after the third and so on. Thus stack frames are piling up on the stack, which is commonly about the size of around 8 kB, until all available memory for the stack is used: That's the stack overflow (you put too much on it, thus it overflows).
This can be solved by using iteration (using loops) instead:
An outer one incrementing from 8 up to the user supplied maximum, as well as an inner one incrementing from 0 to the value of the outer loop's current iteration variable. This gives you all the pairs of values you want to operate on.
Calculating the greatest common divisor and its cost should be factored out into a function.
The only thing left is calling that function from within the loops and some how keeping track of the maximum.
#include <iostream>
#include <vector>
#include <utility>
using namespace std;
unsigned gcd(unsigned a, unsigned b, unsigned * const cost) {
if (cost) {
*cost = 0;
}
while (b != 0) {
auto const rest = a % b;
if (cost) {
++(*cost);
}
a = b;
b = rest;
}
return a;
}
int main() {
unsigned const n = 3500;
unsigned greatestCost = 0;
vector<pair<unsigned, unsigned>> pairs;
for (unsigned b = 8; b <= n; ++b) {
for (unsigned a = 0; a <= b; ++a) {
unsigned cost;
gcd(a, b, &cost);
if (cost == greatestCost) {
pairs.emplace_back(a, b);
} else if (cost > greatestCost) {
pairs.clear();
pairs.emplace_back(a, b);
greatestCost = cost;
}
}
}
cout << "Greatest cost is " << greatestCost << " when calculating the GCD of " << endl;
for (auto const & p : pairs) {
cout << "(" << p.first << ", " << p.second << ")" << endl;
}
return 0;
}
(Live)
Note in particular that I'm not using any global variable.
The above might make you feel that recursion is an unusable, useless construct. This is not the case. Many algorithms are most cleanly expressed using recursion. When putting the recursive call as the last statement, then an optimisation known as tail call optimisation can be used: Then the called function is reusing the stack frame of the calling function, thus not using any more memory.
Unfortunately this optimisation is quite tricky to implement in a language like C++ due to various reasons.
Other languages, mostly functional ones, use it and thus also recursion instead of loops, though. An example of such a language is Scheme, which even requires implementations to be able to make that aforementioned optimisation.
As a final note: You could implement the GCD calculation using recursive calls here, since as you see the maximum depth will be 17 + 1 which should be small enough to fit on any (outside of embedded systems) call stack. I'd still go with the iterative version though: It has better performance, better fits the idiom of the language and is the "safer" way to go.

C++ Arrays, Array Conversion not working

I've been stuck on a problem for quite a while today, and despite my searching the internet, I'm not sure as to what I should do. This program (that I will post the source code to) is supposed to be based off of the Birthday Paradox, and help us to prove it correct.
The idea is that we have multiple arrays, one of which simulates the paradox by counting the times that there is NOT a matching birthday pair, another which takes that array and creates a ratio(array value/over total iterations) and another that creates a theoretical array ratio value.
Now, this is where I"m stuck. I can get the first two functions to work perfectly, birthdayFrequency and ratioArray, but the next one idealArray I cannot get to work properly. Both ratioArray and idealArray should be a double data type, and ratioArray stores it properly as a double.
However, idealArray does not. It stores the data in the array positions as integers. I want to know if there's something I missed, something that might have caused me to accidentally make the array an integer.
*I'm going to apologize, the code is really long. Also, I can't get it all to fit in a code window. I apologize.
using namespace std;
//Arraytype declarations
typedef int Birthday[365];
typedef bool Counter[365];
typedef double Ratio[365];
void ratioArray(int, Birthday, Ratio);
void idealArray(Ratio);
void outputTable();
int randomInt(int);
//Main function
int main()
{
Birthday array = {0};
Ratio vector = {0};
Ratio matrix = {0};
int seed;
int runs;
//Prompt the user for the number of times the simulation is to be run.
cout << "Hello and welcome to the Birthday Paradox Simulator. " << endl;
cout << "This program uses simulated runs to calculate and verify the paradox." << endl << endl;
cout << "Please enter the number of runs you want done. IMPORTANT, must be a positive integer." << endl;
cin >> runs;
while (runs <= 0)
{
cout << "That's an invalid value. Please enter a positive number." << endl;
cin >> runs;
}
//Prompt the user for a non-negative integer seed value
cout << "Please input a seed to be used for randomly generating numbers. It must be an integer, and non-negative." << endl;
cin >> seed;
while (seed < 0)
{
cout << "I'm sorry, that is an invalid value. Please enter a non-negative number)" << endl;
cin >> seed;
}
//Seed the srand function
srand(seed);
//Call birthdayFrequency function
birthdayFrequency(runs, array);
//Call ratioArray function
ratioArray(runs, array, vector);
//Call idealRatioArray function
idealArray(matrix);
//Testing values
cout << array[1] << endl;
cout << array[2] << endl;
cout << array[3] << endl;
cout << vector[1] << endl;
cout << vector[2] << endl;
cout << vector[3] << endl;
cout << matrix[1] << endl;
cout << matrix[2] << endl;
cout << matrix[3] << endl;
//Call outputTable function
outputTable();
return 0;
}
void birthdayFrequency(int n, Birthday number)
{
int iteration = 0;
int value;
int boundary = 364;
//For loop for n iterations
for ( int k =0 ; k < n ; k++)
{
Counter boolean = {0};
iteration = 0;
//Randomly mark birthdays until there's a duplicate using a for loop
for ( int i = 0; i < 366; i ++)
{
value = randomInt(boundary);
if (boolean[value] == 1)
break;
else
boolean[value] = 1;
number[iteration]++; //Increment the frequency array for every non-match
iteration++;
}
}
}
void ratioArray(int n, Birthday number, Ratio vectors)
{
double ratio;
//For loop for the number of runs, storing the value of ratios to the total number of runs.
for ( int i = 0 ; i < 364 ; i++)
{
ratio = (double)number[i] / n;
vectors[i] = ratio;
}
}
void idealArray(Ratio number)
{
number[0]= 1.0;
number[1] = 1.0;
//Create an ideal, theoretical probability array
for ( int n = 2; n < 364; n++)
{
number[n] = (number[n - 1]*(1- (n-1)/365));
}
}
void outputTable()
{
//Not completed yet.
}
int randomInt(int bound)
{
return static_cast<int>( rand() / (RAND_MAX + 1.0) * bound );
}
In this code:
for ( int n = 2; n < 364; n++)
{
number[n] = (number[n - 1]*(1- (n-1)/365));
}
n is an integer, therefore (1-(n-1)/365)) will evaluate to an integer value, since all values in the expression are integers. Also, an integer multiplied by an integer will produce an integer. Since you start off setting number[1] to 1.0, and each element is calculated by multiplying the previous element by an integer amount, all subsequent values will be integer amounts (although stored as doubles).
Change your code to use doubles for the calculation:
for ( int n = 2; n < 364; n++)
{
number[n] = (number[n - 1]*(1.0-((double)n-1.0)/365.0));
}

How to compare the value inside of an array

So Im writing a program that asks the user to input the number of pancakes a person(1-10) had for breakfast. The program must analyze the input and determine which person ate the most pancakes. Also the program must output a list in order of number of pancakes eaten of all 10 people. So far I have written the code to get the user input and the code to display the array, but not in order. Im completely lost when it comes to comparing the elements in the array:
int getPancakes();
void displayArray(int theArray[],int sizeOfArray);
void compareArray(int sizeOfArray);
int pancakes[10];
int z = 0;
int main()
{
}
int getPancakes(){
int y;
int x = 0;
for(int y = 0; y < 10; y++){
++x;
cout << "How many pancakes did person " << x << " eat?" << endl;
cin >> pancakes[y];
}
}
void displayArray(int theArray[],int sizeOfArray){
for(int x = 0 ;x < sizeOfArray ; x++){
++z;
cout << "Person " << z << " ate " << pancakes[x] << " pancakes" << endl;
}
}
So how can I instruct my program to compare the elements inside the array? Also how can I instruct my program to print the list of number of pancakes eaten by each person in order?
In order to find who ate the most pancakes, you basically need to find the position of the maximum value in the array.
int findMaxPosition(int array[], int arraySize){
int maxPosition = 0; //assume the first element is maximum
for(int i = 1; i < arraySize; i++)
if(array[i] > array[maxPosition]) //compare the current element with the known max
maxPosition = i; //update maxPosition
return maxPosition;
}
Note that this gives you the first occurence of the maximum value. If the elements are unique, that's enugh. Otherwise, you should find the maximum value, array[maxPosition], and iterate through the array and display every position on which it occurs.
Sorting is a little bit complicated. The sorting algorithms aren't so straightforward, and I'm afraid that if I write you an implementation, I wouldn't help you.
One of the simplest sorting algorithms is bubble sort. Wikipedia (http://en.wikipedia.org/wiki/Bubble_sort) has a detailed page about it, and you should be able to implement it using the pseudocode given there.
If all numbers are unique
int max = 0;
for(int x = 0 ;x < 10 ; x++)
{
if(pancakes[x] > max)
max = pancakes[x];
}
for(int x = 0 ;x < 10 ; x++)
{
if(pancakes[x] == max)
cout << "Person " << x << " ate " << pancakes[x] << " pancakes - biggest number" << endl;
}
To be blunt, there are two methods for comparing an element of an array to another value, direct and through a copy.
// Make a copy:
int count = pancakes[x];
if (count == limit)
{
//...
}
// Direct access
if (pancakes[x] == limit)
{
//...
}
There is no need to run through the array looking for max then sorting to provide output. Instead, you can just keep track of the max value you have found during the input phase:
int getPancakes(){
int max = 0;
for(int y = 0; y < 10; y++){
cout << "How many pancakes did person " << y << " eat?" << endl;
cin >> pancakes[y];
if (pancakes[y]>pancakes[max]){
max = y;
}
}
return max;
}
Note that I removed the redundant declaration of y (you are declaring it in the for loop) and x (was always going to be equal to y).
I also added a return to the function (index of the person who has eaten the most) as you had no return value. (Either return something or make the function return void (no return)).
If you only care about the max number eaten, then you don't even need to keep track of max. Instead, just read the largest value from the array after the sorting step.
Now all you need to do is implement void sortArray() and call it before calling the display function:
int main()
{
int max = getPancakes();
sortArray(); //left to you to implement
displayArray(pancakes,10);
}
You may want to consider making pancakes local to main and passing it into your functions in the same way that you are doing displayArray.
I just finished coming up with a solution to the same exercise, regarding the "who ate the most" part, even if there is more than one person who ate the most pancakes. It involves arrays and vectors. Tested and working:
#include <iostream>
#include <array>
#include <vector>
using namespace std;
int main()
{
array <int, 10> PancakeEater;
vector<int> Winners;
int max;
cout << "Type number of pancakes eaten, separated by spaces, for each of the ten contestants:" << endl;
cout << "#1 #2 #3 #4 #5 #6 #7 #8 #9 #10" << endl;
for (int i = 0; i < PancakeEater.size(); i++)
{
cin >> PancakeEater[i];
}
max = PancakeEater[0];
Winners.push_back(1);
for (int i = 0; i < PancakeEater.size()-1; i++)
{
if (max == PancakeEater[i + 1])
{
Winners.push_back(i + 2);
}
if (max < PancakeEater[i + 1])
{
max = PancakeEater[i + 1];
Winners.clear();
Winners.shrink_to_fit();
Winners.push_back(i + 2);
}
}
if (Winners.size() > 1)
{
cout << endl << "The contestants that ate the most pancakes, on a tie for first place, are contestant numbers " << endl;
for (auto item : Winners)
{
cout << item << " ";
}
}
else
{
cout << endl << "The contestant that ate the most pancakes is contestant number " << endl;
for (auto item : Winners)
{
cout << item << " ";
}
}
}

Derive the execution time growth rate (BigO) of the following code

What is execution time growth rate Big O of this code?
void doDiff(int setA[], int setB[], int sizeA, int sizeB) {
const int MAX = 10;
// validate setA and setB
if ((sizeA == 0) && (sizeB == 0))
cout << "both sets are empty " << endl;
else
cout << "symmetric difference: { " ;
for (int i = 0; i < sizeA; i++ )
if (!member(setB, setA[i],sizeB))
cout << setA[i] << " ";
for (int i = 0; i < sizeB;i++ )
if (!member(setA, setB[i],sizeA))
cout << setB[i] << " ";
cout << "}" << endl;
}
bool member(int set[], int n, int size)
{
for (; size > 0; size--)
if (set[size-1] == n)
return true;
return false;
}
When I calculate the big O of this code, I end up with O(N*N*N) || O(N^3)
I am not sure what exact execution time growth rate is for this code.
please help me.
Thank you in advance
It seems inappropriate to fill an answer with questions, but since this sounds like homework, I think they're a better way to the goal (which is for YOU to figure out how this works):
What is the "big-O" of member? This is important, since doDiff relies on it so much.
How many times does doDiff call member?
If every call to member takes the same amount of time, member is O(X), and doDiff calls member Y times, what is the "big-O" of doDiff?