Need help with arrays and loops - c++

Use a single-subscripted array to solve the following problem: Read in 20 numbers, each of which is between 10 and 100, inclusive. As each number is read, print it only if it is not a duplicate of a number already read. Provide for the "worst case" in which all 20 numbers are different. Use the smallest possible array to solve this problem.
here is what I have so far:
#include <stdio.h>
#define SIZE 20
int duplicate (int num[] );
int main ()
{
int i, numbers[ SIZE ];
printf( " Enter 20 numbers between 10 and 100:\n " );
scanf_s( "%d\n" );
for (int i = 0; i < SIZE - 1; i++ );
{
int duplicate( int num[] )
{
int i, hold;
for ( i = 0; i <= SIZE - 1; i++ )
if ( num[i] == num[i=1] ){
hold = num[i];
else
hold = num[i+1];
}
printf( "%3d\n," num[ i ] );
}

Your professor is, unfortunately, probably not smart enough to solve his own problem. The smallest possible array for this problem is size 2 (Assuming a 64-bit data type, which is the largest the standard provides for. With 32-bit integers it would need three elements, and with 128-bit integers, just 1).
#include <stdint.h>
#include <stdio.h>
int main(void)
{
int_fast64_t visited[2] = { 0 };
int inputs_left = 20;
do {
int input, slot;
int_fast64_t mask;
puts("Enter an integer between 10 and 100: ");
if (!scanf("%d", &input)) {
puts("That's not a number!\n");
continue;
}
if (input < 10 || input > 100) {
puts("Out of range!\n");
continue;
}
slot = (input - 10) >> 6;
mask = 1 << ((input - 10) & 0x3F);
if (visited[slot] & mask) {
puts("Already seen, it is a duplicate.\n");
}
else {
visited[slot] |= mask;
printf("%d is new\n", input);
}
inputs_left--;
} while (inputs_left);
return 0;
}
You are welcome to use this code in your assignment, if you are able to correctly explain how it works (I hope your professor taught you how to write comments).

This is what I came up with, thanks for everybody's help:
#include <stdio.h>
#define MAX 20
int main()
{
int a[ MAX ] = { 0 }; /* user input */
int i; /* counter */
int j; /* counter */
int k = 0; /* number of integers entered */
int duplicate; /* notify of duplicates */
int value;
printf( "Enter 20 numbers between 10 - 100;\n" );
/* ask user for 20 numbers */
for ( i = 0; i <= MAX - 1; i++ ){
duplicate = 0;
scanf( "%d", &value);
/* decide if integer is duplicate */
for ( j = 0; j < k; j++ ) {
/* notify and stop loop if duplicate */
if ( value == a[ j ] ) {
duplicate = 1;
break;
{ /* end if */
/* enter number into array if it's not a duplicate */
if ( !duplicate )
a[ k++ ] = value;
} /* end if */

There are a few problems with your code:
The duplicate function is inside the main function.
i is declared multiple times
There should not be a semicolon after your first for loop.
The hold variable is not being used for anything. It is only being assigned a value.
num[i=1] - not sure what you are trying to do here, but the i=1 is setting i to 1.
In your first for loop, your condition is i < SIZE - 1, meaning it will loop 19 times, not 20. It should be i < SIZE or i <= SIZE - 1.
Your if statements should use braces ({}) for each if/else, or not at all.
if (test) {
// code
}
else {
// code
}
or
if (test)
// code
else
// code
As for the logic:
You are only getting one integer, which you are not putting in the numbers array. You will need to get 20 integers one by one and check the array each time the user enters a number.
The duplicate function should probably take a second parameter, the number that you want to check for. The if statement would check if num[i] equals the number you are looking for.
Remember to initialize the array values and only check values that you have set. For example, when the user enters the third number, you only want to check the first 2 numbers in the array to see if it already exists.
PS: Please try to indent your code properly. Many people will not even try to help if it is not indented properly.

My C is pretty rusty, so here's a pseudo-code solution (since this is homework you should do some of it for yourself):
print initial prompt;
declare nums[ array size 20 ]; // I later assume a 0-based index
declare boolean found;
for (i=0; i < 20; i++) {
// prompt for next number if desired
read next number into nums[i];
found = false;
// compare against all previously read numbers
for (j=0; j < i; j++) {
if (nums[j] == nums[i]) {
found = true;
break;
}
}
if (!found) {
print nums[i];
}
}
Note: the question as stated doesn't say the numbers have to be integers. Also, it says "use the smallest possible array" - you could do it with a 19 element array if you introduce a non-array variable for the current number (since the 20th number read only needs to be checked against the previous 19, not against itself), but that makes the code more complicated.
See also the comment I posted above that mentions some specific things wrong with your code. And check that all of your brackets match up.

Related

(C++) Finding all prime numbers between two integers (without using sieve of Eratosthanes)

I'm trying to find all the prime numbers between two integers and place them in an integer array.
The catch is that i have to use a specific method of doing so (divide each subsequent integer by all the primes in my array). So I can't use the sieve of Eratosthanes or any other 'easier' methods.
My code successfully prompts the user for two integers, but for now I do not use either of them. First I want to make sure the program works for values between 0 and whatever, in this case 200 just to test it.
Problem is, when I run the program and print the first 20 or so values in the array, I'm getting
2, 3, 5, 7, 11, 200, 0, 0, 0, 0, 0, 0 ...... more zeroes.
The first 5 values are correct because they start in the array, but after that the whole thing goes haywire.
I've worked through my nested loop by hand for a couple values and it SEEMS like it should work. I feel like there's a specific array property that I'm overlooking.
Here's my code:
#include "stdafx.h"
#include "iostream"
#include "climits"
#include "cmath"
#include "array"
using namespace std;
int main()
{
// declare variables to store user input
int lowerBound, upperBound;
// prompt user for lesser and greater integers and store them
cout << "Program to find all primes between two integers." << endl;
cout << "Enter lesser integer: " << endl;
cin >> lowerBound;
cout << "Enter greater integer: " << endl;
cin >> upperBound;
// if statement to switch the input variables if the user accidentally enters them backwards
if (lowerBound > upperBound) {
int temp = lowerBound;
lowerBound = upperBound;
upperBound = temp;
}
// initialize int array with the first 5 primes
int primes[100] = { 2, 3, 5, 7, 11 };
// loop to find primes between 12 and 200 (since we already have primes from 1-11 in the array)
for (int i = 12; i <= 200; i++) {
// the maximum divisor needed to determine if the current integer being tested is prime
double maxDivisor = sqrt(i);
// variable for the current size of the array
int size = 5;
// boolean variable is set to true by default
bool isPrime = true;
for (int j = 0; j < size; j++) { // changed "j<=size" to "j<size"
int remainder = (i % primes[j]);
// once the maximum divisor is reached, there is no need to continue testing for the current integer
if (primes[j] > maxDivisor) {
break;
}
// if the remainder of divison by a prime is 0, the number is not prime, so set the boolean variable to false
if (remainder = 0) {
isPrime = false;
}
}
// if isPrime is still true after the nested loop, the integer value being tested will be placed in the next element of the array
if (isPrime == true) {
primes[size] = i;
// since we added to the array, increment size by 1
size++;
}
}
// display the first 20 values in the array for debugging
for (int k = 0; k < 20; k++) {
cout << primes[k] << ", ";
}
system("pause");
return 0;
}
This here
if (remainder = 0) {
isPrime = false;
}
Needs to be changed to
if (remainder == 0) {
isPrime = false;
}
Because = does assignment, not comparison. So what remainder = 0 does it setting remainder to 0, and then it returns that 0, which gets casted to false, which is on of the reasons why it's not finding any primes.
Also, as Fantastic Mr Fox pointed out, for (int j = 0; j <= size; j++) needs to be changed to for (int j = 0; j < size; j++).
Also, did your compiler issue any warnings? If not, try to see if you can set it to be more strict with warnings. I figure most modern compilers will give you a hint at if (remainder = 0). Getting useful warnings from the compiler helps a lot with preventing bugs.
Edit:
As Karsten Koop pointed out, you need to move the int size = 5; out of the loop, to before the for (int i = 12;. With those changes, it's now working on my machine.
Last but not least, a tip: instead of if (isPrime == true), you can just write if (isPrime).

Finding a mode or modes in an array

EDIT Took a different approach and found the solution, updated the function to correctly find the mode or modes
I've been at this algorithm all day and night, I've looked at about 12 code examples 10x over but none of them seem to go above and beyond to address my problem.
Problem: Find the mode(s) in an array, if the array has more than one mode, display them all. (This is a homework assignment so I must use arrays/pointers)
Sample array:
-1, -1, 5, 6, 1, 1
Sample output:
This array has the following mode(s): -1, 1
The problem I'm having is trying to figure how to store and display just the highest mode OR the multiple modes if they exist.
I have used a lot of approaches and so I will post my most recent approach:
void getMode(int *arr, int size)
{
int *count = new int[size]; // to hold the number of times a value appears in the array
// fill the count array with zeros
for (int i = 0; i < size; i++)
count[i] = 0;
// find the possible modes
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
// don't count the values that will always occur at the same element
if (x == y)
continue;
if (arr[x] == arr[y])
count[x]++;
}
}
// find the the greatest count occurrences
int maxCount = getMaximum(count, size);
// store only unique values in the mode array
int *mode = new int[size]; // to store the mode(s) in the list
int modeCount = 0; // to count the number of modes
if (maxCount > 0)
{
for (int i = 0; i < size; i++)
{
if (count[i] == maxCount)
{
// call to function searchList
if (!searchList(mode, modeCount, arr[i]))
{
mode[modeCount] = arr[i];
modeCount++;
}
}
}
}
// display the modes
if (modeCount == 0)
cout << "The list has no mode\n";
else if (modeCount == 1)
{
cout << "The list has the following mode: " << mode[0] << endl;
}
else if (modeCount > 1)
{
cout << "The list has the following modes: ";
for (int i = 0; i < modeCount - 1; i++)
{
cout << mode[i] << ", ";
}
cout << mode[modeCount - 1] << endl;
}
// delete the dynamically allocated arrays
delete[]count;
delete[]mode;
count = NULL;
mode = NULL;
}
/*
definition of function searchList.
searchList accepts a pointer to an int array, its size, and a value to be searched for as its arguments.
if searchList finds the value to be searched for, searchList returns true.
*/
bool searchList(int *arr, int size, int value)
{
for (int x = 0; x < size; x++)
{
if (arr[x] == value)
{
return true;
}
}
return false;
}
It's best to build algorithms from smaller building blocks. The standard <algorithm> library is a great source of such components. Even if you're not using that, the program should be similarly structured with subroutines.
For homework at least, the reasoning behind the program should be fairly "obvious," especially given some comments.
Here's a version using <algorithm>, and std::unique_ptr instead of new, which you should never use. If it helps to satisfy the homework requirements, you might implement your own versions of the standard library facilities.
// Input: array "in" of size "count"
// Output: array "in" contains "count" modes of the input sequence
void filter_modes( int * in, int & count ) {
auto end = in + count;
std::sort( in, end ); // Sorting groups duplicate values.
// Use an ordered pair data type, <frequency, value>
typedef std::pair< int, int > value_frequency;
// Reserve memory for the analysis.
auto * frequencies = std::make_unique< value_frequency[] >( count );
int frequency_count = 0;
// Loop once per group of equal values in the input.
for ( auto group = in; group != end; ++ group ) {
auto group_start = group;
// Skip to the last equal value in this subsequence.
group = std::adjacent_find( group, end, std::not_equal_to<>{} );
frequencies[ frequency_count ++ ] = { // Record this group in the list.
group - group_start + 1, // One unique value plus # skipped values.
* group // The value.
};
}
// Sort <frequency, value> pairs in decreasing order (by frequency).
std::sort( frequencies.get(), frequencies.get() + frequency_count,
std::greater<>{} );
// Copy modes back to input array and set count appropriately.
for ( count = 0; frequencies[ count ].first == frequencies[ 0 ].first; ++ count ) {
in[ count ] = frequencies[ count ].second;
}
}
There's no real answer because of the way the mode is defined. Occasionally you see in British high school leaving exams the demand to identify the mode from a small distribution which is clearly amodal, but has one bin with excess count.
You need to bin the data, choosing bins so that the data has definite peaks and troughs. The modes are then the tips of the peaks. However little subsidiary peaks on the way up to the top are not modes, they're a sign that your binning has been too narrow. It's easy enough to eyeball the modes, a bit more difficult to work it out in a computer algorithm which has to be formal. One test is to move the bins by half a bin. If a mode disappears, it's noise rather than a real mode.

array input not working

The question:
Input data will give the number of test-cases in the first line.
Then test-cases themselves will follow, one case per line.
Each test-case describes an array of positive integers with value of 0 marking end. (this zero should not be included into calculations!!!).
Answer should contain average values for each array, rounded to nearest integer (see task on rounding), separated by spaces.
Problem:
Works fine but at third indice sum is assigned value of arrayInput and it messes everything up. Why does this happen and how can I fix it?
//araytest
#include<cmath>
#include<iostream>
using namespace std;
int main()
{
//var
int i = 0;
int array[13] = {};
//take in # arrays
cin >> i;
for(int x = 0; x<i; x++ )
{
//reset variables (for every array)
float arraySize = 0,
sum = 0, avg = 0;
int indice = 0,
arrayInput = 0;
while(cin >> arrayInput){
if(arrayInput == 0)
{
if(indice == 0)
{
arraySize = 1; /*if only 0 put in first indice
to prevent divide by 0 */
break;
}
else
{
arraySize = indice; // 0 doesn't count
break;
}
}
sum += arrayInput;
array[indice] = arrayInput;
arrayInput = 0;
indice++;
}
avg = round(sum/arraySize);
cout << avg << " ";
}
return 0;
}
First, like other people said, the array you used in this code is totally useless. It did nothing but save arrayinput.
Second, you let arraysize sum avg to be type float. However, arrayinput is assigned to be integer!! That means you never get result like this 2.xxx. So the type you declare for variables is meaningless. They should have same type declaration. I don't understand why you code does not work well. Because if you enter integer number, you wont get anything wrong. But it will crash if you give number like 2.xxx or x.xxx.

Optimizing "It's the Great Pumpkin Patch." ACM 1999 Practice

So, this is a weekly project for school, and I have got it completely working, but feel as if the way I did it, probably isn't one of of the best ways to do it ( or even a good way ). I was hoping you guys could help optimize it / give a better solution. I have already submitted this version, but would like to know a more optimal solution to the problem.
So to start, here's the problem...
It's almost Halloween and Linus is setting out to the garden to wait for the Great Pumpkin. Unfortunately, due to diversification, there are lots of other gourds in the garden this year, so he needs you to write a program to tell him how many patches of pumpkins there are and how big they are.
The input to this program will be a number of different gardens. The first line of the input for each garden will be the dimensions of the garden, r, the number of rows in the garden, and c, the number of columns, where 0 ≤ r ≤ 40 and 0 ≤ c ≤ 40. Following the dimensions will be r lines with c characters on each line. Each of these characters will be a lower case letter representing the type of gourd grown in the square. A lower case 'p' will represent pumpkins. A garden with 0 for the number of rows and/or columns indicates the end of input and should not be processed.
Example input:
10 10
pzzzzzzzzp
pyypzzzzzy
ppppssssyy
ssspssssyy
ssssppssyy
ssssppsspy
zzzzzzsspy
zzzzzzsspy
yyyypzsspy
yyyypppppy
3 4
pppp
pppp
pppp
1 7
zzzzzzz
0 0
For each garden, output the number of the garden (with the first input set being garden 1), the number of pumpkin patches in the garden, and the size of the pumpkin patches in order from smallest to largest. If there is more than one patch of a given size, print the size as many times as it occurs. Use the following format:
Example Output:
Garden # 1: 4 patches, sizes: 1 4 8 10
Garden # 2: 1 patches, sizes: 12
Garden # 3: 0 patches, sizes:
Note: Even though the problem says to input from a file, our professor told us to input through the keyboard.
My approach to this was to put the garden into a 2d array with a border of x's around it. I would then use a function to find a pumpkin patch ( and return its coordinates ). I would then use another function that recursively found if a pumpkin was attached to that one through above, below, left, and right, and returned the size of the pumpkin patch. This function also 'deletes' each pumpkin when it finds it by replacing it by an 'x'. This allowed me to not have to worry about finding pumpkins multiple times.
So here's my code, pretty well commented so that you guys could hopefully understand what I was trying to do.
#include <iostream>
#include <fstream>
using namespace std;
const int MAX_ROW = 41;
const int MAX_COL = 41;
char input ();
int checkForPatchSize ( char arr[][MAX_COL], int numOne, int numTwo );
bool findPatch ( char arr[][MAX_COL], int &row, int&col );
void sort ( int arr[], int size);
int main ()
{
int inputNumOne = -1; // Defaulted to -1, First number for Patch Size
int inputNumTwo = -1; // Defaulted to -1, Second number for Patch Size
int i, j; // i, j are indexes for loops, number
int numArr[MAX_ROW][MAX_COL]; // Array for storing Data
int indexGarden = 0;
int index = 1;
while ( inputNumOne != 0 )
{
cin >> inputNumOne; // User inputs Dimension
cin >> inputNumTwo; // Of Garden...
if ( inputNumOne != 0 and inputNumTwo != 0 ) // End case is that both are 0.
{
char pumpkinPatch[MAX_ROW][MAX_COL]; // Array for storing pumpkin patch info.
for ( i = 0; i < inputNumOne+2; i++ )
{
for ( j = 0; j < inputNumTwo+2; j++ )
{
// This if statement surrounds the garden in X's so that I have a border (allows me to not have to worry about test cases.
if ( i == 0 or j == 0 or i == inputNumOne + 1 or j == inputNumTwo + 1 )
{
pumpkinPatch[i][j] = 'x';
}
else // This is the input of the garden into a 2d array.
{
pumpkinPatch[i][j] = input();
}
}
}
int row, col, size, numberOfPatches = 0;
bool foundPatch = true;
index = 1;
while ( foundPatch == true )
{
row = inputNumOne+2; // Because I added a border to the garden
col = inputNumTwo+2; // the size is +2 of what the user input.
foundPatch = findPatch ( pumpkinPatch, row, col ); // Finds the start of a pumpkin patch, and returns the coordinates ( as row and col ).
if ( foundPatch == true ) // If a patch is found....
{
numberOfPatches++; // Increase number of patches
size = checkForPatchSize ( pumpkinPatch, row, col); // find size of particular patch
numArr[indexGarden][index] = size; // put size into data arr (to be printed to screen later).
index++;
}
}
numArr[indexGarden][0] = numberOfPatches; // Put number of patches as first item in each column of data arr.
indexGarden++;
}
}
for ( index = 0; index < indexGarden; index++ ) // Print out Garden Info
{
cout << "Garden # " << index + 1 <<": " << numArr[index][0] << " patches, sizes: ";
int temp = numArr[index][0]; // temp is the number of patches in particular garden.
int tempArr[temp]; // temp array to be used for sorting
int indexTwo;
for ( indexTwo = 0; indexTwo < temp; indexTwo++ )
{
tempArr[indexTwo] = numArr[index][indexTwo+1]; // Transfer sizes into a temp array so that they can be sorted.
}
sort (tempArr, temp); // Sort ( Sorts arr from smalles to larges )
for ( indexTwo = 0; indexTwo < temp; indexTwo++ ) // Output sorted array to screen.
{
cout << tempArr[indexTwo] << " ";
}
cout << endl;
}
}
char input()
{
char letter;
cin >> letter;
return letter;
}
/////////////// findPatch /////////////////////////////////////////////////
// Requirements: a 2D array of garden, and the size of it (row and col). //
// Returns a bool, true if patch is found, false if no patches found. //
// row and col are returned by reference to be the coordinates of one //
// of the pumpkins in the patch. //
///////////////////////////////////////////////////////////////////////////
bool findPatch ( char arr[][MAX_COL], int &row, int&col )
{
int rowIndex = 0;
int colIndex = 0;
while ( arr[rowIndex][colIndex] != 'p' and rowIndex < row )
{
colIndex = 0;
while ( arr[rowIndex][colIndex] != 'p' and colIndex < col )
{
colIndex++;
}
if ( arr[rowIndex][colIndex] != 'p' )
{
rowIndex++;
}
}
if ( arr[rowIndex][colIndex] != 'p' )
{
return false;
}
row = rowIndex;
col = colIndex;
return true;
}
/////////////// checkForPatchSize /////////////////////////////////////////
// Requirements: a 2D array of garden, and the coordinates of the start //
// of a patch. (Gotten from findPatch) //
// Returns an int, which is the size of the patch found //
// All p's or pumpkins are changed to x's so that they are not used //
// multiple times. //
///////////////////////////////////////////////////////////////////////////
int checkForPatchSize ( char arr[][MAX_COL], int numOne, int numTwo )
{
int index = 0;
if ( arr[numOne][numTwo] == 'p' )
{
index++;
arr[numOne][numTwo] = '0';
// Check Above
index += checkForPatchSize ( arr, numOne - 1, numTwo );
// Check to Left
index += checkForPatchSize ( arr, numOne, numTwo - 1 );
// Check Below
index += checkForPatchSize ( arr, numOne + 1, numTwo );
// Check to Right
index += checkForPatchSize ( arr, numOne, numTwo + 1 );
return index;
}
return 0;
}
/////////////// sort //////////////////////////////////////////////////////
// Requirements: an integer array, and the size of it (amount of //
// numbers in it). //
// //
// Sorts an array from smalles to largest numbers //
///////////////////////////////////////////////////////////////////////////
void sort ( int arr[], int size )
{
int index = 0;
bool changeMade = true;
while ( changeMade == true )
{
changeMade = false;
for ( index = 0; index < size - 1; index++ )
{
if ( arr[index] > arr[index+1] )
{
int temp = arr[index];
arr[index] = arr[index+1];
arr[index+1] = temp;
changeMade = true;
}
}
}
}
Alright, after reading through your code, I see your approach. Generally, I would approach this from a visual perspective. As it is, your code should work just fine, and is quite an elegant solution. The single weakness of your algorithm is the fact that it iterates over the same patch each time it moves. For example, when it moves upwards, it checks downwards. Avoiding redundancy is the surest sign of an optimal algorithm, but in terms of the small-scale at which you are deploying the algorithm, it need not be optimal.
In a way, the recursive nature of your code makes it quite beautiful because it traverses the pumpkin patch like little sparks that die out, which I really do like. Recursion is something which I don't often bother myself with, mostly because I don't think recursively, but after spending a moment wrapping my head around your algorithm, I really do see its value in cases like this. I would love to see the algorithm at work with dynamic visuals.
As for the accuracy of your algorithm, I can not imagine that it would fail in any manner to count the pumpkins correctly because it functions by making a small wave around the picked pumpkin in which the algorithm repeats itself, effectively propagating through the patch until it is all counted. As I said, the only shortcoming of your algorithm is that it would fall into an infinite loop if you did not somehow mark pumpkins as found (it checks the position it was called from). Beyond that, I can only say that you've proposed an excellent solution and that your doubts are almost entirely misplaced. Using a recursive algorithm was an excellent choice in this regard because it doesn't require a long list of cases in order to 'count'; it simply jumps into adjacent positions, returning to itself with the full count.

C++ array excercise-help needed

I'm C++ begginer. I did this excercise from Deitel's book:
Use a one-dimensional array to solve
the following problem. Read in 20
numbers, each of which is between 10
and 100, inclusive. As each number is
read, validate it and store it in the
array only if it is not a duplicate of
a number already read. After reading
all the values, display only the
unique values that the user entered.
Provide for the "worst case" in which
all 20 numbers are different. Use the
smallest possible array to solve this
problem.
Here is my code:
#include <iostream>
using namespace std;
bool compare(int arrayNum[],int arraySize,int element);
int main()
{
const int size=20;
int i=1;
int num[size];
int arrayElement;
int counter=0;
while(i<=20)
{
cin>>arrayElement;
if(i==1) //stores first element in array
num[0]=arrayElement;
//compare new element with stored elements
//if element is not a duplicate store it in array
else if (compare(num,size,arrayElement))
{
counter++;
num[counter]=arrayElement;
}
i++;
}
//displays array elements
for(int k=0;k<=counter;k++)
cout<<num[k]<<endl;
return 0;
}
//compare elements in array
bool compare(int arrayNum[],int arraySize,int element)
{
for(int j=0;j<arraySize;j++)
{
if(arrayNum[j]==element)
return false;
}
return true;
}
It works, but I'm not sure if I have interpreted the task correctly. I assume then I don't have to include conditional statement for range of numbers (10 to 100 inclusive), as this will be read from the keyboard and input by me. Therefore why was this instruction included? Also at the end it says
use the smallest possible array
I assume the max size has to be 20,but I don't think there is a way to dynamically expand array size (for example while storing new elements) as array size is const. I would appreciate if someone could help me with this. Any comments regarding code, or better solution are welcome.
As each number is read, validate
it and store it in the array
Emphasis mine. The text clearly says that your program has to validate the input. In other words, it has to check that the entered number is between 10 and 100, and if it is not, handle the error appropriately. So yes, you do need a conditional, although exactly what you do to handle the error is up to you.
And you're right, since arrays aren't dynamically resizable, the array size has to be at least 20.
You do need a conditional. Basically it's saying to take in a number between 10 and 100. If it's not a number between those ranges, don't store it. Also, if that number already exists in the array, don't store it. Then just print out the values in the array.
You assume correct about the array size, it's maximum size would be 20, although you may not store all 20 values (again, because some input might be bad).
The smallest possible array is a char[12], where the individual bits are used as flags.
char data[12]; // memset(data, 0, sizeof(data)); in main();
void set(int n_raw;)
{
int n = n_raw - 10;
int index = n/8;
int offset = n-8*index;
data[index] |= 1 << offset; // added "1 <<"
}
Reading the values back is left as an exercise for the student.
I assume then I don't have to include
conditional statement for range of
numbers (10 to 100 inclusive), as this
will be read from the keyboard and
input by me. Therefore why was this
instruction included?
Sure, in this case you wrote the code and know to enter numbers within the range expected; however, it is a standard best-practice to always validate input data from a user, always. That way erroneous values are handled gracefully (with an appropriate error message) and helps to make your program more robust.
Also at the end it says
use the smallest possible array
I assume the max size has to be 20,,,
I think what they might have been getting at here is that you could have used an array of 91 bytes as shown below.
int cnt = 0; // count of unique values entered
byte values[91]; // values entered indicator array
int valIdx; // used as values array index
memset((void *)values, 0, sizeof(values)); // initialize array to all zeros
while ( cnt < 20 )
{
// [code for the following comments not shown]
// have user input a number
// validate the number (>= 10 && <= 100)
// subtract 10 from the number and store it in valIdx
// (now valIdx will contain a number >= 0 <= 90)
if ( !values[valIdx] )
{
values[valIdx] = 1;
++cnt;
}
}
// then to show the unique values...
for ( valIdx = 0; valIdx < sizeof(values); valIdx++ )
{
if ( values[valIdx] )
{
cout << valIdx + 10 << endl;
}
}
That solution however, would not have met the "use the smallest array possible" requirement.
Back to your code...
I would go ahead and add the user input validation, just for completeness (and to get into the habit of never trusting users (especially yourself).
As far as improvements go, here is one thing to think about. The compare routine goes through every array element when a unique number has been entered. It only needs to check against those that have a stored value in them. Making that change should lead you to refactor the contents of your while loop as well.
I'm studying C++ in the same book!!
My first implementation for solving this problem was one that don't use any complementar array.. it uses a linear search to find duplicates..
take a look:
#include <iostream>
using namespace std;
// remember: size_t = unsigned int
const size_t arraySize = 20;
size_t _array[ arraySize ];
// global variable to keep track of the last used
// position in the _array
size_t counter = 0;
// the argument is not changed, so pass it by
// const reference
bool dupSearch( const int & );
int main()
{
// disregard this
ios_base::sync_with_stdio( false );
// "temp" variable declared outside the loop to
// avoid repeated allocation and deallocation
int i = arraySize, temp;
// look at the loop condition below " ( i-- ) "
// remember:
// false = ( every expression evaluated to 0 )
// true = ( every expression evaluated to a non-zero result )
// more details on pag. 108 of the book. 8/e Portability tip 4.1
while ( i-- )
{
// read the number from the user
cin >> temp;
// if the number entered is valid, put the
// number on _array[ counter ] and increment 'counter'
if ( dupSearch( temp ))
{
_array[ counter ] = temp;
++counter;
}
}
// print the result in column format
cout << endl;
for ( size_t j = 0; j < counter; ++j )
cout << _array[ j ] << endl;
}
// validation: if the value is out of the described range, return false
// if is in the range, check for duplicates using linear search.
// if a duplicate is found, return false
// otherwise, return true.
bool dupSearch( const int &a )
{
if ( a < 10 || a > 100 )
return false;
else
for ( size_t i = 0; i < counter; ++i )
if ( _array[ i ] == a )
return false;
return true;
}
the number of comparisons is
n = ( n * ( n + 1 )) / 2
where n = counter. worst case --> counter = 20 numbers --> loop 210 times through the program execution.