1

my program takes in values from a input file and passes them to an array called gpa. I have created a function that finds the smallest value in the gap array and displays it, but I also need to display a duplicate value if there is one. How would I do this.

Thank you in advance

#include <iostream>
#include <fstream>

using namespace std;

void lowestGpa(string names[], double gpa[], int SIZE){
    int count;
    double lowest = gpa[0];
    string name;

    for (count = 0; count < SIZE; count++)
    {
        if (gpa[count] <= lowest)
        {
            lowest = gpa[count];
            name = names[count];
        }
    }

    cout << name << " " << lowest;
}

int main()
{
    ifstream infile;
    infile.open("GPA.txt");

    int const SIZE = 15;
    string names[SIZE];
    double gpa[SIZE];

    while (infile)
    {
        for(int i = 0; i < SIZE; i++)
        {
            infile >> names[i] >> gpa[i];
        }
    }

    lowestGpa(names, gpa, SIZE);

    infile.close();

    return 0;
}
5
  • 1
    In an unrelated note, please drop the habit of double-spacing your code. It makes it unreadable. Use whitespace strategically. Commented Oct 30, 2013 at 3:00
  • There's a std::min_element algorithm and a std::adjacent_find algorithm, which tells you exactly where adjacent equal elements are. Commented Oct 30, 2013 at 3:05
  • just add one more loop after you find the lowest value to check which one equals to it... Commented Oct 30, 2013 at 3:06
  • 1
    @kfsone, You might want to check on that one. Commented Oct 30, 2013 at 3:21
  • @kfsone It won't always evaluate to true. Commented Oct 30, 2013 at 3:21

5 Answers 5

1

The easiest (but not necessarily computationaly quickest) way might be to sort your data. You can then find the lowest because it'll be at position 0 in the array, and you can check by duplicates by iterating the list and finding instances where score[n] == score[n + 1].

#include <iostream>
#include <algorithm>
using namespace std;

int main() {
    const size_t size = 7;
    int array[size] = { 70, 20, 60, 40, 10, 30, 40 };
    // note: the second argument is just past the last element,
    // it's where the array has *ended*
    std::sort(&array[0], &array[size]);

    for (size_t i = 0; i < size; ++i)
        std::cout << array[i] << " ";
    std::cout << endl;

    // lowest:
    std::cout << "Lowest: " << array[0] << std::endl;

    // duplicate check
    // skip 1 and use backwards-looking checks, this saves us having
    // to do math in the loop condition.
    for (size_t i = 1; i < size; ++i) {
        if (array[i] == array[i - 1])
            std::cout << (i - 1) << " and " << i <<
                " contain " << array[i] << std::endl;
    }
    return 0;
}

Live demo: http://ideone.com/3WKrHR

Sign up to request clarification or add additional context in comments.

3 Comments

Algorithmically speaking, the quickest way is not sort the data, since that is O(nlog n), whereas O(n) is possible. But I doubt that makes a big difference here.
Actually, I misread the question - I thought he needed to find all duplicates not just a duplicate of the lowest value.
And - bleah - quickest was a poor choice of word on my part :)
0
//Add a loop to cout the lowest's name 
for (count = 0; count < SIZE; count++)
{

    if (gpa[count] == lowest )

    {
        cout << names[count]<< " " << lowest;
    }

}

But this method is not perfect, 2 loops.

Comments

0

You likely want to find all duplicates of the lowest GPA.

#include <algorithm>
#include <numeric_limits>

void lowestGpa(string names[], double gpa[], int size){
    double lowest = numeric_limits<double>::infinity(); //or 1. / 0
    for(int i = 0; i < size; i++) {
        lowest = min(lowest, gpa[i]);
    }

    for(int i = 0; i < size; i++) {
        if(gpa[i] == lowest) {
            cout << names[i] << " " << gpa[i];
        }
    }
}

This runs in O(n),

Also, this does not crash when size is 0.

4 Comments

1. / 0? Interesting. That... Well, that looks like a divide by zero? :)
I wanted Infinity. There is another way to get this...let me look it up. Notice this is not 1 / 0. It is 1. / 0.
Hey - I wasn't down voting or anything - genuinely surprised that works - the "." just promotes it to a floating point and I guess there's a rule that says division by zero is bad unless it's floating. ideone.com/YhNE2y
@kfsone, I hear you :) Interestingly enough, g++ gives me a divide by zero compile warning when I use that.
0

There is no need to sort the whole array nor loop twice. Just use an extra vector to store the names with lowest GPA.

void lowestGpa(string names[], double gpa[], int SIZE){
    double lowest = gpa[0];
    vector<int> lowids(1, 0);

    for (int count = 0; count < SIZE; count++)
    {
        if (gpa[count] < lowest)
        {
            lowest = gpa[count];
            lowids.clear();
            lowids.push_back(count);
        }
        else if (gpa[count] == lowest)
        {
            lowids.push_back(count);
        }
    }

    for (vector<int>::const_iterator i = lowids.begin(); i != lowids.end(); ++i)        
        cout << names[*i] << " " << lowest << endl;
}

5 Comments

That has the same potential overhead as looping twice, likely more.
Store the indices instead to reduce the string copy overhead.
@timrau This solves the problem indeed but I haven't yet studied const_iterator or anything similar
I thought about this approach. FYI, notice the second loop...at the end.
But the 2nd loop does not loop through the whole input array. Only through the answers.
0

You can use std::set, std::set_difference, std::sort to find the lowest duplicate element:

#include <vector>
#include <set>
#include <iostream>

int main() {
    int gpas[] = {100,30,97,67,89,100,90,67,100,67,30,1,1};//sample values

    std::vector<int> vec(gpas, gpas + sizeof(gpas)/sizeof(int));//this constructor is only valid for stack allocated arrays
    std::set<int> cpy(vec.begin(), vec.end());//create a set with the unique gpas in a set
    std::vector<int> duplicates;

    std::set<int>::const_iterator it;

    std::sort(vec.begin(), vec.end());//sort the set as set_difference requires that the container is sorted

    //find the duplicates using set_difference. This will find all duplicates
    //(which will be repeated n - 1 times in `duplicates` for n > 1)
    std::set_difference(vec.begin(), vec.end(), cpy.begin(), cpy.end(), std::back_inserter(duplicates));

    //this creates a set from all the duplicates found
    std::set<int> unique_duplicates(duplicates.begin(), duplicates.end());

    //output the duplicates
    for (it = unique_duplicates.begin(); it != unique_duplicates.end(); ++it) {
        std::cout << *it << std::endl;
    }

    //if you want the lowest value of the duplicates:
    //you can use the min_element from <algorithm>:
    //std::min_element(unique_duplicates.begin(), unique_duplicates.end());

    //However, as the vector `vec` was already sorted, this ensures that
    //all the other results obtained from the sorted vector will ALREADY
    //be sorted. Hence, if size is > 0, then we can simply look at the
    //first element alone.
    if (unique_duplicates.size() > 0) {
        it = unique_duplicates.begin();
        std::cout << "The LOWEST duplicate element is: " << *it << std::endl;
    }

    return 0;
}

From the sample data posted, this outputs:

1
30
67
100

As the duplicate elements

And, 1 as the lowest duplicate element.

REFERENCES:

http://www.cplusplus.com/reference/algorithm/set_difference/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.