Index/Max/Min of a Vector<double> C++ - c++

I want to be able to figure out the highest and lowest element in an vector and also figure out what position/index that high/low number is currently.
For example,
vector<double> x;
std::cout << "Enter in #s: ";
double numbers;
std::getline(std::cin, numbers);
x.push_back(numbers);
Let's say the user inputted 4.3 1.0 2.99 43.5
I would want the result to say
The highest number is 43.5 at position 4
The lowest number is 1.0 at position 2
I was wondering if there is any way to implement this code WITHOUT using the min_element/max_element function and do it with a for loop?
I wanted to use something like:
for (int i=0;i < x.size();i++)
if ( //the number is less than ) {
std::cout << "The lowest number is...... at position .....";
if ( //the number is greather than ) {
std::cout << "The highest number is......at position......";

Compare each number to the best max / min found so far.
If it is bigger/smaller replace the max/min with it and note the index
You will need a max and min variable and two indexes - be carefull what you set the initial value if your max and min to

For that, you need to store both the indices of the highest and lowest elements, comparing them with the current element for each iteration.
// Note: the below code assumes that the container (vector) is not empty
// you SHOULD check if the vector contains some elements before executing the code below
int hi, lo; // These are indices pointing to the highest and lowest elements
hi = lo = 0; // Set hi and lo to the first element's index
// Then compare the elements indexed by hi and lo with the rest of the elements
for (int i = 1;i < x.size();i++) {
if(x[i] < x[lo]) {
// The element indexed by i is less than the element indexed by lo
// so set the index of the current lowest element to i
lo = i;
}
// Below, else if is used and not if because the conditions cannot be both true
else if(x[i] > x[hi]) {
// Same logic as the above, only for the highest element
hi = i;
}
}
// Note: the position indicated by the output below will be 0-based
std::cout << "The lowest number is " << x[lo] << " at position " << lo << ".\n";
std::cout << "The highest number is " << x[hi] << " at position " << hi << ".\n";
LIVE DEMO

size_t iMax=0,iMin=0;
for(size_t i=1; i<x.size(); ++i)
{
if(x[iMax] < x[i])
iMax=i;
if(x[iMin] > x[i])
iMin=i;
}
//iMax is index of the biggest num in the array

Related

How to pick the max top 10 quantity from HashTable C++?

I already wrote a working project but my problem is, the last part.I have already Read 500.000 row from csv file into vector, then put into the hashtable.I can print whole hashtable but I need to pick top 10 Quantity from my hashtable.Just be clear, I am not about to sort the whole hashtable, just pick top 10.
The topic of my project is,program must be able to store individual products (given with StockCode) from csv file and insert it into a suitable data structure. If that product is already inserted into the structure, its counter must be increased by the quantity of the order.After reading and processing is over, your program must list the “top 10” products ordered by individuals.
There is rule about the libraries, This will be a proper C++ class. You must be able to create many instances of this class. (Please use no third party libraries and C++ STL, Boost etc.) However, you can use, iostream, ctime, fstream, string like IO and string classes.
Important note: Only thing I should focus is speed, storage or size is not a problem.
What I've done so far is,
Read Csv file row by row into vector
Stockcodes in row[1], Quantity in row[3]
Put them into Hashtable and increase their quantity by the quantity of the order.
Print the whole hash table.
What I need to do is,
Print the Top 10 Quantity
Now let's share Example csv file, Driver program codes, Output of the print function.
Csv File look like this:
InvoiceNo;StockCode;Description;Quantity;
536365;85123A;WHITE HANGING HEART T-LIGHT HOLDER;6
536365;71053;WHITE METAL LANTERN;6;
536365;84029G;KNITTED UNION FLAG HOT WATER BOTTLE;6;
536365;84029E;RED WOOLLY HOTTIE WHITE HEART.;6;
536365;22752;SET 7 BABUSHKA NESTING BOXES;2;
536365;21730;GLASS STAR FROSTED T-LIGHT HOLDER;6;
main.cpp
void printMaxQuantity() {
int maxValue=0;
for (int i = 0; i < 1000000; ++i) {
if(table[i] != nullptr) {
if (table[i]->quantity > maxValue)
maxValue = table[i]->quantity;
if (table[i]->quantity == maxValue) {
cout << "Index: " << i << endl;
cout << "StockCode: " << table[i]->stockCode << endl;
cout << "Quantity: " << table[i]->quantity << endl;
cout << endl << endl;
}
}
}
}
};
Here the output:(After edit the code StockCode: 85123A is correct output, but still struggling about the top 10)
Index: 41240
StockCode: 10002
Quantity: 48
Index: 309193
StockCode: 85123A
Quantity: 72
Process finished with exit code 0
Also one last note, I am doing this for a school project so I shouldn't use any third party software or include any different libraries because it is not allowed (I will implement my own vector class later)
Since this is homework, I will avoid writing actual code. Since you do not have any prior information about the actual data set, you will need to loop through it, which is a linear complexity. In order to find the top 10 items I advise you to create an array of 10 items to store the best items you get so far.
The first step is to copy the first 10 elements into your array.
The second step is sort your array of 10 items descendingly, so you will always use the last item for comparison.
Now you can loop the big structure and on each step, compare the current item with the last one of the array of ten elements. If it's lower, then do nothing. If it's higher, then find the highest ranked item in your array of 10 items which is smaller than the item you intend to insert due to higher quality. When you find that item, loop from the end until this item until your array of ten elements and on each step override the curret element with the current one. Finally override the now duplicate element.
Example: Assuming that your 7th element has lower quality than the one you intend to insert, but the 6th has higher quality override 9th element with the 8th, then the 8th with the 7th and then the 7th with the item you just found. Remember that array indexes start from 0.
This is what you want clearly.This code pick the top 10 from your hash table
void hashTable::printTopTen() {
int maxValue = 0;
int indexHolder = 0;
cout << "#" << " " << "Stock Code" << "\t" << "Description" << "\t\t\t" << "Quantity" << endl;
for (int i = 0; i < 10; ++i) { //-> This loop for top 10
for (int index = 0; index < TABLE_SIZE; ++index) { //-> base loop to find max quantity in hash table
if (table[index] != nullptr) { // to check if index is NULL or not
if (table[index]->quantity > maxValue) {
maxValue = table[index]->quantity; //update the maxValue with biggest quantity
indexHolder = index; // -> to store index number of max quantity in hash table
}
}
}
for (int indeX = 0; indeX < TABLE_SIZE; ++indeX) { //find the max quantity's stockCode,description
if (table[indeX] != nullptr) { // to check if index is NULL or not
if (table[indeX]->quantity == maxValue) { //if we have reached the maxValue then it's quantity is top 1
cout << i + 1 << "." << " " << table[indeX]->stockCode << "\t" << table[indeX]->description
<< "\t" << table[indeX]->quantity << endl;
table[indexHolder]->quantity = 0; //after cout the max one, delete the index so it can't be top 1 again
}
}
}
maxValue = 0; // update max value 0 again for second base loop
}
}
This question already has an answer. But I want to show you how to perform selection sort so you can compare it with your code.
**Performance trick: ** Quick Sort algorithm can be used instead of Selection Sort
hashMap=hashTable, hashEntry=Node, so this what I did:
void hashTable::selectionSort() {
int firstCounter, secondCounter;
Node *emptyOne = new Node("empty", "thisEmpty", 0);
Node *temp;
for (firstCounter = 1; firstCounter < TABLE_SIZE; firstCounter++) {
if (table[firstCounter] == nullptr) {
table[firstCounter] = emptyOne;
}
temp = table[firstCounter];
secondCounter = firstCounter - 1;
if (table[secondCounter] == nullptr) {
table[secondCounter] = emptyOne;
}
while (secondCounter >= 0 && table[secondCounter]->quantity > temp->quantity) {
table[secondCounter + 1] = table[secondCounter];
secondCounter = secondCounter - 1;
if (table[secondCounter] == nullptr) {
table[secondCounter] = emptyOne;
}
}
table[secondCounter + 1] = temp;
}
}

Why isn't this x value increasing in this map for loop? c++

The purpose of this loop is to look through a 2d vector and count the frequency in which a value in the first column appears. If the value shows up all three times, then it is good to go. If it doesn't then I would like to delete the row that it's in from the vector. The "it" iterator stores the value as (value, frequency).
I can't figure out how to delete the row at this point though, i have been trying to use a counter "x" in the second for loop so that it can keep track of which row it is on, but when i run it through the debugger the x doesn't increment. What ends up happening is the vector deletes the first rows instead of the rows that make the if statement true.
Why isn't the "x" incrementing? Is there a different method i could use to keep track of which row the loop is currently in?
"data" is the 2d vector.
for (int i = 0; i < data.size(); i++) // Process the matrix.
{
occurrences[data[i][0]]++;
}
for (map<string, unsigned int>::iterator it = occurrences.begin(); it != occurrences.end(); ++it)
{
int x = 0;
if ((*it).second < 3) // if the value doesn't show up three times, erase it
{
data.erase(data.begin() + x);
}
cout << setw(3) << (*it).first << " ---> " << (*it).second << endl; // show results
x++;
}
You reset x back to 0 every loop. Initialize it outside the loop and it should work.
int x = 0;
You have to initialize x outside the for loop. If you declare it in the for loop it will be set to 0 every time. You current program deletes the first element each time because the x is always zero here: data.erase(data.begin() + x);
for (int i = 0; i < data.size(); i++) // Process the matrix.
{
occurrences[data[i][0]]++;
}
int x = 0;
for (map<string, unsigned int>::iterator it = occurrences.begin(); it != occurrences.end(); ++it)
{
if ((*it).second < 3) // if the value doesn't show up three times, erase it
{
data.erase(data.begin() + x);
}
cout << setw(3) << (*it).first << " ---> " << (*it).second << endl; // show results
x++;
}

histogram program gives strange output C++

I have been writing code to produce a horizontal histogram. This program takes user input of any range of numbers into a vector. Then it asks the user for the lowest value they want the histogram to begin at, and how big they want each bin to be. For example:
if lowestValue = 1 and binSize = 20
and vector is filled with values {1, 2, 3, 20, 30, 40, 50} it would print something like:
(bin) (bars) (num)(percent)
[ 1-21) #### 4 57%
[21-41) ## 2 28%
[41-61) ## 2 28%
Here is most of the code that does so:
void printHistogram(int lowestValue, int binSize, vector<double> v)
{
int binFloor = lowestValue, binCeiling = 0;
int numBins = amountOfBins(binSize, (int)range(v));
for (int i = 0; i<=numBins; i++)
{
binCeiling = binFloor+binSize;
int amoInBin = amountInBin(v,binFloor, binSize);
double perInBin = percentInBin(v, amoInBin);
if (binFloor < 10)
{
cout << "[ " << binFloor << '-' << binCeiling << ") " << setw(20) << left << formatBars(perInBin) << ' ' << amoInBin << ' '<< setprecision(4) << perInBin << '%' << endl;
binFloor += binSize;
}
else
{
cout << '[' << binFloor << '-' << binCeiling << ") " << setw(20) << left << formatBars(perInBin) << ' ' << amoInBin << ' '<< setprecision(4) << perInBin << '%' << endl;
binFloor += binSize;
}
}
}
and the function that counts how many terms are in each bin:
int amountInBin(vector<double> v, int lowestBinValue, int binSize)
{
int count = 0;
for (size_t i; i<v.size(); i++)
{
if (v[i] >= lowestBinValue && v[i] < (lowestBinValue+binSize))
count += 1;
}
return count;
}
Now my issue:
For some reason, it is not counting values between 20-40. At least as far as I can see from my testing. Here is an image of a run:
Any help is appreciated.
I would suggest a different approach. Making two passes, first calculating the number of bins, then another pass to add them up, looks fragile, and error-prone. Not really surprise to see you trying to figure out a bug of this kind. I think your original approach is too complicated.
As the saying goes "the more you overthink the plumbing, the easier it is to stop up the drain". Find the simplest way to do something, and it will have the least amount of surprises and gotchas, to deal with.
I think it's simpler to make a single pass over the values, calculating which bin each value belongs to, and counting the number of values seen per bin. Let's use a std::map, keyed by bin number, with the value being the number of values in each bin.
void printHistogram(int lowestValue, int binSize, const std::vector<double> &v)
{
std::map<int, size_t> histogram;
for (auto value:v)
{
int bin_number= value < lowestValue ? 0:(value-lowestValue)/binSize;
++histogram[bin_number];
}
And ...that's it. histogram is now your histogram. histogram[0] is now the number of values in the first bin, [lowestValue, lowestValue+binSize), which also includes all values less than lowestValue. histogram[1] will be the number of values found for the next bin, and so on.
Now, you just have to iterate over the histogram map, and generate your actual histogram.
Now, the tricky part here is that the histogram map will only include keys for which at least 1 value was found. If no value was dropped into the bin, the map will not include the bin number. So, if there were no values in the first bin, histogram[0] won't even exist, the first value in the map will be the bin for the lowest value in the vector.
This isn't such a difficult problem to solve, by iterating over the map with a little bit of extra intelligence:
int next_bin_number=0;
for (auto b=histogram.begin(); b != histogram.end(); b++)
{
while (next_bin_number < b->first)
{
// next_bin_number had 0 values. Print the histogram row
// for bin #next_bin_number, showing 0 values in it.
++next_bin_number;
}
int n_values=b->second;
// Bin #n_next_number, with n_values, print its histogram row
++next_bin_number;
}
The code in the loop doesn't initialize i, so the results are at best unpredictable.

Finding the closest number of array to another given number

I have this program to write that I have a array of 11 numbers entered from me. Then I need to find the avarage sum of those numbers, and then im asked to find the closest number of this array to the avarage sum, and then the most distant element of the array to the avarage sum again. SO far I manage to write a program to create this array and find the avarage sum. I asssume there is something to do with abs function of cmath libary , but so far I only fail to make it.
#include <iostream>
using namespace std;
int main() {
unsigned const int size = 11;
float number[size];
for (unsigned i = 0; i<size; i++) {
cout << "Please enter value for number "
<< i + 1 << ":";
cin >> number[i];
}
for (unsigned i = 0; i<size; i++) {
cout << "Number " << i + 1 << " is : "
<< number[i] << endl;
}
unsigned int sum = 0;
for (unsigned i = 0; i<size; i++) {
sum += number[i];
}
What is the problem? You are not asking a question, just making a statement... It does seem that you have not posted the whole code..
In c++ usually to use "abs" you should use fabs from the "math.h" library!
You will be okay with the compare operators.
Just traverse your array in a loop and calculate the difference between your compare value and the current value on your array. Initiate a temporary variable that keeps the array entry that created the smallest difference.
Every time a difference that is smaller than the current one comes up replace the value in your temporary variable.
So you replace under the following condition: If |number[i] - average_value| < |tmp_closest_val -average_val| Then tmp_closest_val = number[i] EndIf.
I hope you get the concept from that rough draft.

c++ vector not updating in nested for loop

So I create and initialize a vector (of size nmask+3) to 0, and I assign an initial value to one of the elements. I then make a for loop that goes through the first nmask elements of the vector and assigns to each element an average of 26 other elements in the vector (defined by the 4D int array voxt, which contains vector addresses).
My problem is that when I check the values of nonzero elements in my vector (phi) within the nested loop (the first cout), the values are fine and what I expect. However, when the loop finishes going through all nmask elements (for (int i= 0; i<nmask; i++) exits), I check the nonzero elements of phi again, and they are all lost (reset to 0) except for the last non-zero element (and element tvox which is manually set to 1).
I feel that since phi is initialized outside of all the loops, there should be no resetting of values going on, and that any updated elements within the nested loop should remain updated upon exit of the loop. Any ideas as to what is going on / how to fix this? Code is below; I tried to comment in a sense of the outputs I'm getting. Thanks in advance.
vector<double> phi(nmask+3, 0); //vector with nmask+3 elements all set to 0 (nmask = 13622)
phi[tvox]= 1; //tvox is predefined address (7666)
for (int n= 0; n<1; n++)
{
vector<double> tempPhi(phi); //copy phi to tempPhi
for (int i= 0; i<nmask; i++)
{
for (int a= -1; a<=1; a++)
{
for (int b= -1; b<=1; b++)
{
for (int c= -1; c<=1; c++)
{
if (!(a==0 && b==0 && c==0))
{
//oneD26 is just (double) 1/26
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
if (phi[i]!=0)
{
//this gives expected results: 27 nonzero elements (including tvox)
cout << n << " " << i << " " << a << b << c << " " << phi[i] << endl;
}
}
}
}
}
}
phi[svox]= 0; //svox = 7681
phi[tvox]= 1;
for (int q= 0; q<nmask; q++)
{
//this gives only 2 nonzero values: phi[tvox] and phi[9642], which was the last nonzero value from 1st cout
if (phi[q]!=0)
cout << q << " " << phi[q] << endl;
}
}
Difficult to tell just what is going on, but the easiest explanation is that after phi[i] gets set to non-zero and displayed to cout, it gets set to zero again in one of the later iterations through the inner loops.
If you do some tracing and check phi[i] just before updating you'll see that you often overwrite a non-zero element with zero.
Note: I have no idea what your code does, this is pure Sherlock Holmes reasoning.. if after the loops you find only 2 non-zero elements then the only logical consequence is that after updating something to non-zero later in the loop you update it to zero.
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
The nested for-loops using a, b, and c run for a combined 9 iterations with the same value of i. Since you overwrite phi[i] to a new value every time, you only retain the value from the last iteration where a, and c are all 1. If that last iteration happens to produce zero values, then phi[i] will have lots of zeroes. Perhaps you meant to do something like phi[i] += ... instead of phi[i] = ...?
I do suggest to replace the meat of the loop with something like
const boost::irange domain(-1,2);
for (int i: boost::irange(0, nmask)) for (int a: domain) for (int b: domain) for (int c: domain)
{
if (a==0 && b==0 && c==0)
continue;
//oneD26 is just (double) 1/26
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
if (phi[i]!=0)
{
//this gives expected results: 27 nonzero elements (including tvox)
cout << n << " " << i << " " << a << b << c << " " << phi[i] << endl;
}
}
Of course, for brevity I assume both boost/range.hpp and c++0x compiler. However, with trivial macro's you can achieve the same. That is without writing/using a proper combinations algorithm (why is that not in the standard, anyway).