Searching and sorting arrays - c++

I am taking an introductory level C++ class. I have to write a boolean function that checks for duplicates along a vectors and returns true and false if no duplicates
#include<iostream>
#include<vector>
using namespace std;
bool has_duplicates(const vector <int> &v);
int main() {
vector<int> Vec(8);
Vec = { 20, 30, 40, 50, 10, 20, 5, 6 };
has_duplicates(Vec);
return 0;
}
bool has_duplicates(const vector<int>& v) {
bool duplicatefound = false;
for (int i = 0; i < 8; i++) { // Check each other number in the array
for (int j = i; j < 8; j++) { // Check the rest of the numbers
while (j != i) {// Makes sure don't check number against itself
if (v[i] == v[j]) {
cout << "duplicate found" << endl;
duplicatefound = true;
break;
}
}
}
}
return duplicatefound; // Reset the boolean after each number entered has been checked
}

There is a very simple solution to your problem:
Iterate through your array, using a loop:
for(int i=0; i < array_length; i++)
Within this loop, make use of another loop, to check whether any value prior to the one, to which i is pointing, is equal to your_array[i]. If this is the case you have found a duplicate and can return true, else the loops will just run until the end of the array is reached and then you can return false.
Thus your entire function would be something like:
bool contains_duplicates(int array[], int len) {
for(int i=0; i < len; i++) {
for(int j=0; j < i; j++) {
if(array[j]==array[i]) {
return true;
}
}
}
return false;
}
Hope I could help, cheers!
lindebear

You can use templates to extend the type contained on vector like this. This solution reduces the algorithm complexity to O(n log n) which is better than O(n^2) from your nested loop, it doesn't mean it will be faster always but it make a difference on large vectors.
template< typename T>
bool hasDuplicates(std::vector<T> vect) {
std::sort(vect.begin(), vect.end());
T last;
typename vector<T>::iterator it;
for(it = vect.begin(); it < vect.end(); it++) {
if (vect.begin() != it) {
if(last == *it) {
return true;
}
}
last = *it;
}
return false;
}

Related

How can I check if a array contains multiple elements?

I am trying to see if an array contains multiple values at any given index in the array, and if it does I want it to return true and if not return false. I want it to return true when it finds the numbers 1-9 and false if it does not.
bool isSolved(int a[], int size) {
int count = 0;
for (int i = 1; i < 10; i++) {
if (hasNum(a,size,i)) {
count++;
}
}
if (count == 9) {
return true;
}
else {
return false;
}
}
bool hasNum(int a[], int size, int num) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (a[j] == num) {
return true;
}
else {
return false;
}
}
}
}
This is what I have so far and it just gets stuck and never ends.
Man, that's C++. So use a standard vector and the count_if function from the standard library:
#include <algorithm>
#include <vector>
std::vector<int> a { /* fill vector */ };
std::count_if(std::begin(a), std::end(a), [](auto const& x){ return x == 1;});
Return the number of elements with value 1.
Also good, to question whether there's any value of 1:
std::any_of(std::begin(a), std::end(a), [](auto const& x){ return x == 1;});
I know this is strictly not an answer ...
There's no need to have 2 for loops in your hasNum function. Also, you are returning false if any of the values in the array is not equal to the number passed. You need to return false after the for loop ends.
Rewrite your hasNum function as shown below:
bool hasNum(int a[], int size, int num) {
for (int i = 0; i < size; i++) {
if (a[i] == num) {
return true;
}
}
return false;
}
I am trying to see if an array contains multiple values at any given index in the array
An array always contains exactly one value in every index.
Basically, your code is far from any C++ guidelines.
First, you don't pass array in C++ as int a[]. Use std::vector<int> instead.
Second your algorithm is badly inefficient. Consider using histogram approach.
bool isSolved(const std::vector<int>& a)
{
std::array<bool,10> hist;
for(int i=0; i<10; i++)
{
hist[i]=false;
}
for(auto x : a)
{
if(x>=0 && x<10)
{
hist[x] = true;
}
}
for(int i=0; i<10; i++)
{
if(!hist[i]) return false;
}
return true;
}
Here is a hint to the solution to your problem:
class BinaryTreeSet : public BinarySearchTree {
...
operator==
...
};
You are best off using std algorithms like find_if:
#include <algorithm>
int a[42]; // or vector<int> a(42) or any other container of any size
std::find_if(std::begin(a),std::end(a),[](auto const& v){return (v>=1)&&(v<=9);});

Sorting strings in ascending order by a certain value. What is wrong in my implementation?

I have the following problem :
Given a number N and N names, sort the names using a certain value (in ascending order). The names with the same value get sorted alphabetically.
The value of each name is determined by the number of pairs of vowels or consonants. Thus, each pair of vowels adds 1 to the value of the word, each pair of consonants subtracts 1 from the value, and a vowel-consonant or consonant-vowel pair doesn't change the value of the word.
What I did :
I created a vector using a struct. Each element has the name and its value. I calculated the value of each name and gave it to the .value field. After that, I sorted my vector using 2 for loops (I had no efficient idea for a value sort and an alphabetical sort all in one), and displayed the vector.
What happens:
I get no result, and I also think that there might be a segmentation fault. I'm still a newbie when it comes to finding out such errors.
Can you give me a few pointers ?
Thank you.
Attached the code below.
#include <vector>
#include <string>
#include <cstring>
using namespace std;
const char voc[] = "aeiouAEIOU";
struct stud
{
string name;
int value;
};
typedef vector<stud> vect;
void data(int& n, vect& v)
{
cin>>n;
for(int i = 0; i < n; ++i)
{
cin>>v[i].name;
}
}
int getValue(string name)
{
int value = 0;
int len = name.length();
for(int i = 0; i < len; ++i)
{
if(strchr(voc, name[i]) && strchr(voc, name[i+1]))
value++;
else if(!strchr(voc, name[i]) && !strchr(voc, name[i+1]))
value--;
}
return value;
}
void updateValues(vect& v)
{
vector<stud>::size_type v_size = v.size();
for(unsigned i = 0; i < v_size; ++i)
{
int value = getValue(v[i].name);
v[i].value = value;
}
}
void sortByValue(vect& v)
{
vector<stud>::size_type v_size = v.size();
for(unsigned i = 0; i < v_size; ++i)
for(unsigned j = i+1; j < v_size; ++j)
{
if(v[i].value > v[j].value)
swap(v[i], v[j]);
else if(v[i].value == v[j].value)
if(v[i].name.compare(v[j].name) > 0)
swap(v[i], v[j]);
}
}
void display(vect v)
{
vector<stud>::size_type sz = v.size();
for(unsigned i = 0; i < sz; ++i)
cout<<v[i].name<<'\n';
}
int main()
{
int n;
vect myvec;
data(n, myvec);
updateValues(myvec);
sortByValue(myvec);
display(myvec);
return 0;
}
better use overload operator> watch here
or use std::sort
std::vector<stud> vec;
//read
std::sort(vec.begin(), vec.end(), [](const auto& a, const auto& b) -> bool
{
if (a.value == b.value)
return a.name > b.name;
else
return a.value > b.value
});

Unable to understand error

I have written a mergesort algo as follows but on compiling it I get the following ,which states
Expression: vector subscript out of range
I dont understand why I am getting this error, plz point out the mistakes,I have coded this algo based on my understanding of the mergesort algorithm
As per my understanding I have coded a recursive function(mergesort), in which each time the array in question is divided in two parts left and right namely and then the left and right arrays are subdivided further till the point where there is only 1 element present in the subarrays once this stage arrives the merge function is called to sort the partitioned arrays and merge it to the original array from which the arrays were partitioned and the recursion goes a step backward in the recursion tree
Here is the source code
#include<iostream>
#include<vector>
using namespace std;
class Soham
{
vector<int> v;
public:
Soham();
void merge(vector<int> &, vector<int> & ,vector<int> &);
void mergesort(vector<int> &);
};
Soham::Soham()
{
int no;
for (int i = 0; i < 5; i++)
{
cin >> no;
v.push_back(no);
}
mergesort(v);
cout << "result" << endl;
for (auto it = v.begin(); it != v.end(); it++)
cout << *it << " ";
}
void Soham::mergesort(vector<int> &v)
{
if (v.size() < 2)
return;
else
{
vector<int>left, right;
if (v.size() % 2 == 0)//if input size is even
{
auto it = v.begin() + (v.size() / 2);
left.assign(v.begin(),it);
right.assign(it, v.end());
}
else// if input size is odd
{
auto it = v.begin() + (v.size() / 2);
left.assign(v.begin(),next(it));
right.assign(next(it), v.end());
}
mergesort(left);
mergesort(right);
merge(left, right,v);
}
}
void Soham::merge(vector<int> &temp_left, vector<int> &temp_right,vector<int> &temp_main)
{
int i = 0, j = 0, k = 0;
while (i<= temp_left.size() && j <= temp_right.size())
{
if (temp_left[i] <= temp_right[j])
{
temp_main[k] = temp_left[i];
i++;
k++;
}
else
{
temp_main[k]=temp_right[j];
j++;
k++;
}
}
while (i <= temp_left.size())
{
temp_main[k]=temp_left[i];
i++;
k++;
}
while (j <= temp_right.size())
{
temp_main[k]=temp_right[j];
j++;
k++;
}
}
int main()
{
Soham a;
system("pause");
return 0;
}
Thanks For Help
while (i <= temp_left.size())
When you access vector at index size() you will get your out-of-bounds access

Quitting a function if all values in an array are true

There is a simple feature I would like to add to one of the members of a class: I would like to quit the function in case all the values of some boolean (2d) array are true.
In the simpler case of a 1d array I can do it this way:
int SIZE = 10;
std::vector<bool> myArray(SIZE, true);
int i = 0;
while(myArray[i] and i < SIZE){
++i;
}
if(i == SIZE){
return;
}
// rest of the code for array not all true
There is probably no quicker way to do it (minus marginal optimizations) but I find it a bit ugly. Are there nicer ways to do it?
=========================================
In the end I decided to implement:
{
bool allTrue = true;
for(int i = 0; i < SIZE1 and allTrue; ++i)
for(int j = 0; j < SIZE2 and allTrue; ++j)
allTrue &= myArray[i][j];
if(allTrue)
return;
}
You may use std::all_of from <algorithm>:
if (std::all_of(myArray.begin(), myArray.end(), [](bool b) {return b;})) {
return;
}
One of the solutions:
int my2Da[][2] = {{true, true},{true, true},{true, true}};
int *pa = my2Da[0];
bool flag=true;
for (int i=0;flag && i<(sizeof my2Da)/(sizeof (int));flag &= pa[i++]);
//flag indicates about the result
For a 2d vector, you might want to break it down :
#include <vector>
#include <algorithm>
bool all_true(const std::vector<bool>& v)
{
return std::all_of(std::begin(v), std::end(v), [](const auto& b) { return b; });
}
bool all_true(const std::vector<std::vector<bool>>& vv)
{
return std::all_of(std::begin(vv), std::end(vv), [](const auto& v) {
return all_true(v);
});
}
void test()
{
std::vector< std::vector< bool > > d2 /* = initalise 2d vector */;
while(!all_true(d2))
{
// things you want to do
}
}
May be and-ing all values? This way:
bool r = true;
for (int i=0; i<myArray.size() && r; i++) r &= myArray[i];
return r;
Or std::all_of if your are familiar with iterators and lambdas.

How to check if all the values of an array are equal to 0?

The context of the program is a game involving pegs and discs. The user inputs the amount of pegs (max of 20) and the amount of discs on each peg (max of 10). Two players go back and forth removing any amount of discs on a single peg each turn, given that there are enough discs to remove on that peg. The player to remove the last disc loses.
The number of discs are stored in an array, where the index of the array corresponds the peg number. I have a boolean function that checks whether or not the pegs are empty of discs, implying someone has won. There is some logical error in my code but I can't figure out what it is:
bool checkPegs(int array[], int size)
{
int checker(0);
for (int i = 0; i < size; i++)
{
if(array[i] = 0)
{
return true;
}
else
{
return false;
}
}
}
bool checkPegs(int array[], int size)
{
for (int i = 0; i < size; i++)
{
if(array[i] != 0)
{
return false;
}
}
return true;
}
try memcmp instead of having separate function with for loop:
int zeros[sizeof(yourArray)];
if(memcmp(yourArray,zeros,sizeof(yourArray))==0)
//do things
else
//do things
if(array[i] = 0)
That doesn't compare array[i] with 0, it assigns 0 to array[i]. You want array[i] == 0.
if(array[i] == 0)
{
return true;
}
else
{
return false;
}
The second issue is that you only check the first element, then return based on that. You should check every element to ensure they are non-zero:
for (int i = 0; i < size; i++)
{
if(array[i] != 0) {
return false;
}
}
Finally, you don't handle the case that size is 0. In that case, you should return true.
bool checkPegs(int array[], int size)
{
for (int i = 0; i < size; i++)
{
if(array[i] != 0) {
return false;
}
}
return true;
}
there are two errors here
bool checkPegs(int array[], int size)
{
int checker(0);
for (int i = 0; i < size; i++)
{
if(array[i] = 0) // the first one use '==' instead of '='
{
return true; // the second one, you are testing the first element only
}
else
{
return false;
}
}
}
here how it should be
bool checkPegs(int array[], int size)
{
for (int i = 0; i < size; i++)
{
if(array[i] )
return false; // return false at the first found
}
return true; //all elements checked
}
The way you wrote your code cannot work, for you are actually considering only the first element because of the two return statements in the if/else. Moreover, you use an assignment statement instead of a comparison.
It follows a reviewed example:
bool checkPegs(int *array, int size) {
for (int i = 0; i < size; i++) {
if(array[i] != 0) { return false; }
}
return true;
}
Keep in mind that it can be optimized and you can do the same using standard utilities, but I assume that you are learning to code and so it's worth to write it for yourself.