How do I compare an element of array in c/c++? - c++

int arr[] = {10, 20, 20, 10, 10, 30, 50, 10, 20};
I want to compare each element in an array so that I can make pairs of similar numbers using C/C++.
In above example there are three pairs (10-10, 20-20, 10-10).
I want to find number of pairs in given array(i.e. 3).
Can anyone please help me with logic?

The approach using C can differ from the approach using C++ because for example in C++ you can use standard containers and algorithms while in C they are absent.
So I will show a solution that can be implemented in the both languages.
Here you are. The program is written using C but it is easy can be transformed in a C++ program by substituting the header and only one statement: the output statement.
#include <stdio.h>
int main( void )
{
int a[] = { 10, 20, 20, 10, 10, 30, 50, 10, 20 };
const size_t N = sizeof( a ) / sizeof( *a );
size_t total = 0;
for ( size_t i = 1; i < N; i++ )
{
size_t count = 1;
for ( size_t j = 0; j < i; j++ )
{
if ( a[i] == a[j] ) ++count;
}
if ( count % 2 == 0 ) ++total;
}
printf( "The number of pairs of equal elements is %zu\n", total );
return 0;
}
The program output is
The number of pairs of equal elements is 3
In C++ you can use for example the following alternative approach using the standard container std::map or std::unordered_map.
#include <iostream>
#include <map>
int main()
{
int a[] = { 10, 20, 20, 10, 10, 30, 50, 10, 20 };
size_t total = 0;
std::map<int, size_t> m;
for ( const auto &item : a ) ++m[item];
for ( const auto &item : m ) total += item.second / 2;
std::cout << "The number of pairs of equal elements is " << total << '\n';
return 0;
}
The program output is the same as shown above.
The number of pairs of equal elements is 3

And here the C++ solution.
Same approach as Vlad. Simply count the groups of all values and divide this counter by 2, because we are lokking for pairs.
Then count the overall counts:
#include <iostream>
#include <map>
#include <algorithm>
#include <numeric>
int main() {
// The data
int arr[] = { 10, 20, 20, 10, 10, 30, 50, 10, 20 };
// The counter for occurences of one value in the array
std::map<int, size_t> counter{};
// Do Count
for (int i : arr) counter[i]++;
// Devide all counts by 2. Thats, because we are looking for pairs
std::for_each(counter.begin(), counter.end(), [](auto& p) { p.second /= 2;});
// Calculate the overall sum
size_t pairCounter = std::accumulate(counter.begin(), counter.end(), 0U,
[](const size_t v, const auto& p) { return v + p.second; });
std::cout << "\nNumber of pairs: " << pairCounter << "\n";
return 0;
}

Related

Function returning the wrong kth value while using sets

I was attempting to solve this question on some website where you have the find the kth smallest value in c++ so I came up with:
#include <bits/stdc++.h>
using namespace std;
int kthSmallest(int arr[], int l, int r, int k) {
// l is the first index
// r is the index of the last element (size - 1)
// k is the kth smallest value
set<int> s(arr, arr + r);
set<int>:: iterator itr = s.begin();
advance(itr, (k - 1));
return *itr;
}
int main() {
int arr[] = {7, 10, 4, 20, 15};
cout << kthSmallest(arr, 0, 4, 4);
return 0;
}
This shows the output of 20 instead of 15 which is the right answer and I cannot figure out what I did wrong here.
The 2nd argument of the constructor of std::set should be an iterator for an element next to the last element, not one for the last element.
Therefore, you are operating with a set whose members are {7, 10, 4, 20}.
The line
set<int> s(arr, arr + r);
should be
set<int> s(arr, arr + r + 1);
or (to match the comment)
set<int> s(arr + l, arr + r + 1);
The range in this statement
set<int> s(arr, arr + r);
is specified incorrectly when r is equal to 4 for this array
int arr[] = {7, 10, 4, 20, 15};
that has 5 elements. It means that 15 is not present in the range [7, 10, 4, 20]. You have to specify the parameter r equal to 5 that is to the number of elements in the array instead of 4.
Also the parameter l is not used in the function.
And you need to check whether the value of k is not greater than the value of r calling the function std::advance.
Also pay attention to that the array can have duplicated values. In this case the function can return an incorrect value.
So in general your function is incorrect and unsafe.
Instead of returning an object of the type int you should return either an iterator that points to the target object in the array or to the end of the range or the index of the target element..
With your approach you should use std::multiset instead of std::set. And the value of k should start from 0 as all indices in C++. Otherwise calling the function with the value of k equal to 0 you will get undefined behavior.
Here is a demonstration program.
#include <iostream>
#include <functional>
#include <set>
#include <iterator>
size_t kthSmallest( const int arr[], size_t n, size_t k )
{
if ( not ( k < n ) ) return n;
std::multiset<std::reference_wrapper<const int>> s;
for ( size_t i = 0; i < n; i++ )
{
s.insert( std::ref( arr[i]) );
}
auto it = std::next( std::begin( s ), k );
size_t result = std::distance( arr, &it->get() );
return result;
}
int main()
{
int arr[] = {7, 10, 4, 20, 15};
const size_t N = sizeof( arr ) / sizeof( *arr );
for ( size_t i = 0; i < N; i++ )
{
std::cout << i << ": " << arr[kthSmallest( arr, N, i )] << '\n';
}
return 0;
}
The program output is
0: 4
1: 7
2: 10
3: 15
4: 20

loop over map of vectors and get max across columns in c++

I have a map defined as follows:
const map<int, vector<float> >& m = …;
I want to loop over the columns (size of the map.second: vector) and in every iteration I get the:
1- The max value of the column across the map.first: int
2- The value of the map.first: int at the which the max occurs
For example:
#0 I get 31, 1
#1 I get 15, 2
#2 I get 18, 2
What is the easiest way to do this?
You need a function that accepts a column number and loops through each row calculating the maximum for that column.
You only need one loop because you can access whichever column you want by indexing the vector like an array (as long as you check that the vector has enough elements)
There are two ways to do this: the C++17 way where you can assign objects with multiple values directly to multiple variables, and the old way where you reference the members of std::pair instead.
The C++17 way:
#include <map>
#include <vector>
#include <utility>
#include <iostream>
std::pair<int,float> column_max(const auto & m, int column)
{
int index = -1;
float maximum = -std::numeric_limits<float>::max();
for (const auto & [key,value] : m)
if (value.size() > column && value[column] > maximum)
{
index = key;
maximum = value[column];
}
return {index,maximum};
}
int main()
{
const std::map<int,std::vector<float>> m =
{
{0, { 1, 5, 10, 22}},
{1, {31, 5, 10, 12}},
{2, { 1, 15, 18, 12}}
};
for (int i=0; i<4; i++)
{
const auto [index,maximum] = column_max(m,i);
std::cout << "#" << i << ": " << maximum << " " << index << "\n";
}
return 0;
}
Try it here: https://onlinegdb.com/O5dmPot34
And the equivalent, but older way:
#include <map>
#include <vector>
#include <utility>
#include <iostream>
#include <float.h>
std::pair<int,float> column_max(const std::map<int,std::vector<float>> & m, int column)
{
int index = -1;
float maximum = -FLT_MAX;
for (std::map<int,std::vector<float>>::const_iterator entry=m.begin(); entry!=m.end(); entry++)
if (entry->second.size() > column && entry->second[column] > maximum)
{
index = entry->first;
maximum = entry->second[column];
}
return std::make_pair(index,maximum);
}
int main()
{
const std::map<int,std::vector<float>> m =
{
{0, { 1, 5, 10, 22}},
{1, {31, 5, 10, 12}},
{2, { 1, 15, 18, 12}}
};
for (int i=0; i<4; i++)
{
std::pair<int,float> value = column_max(m,i);
std::cout << "#" << i << ": " << value.second << " " << value.first << "\n";
}
return 0;
}
Try it here: https://onlinegdb.com/273dnHRZK

Finding the lowest missing integer in a vector containing positive and negative int's?

I'm writing an operation to find the lowest missing element of a vector, V = 1..N + 1. This has to be performed in O(N) time complexity.
Solution One:
std::vector<int> A {3,4,1,4,6,7};
int main()
{
int max_el = *std::max_element(A.begin(), A.end()); //Find max element
std::vector<int> V(max_el);
std::iota(V.begin(), V.end(), 1) //Populate V with all int's up to max element
for(unsigned into i {0}; i < A.size(); i++)
{
int index = A[i] - 1;
if(A[i] == V[index]) //Search V in O(1)
{
V[index] = max_el; //Set each to max_el, leaving the missing int
}
}
return *std::min_element(V.begin(), V.end()); //Find missing int as its the lowest (hasn't been set to max_el)
}
//Output: 2
This works completely fine.
However, I'm now trying to get this to work with vector containing negative int's.
Solution Two:
My logic is to take the same approach, however 'weight' the indexes given the size of the vector and the number of negative int's in the vector:
std::vector<int> A {-1, -4, -2, 0, 3, 2, 1}
int main()
{
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int min_el_abs = abs(min_el); //Convert min element to absolute
int total = min_el_abs + max_el;
std::vector<int> V(total + 1);
std::iota(V.begin(), V.end(), min_el);
int index;
//Find amount of negative int's
int first_pos;
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] >= 0) {first_pos = i; break;}
}
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] <= 0) //If negative
{
index = (A.size() - first_pos) - abs(A[i]);
} else
{
index = (A[i] + 1) + first_pos;
}
if(A[i] == V[index])
{
V[index] = 0;
}
}
return *std::min_element(V.begin(), V.end());
}
//Output: -3
Solution Two fails to compare the values of the two vectors (A and V), as calculating the index with the above methods with a positive int doesn't work.
1) How can I get my Solution 2 to work with unordered vector's of negative int's?
2) How can I edit my Solution 2 to work with vectors of positive as well as vectors with negative int's?
Your first solution seems O(max(N,M)), where I consider N the number of elements in vector A and M the size of vector V (or max(Ai)), but you are looping through both vectors multiple times (with std::min_element, std::max_element, the for loop, the allocation of V and std::iota too).
Besides, once corrected a couple of typos (a missing ; and an into instead of int), your program returns the value found... from main(), which is a bit odd.
Your first algorithm always searches for the lowest missing value in the range [1, max value in A], but it can be generalized to find the lowest missing element in the range [min(Ai), max(Ai)], even for negative numbers.
My approach is similar to that of L.Senioins, but I've used different library functions trying to minimize the number of loops.
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
template <class ForwardIt>
typename std::iterator_traits<ForwardIt>::value_type
lowest_missing(ForwardIt first, ForwardIt last)
{
if ( first == last )
throw std::string {"The range is empty"};
// find both min and max element with one function
auto result = std::minmax_element(first, last);
// range is always > 0
auto range = *result.second - *result.first + 1;
if ( range < 2 )
throw std::string {"Min equals max, so there are no missing elements"};
std::vector<bool> vb(range); // the initial value of all elements is false
for (auto i = first; i != last; ++i)
vb[*i - *result.first] = true;
// search the first false
auto pos = std::find(vb.cbegin(), vb.cend(), false);
if ( pos == vb.cend() ) // all the elements are true
throw std::string {"There are no missing elements"};
return std::distance(vb.cbegin(), pos) + *result.first;
}
template <class ForwardIt>
void show_the_first_missing_element(ForwardIt first, ForwardIt last)
{
try
{
std::cout << lowest_missing(first, last) << '\n';
}
catch(const std::string &msg)
{
std::cout << msg << '\n';
}
}
int main() {
std::vector<int> a { 1, 8, 9, 6, 2, 5, 3, 0 };
show_the_first_missing_element(a.cbegin(), a.cend());
std::vector<int> b { -1, -4, 8, 1, -3, -2, 10, 0 };
show_the_first_missing_element(b.cbegin(), b.cend());
show_the_first_missing_element(b.cbegin() + b.size() / 2, b.cend());
std::vector<int> c { -2, -1, 0, 1, 2, 3 };
show_the_first_missing_element(c.cbegin(), c.cend());
std::vector<int> d { 3, 3, 3 };
show_the_first_missing_element(d.cbegin(), d.cend());
std::vector<int> e;
show_the_first_missing_element(e.cbegin(), e.cend());
return 0;
}
The results outputted for my test cases are:
4
2
-1
There are no missing elements
Min equals max, so there are no missing elements
The range is empty
My solution is to make a bool vector (or char vector just to avoid compilation warnings about casting to bool) which has the size of all possible elements. All elements are initialized to 0 and later are assigned to 1 which indicates that the element is not missing. All you need to do then is to find an index of the first 0 element which is the lowest missing element.
#include <vector>
#include <algorithm>
#include <iostream>
std::vector<int> A{ -1, 0, 11, 1, 10, -5 };
int main() {
if (A.size() > 1) {
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int range = abs(max_el - min_el) + 1;
std::vector<int> V(range, 0);
for (size_t i = 0; i < A.size(); i++)
V[A[i] - min_el] = 1;
if (*std::min_element(V.begin(), V.end()) == 0)
std::cout << std::distance(V.begin(), std::find(V.begin(), V.end(), 0)) + min_el;
else
std::cout << "There are no missing elements" << std::endl;
}
else
std::cout << "There are no missing elements" << std::endl;
std::cin.get();
}
I'm going to try give my own question an answer, after spending sometime thinking about this:
int main()
{
std::vector<int> A {-3, -1, 0, 1, 3, 4};
auto relative_pos = std::minmax_elment(A.begin(), A.end());
std::vector<bool> Litmus( *(relative_pos.second) - *(relative_pos.first), false); //Create vector of size max val - min val)
auto lowest_val = *(relative_pos.first);
for(auto x : A)
{
Litmus[i - lowest_val] = true;
}
auto pos = std::find(Litmus.begin(), Litmus.end(), false); //Find the first occurring false value
std::cout<< (pos - Litmus.begin()) + lower<<std::endl; //Print the val in A relative to false value in Litmus
}
This solution works with negative numbers and is linear.
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <numeric>
int solution(vector<int> &A) {
std::vector<int>::iterator it = std::max_element(A.begin(),A.end());
try
{
sort(A.begin(),A.end());
std::vector<int>::iterator it = std::unique(A.begin(),A.end());
A.resize(std::distance(A.begin(),it));
for(int i = 0, j = 1; i < A.size(); i++)
{
if( A[i] != j)
{
return j;
}
j++;
}
}
catch(exception &e)
{
std::cout<<e.what()<<std::endl;
}
return ++(*it);
}

dividing duplicates by the counter of duplicates

the program i'm trying to write gets info from user, check duplicate in weight and count those duplicates.
For example,
{10, 40, 30, 40, 30} each 40 and 30 is duplicated 2 times
so it should be {10, 20, 15, 20, 15}
and this is my code:
struct Data {
int id;
double weight
}
std::sort(p, p + num, acompare);
for (int i = 0; i < num; i += counter) {
for (counter = 1; i + counter<num&& p[i + counter].weight== p[i].weight; )
counter++; // count consecutives dups
if (counter>1) { // if more than one, process the dups.
cntArr[i] = counter;
cntArr[counter] = counter;
} else
cntArr[i] = 1;
}
for (int i = 0; i < num; i++) {
cout << p[i].id << ":" << p[i].weight/ (double) cntArr[i] << endl;
}
and the result is like this
input :
1 100
2 100
3 100
4 80
5 80
output :
4 40
5 -9.79969e-08
1 33.3333
2 33.3333
3 -1.18744e-07
How do i fix this?
It's a bit hard to debug the specific problem in your code, as it isn't complete (can't copy-paste it to an editor and build it). In particular, not sure what are p, cntArray, and how they are initialized.
However, fundamentally, this code could be made shorter and more efficient. Instead of sorting (immediate Θ(n log(n)) complexity), use an std::unordered_map to store the multiplicity of each element. Shorter, fewer potential bugs, and (expected) linear complexity.
#include <vector>
#include <unordered_map>
#include <iostream>
#include <algorithm>
int main() {
const std::vector<int> a{10, 40, 30, 40, 30};
std::unordered_map<int, std::size_t> counts;
std::for_each(std::begin(a), std::end(a), [&](int e){ ++counts[e]; });
std::for_each(std::begin(a), std::end(a),
[&](int e){ std::cout << e / static_cast<double>(counts[e]) << std::endl; });
}
Outputs:
$ ./a.out
10
20
15
20
15

Absolute Distinct Numbers

I am writing an exercises on codility via c++. Here the question:
A non-empty zero-indexed array A consisting of N numbers is given. The
array is sorted in non-decreasing order. The absolute distinct count
of this array is the number of distinct absolute values among the
elements of the array.
For example, consider array A such that:
A[0] = -5
A[1] = -3
A[2] = -1
A[3] = 0
A[4] = 3
A[5] = 6
The absolute distinct count of this array is 5, because there are 5 distinct absolute values among the elements of this array,
namely 0, 1, 3, 5 and 6.
Write a function:
int solution(vector<int> &A);
that, given a non-empty zero-indexed array A consisting of N numbers,
returns absolute distinct count of array A.
For example, given array A such that:
A[0] = -5
A[1] = -3
A[2] = -1
A[3] = 0
A[4] = 3
A[5] = 6
the function should return 5, as explained above.
Assume that:
N is an integer within the range [1..100,000];
each element of array A
is an integer within the range [−2,147,483,648..2,147,483,647];
array
A is sorted in non-decreasing order.
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space
complexity is O(N), beyond input storage (not counting the storage
required for input arguments).
Elements of input arrays can be
modified.
I am writing down the following code, and I fail to find any problems in my code, but it just doesn't pass.
#include <algorithm>
#include <vector>
#include <cmath>
int solution(vector<int> &A) {
int N(A.size());
vector<long long> B(N,0);
int counter(1);
//int index(0);
int move1(0);
int move2(N-1);
if(N==1)
{return 1;}
if(N==0)
{return 0;}
if(N==2)
{
if(abs(A[0])==abs(A[1]))
{return 1;}
else{return 2;}
}
for (int i = 0 ; i < N ; ++i)
{
B[i]=abs((long long )A[i]);
}
while(move1<move2)
{
if(B[move1]==B[move1+1])
{move1+=1;}
else if(B[move2]==B[move2]-1)
{move2-=1;}
else if(B[move1]>B[move2])
{
counter+=1;
move1+=1;
}
else if(B[move1]<B[move2])
{
counter+=1;
move2-=1;
}
else{move1+=1;}
}
return counter;
}
Here's the link of performance, https://codility.com/demo/results/trainingUT9QAN-JMM/
There's some errors but I can't figure out its detail, if anyone could help me with my code, I will really appreciate!
Thanks!
You may want to have an iterative solution. Start from both ends and work your way inward toward 0.
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
size_t solution( const std::vector< int > & A )
{
std::vector< int >::const_iterator f( A.begin() );
std::vector< int >::const_reverse_iterator b( A.rbegin() );
size_t result = 0;
if( A.size() )
for( ; ( f != A.end() ) && ( b != A.rend() ); )
{
if( *f >= 0 )
return result + ( ( A.end() - f ) - ( b - A.rbegin() ) );
else if( *b <= 0 )
return result + ( ( A.rend() - b ) - ( f - A.begin() ) );
else if( *f == -*b )
++result, ++f, ++b;
else if( *f > -*b )
++result, ++b;
else
++result, ++f;
}
return result;
}
int main( int, char ** )
{
std::cout << solution( std::vector< int >{ -5, -3, -1, 0, 3, 6} ) << std::endl;
std::cout << solution( std::vector< int >{ -5, -3, -1, 0, 1, 3, 6} ) << std::endl;
std::cout << solution( std::vector< int >{ -5, -3, -1, 0, 2, 3, 6} ) << std::endl;
std::cout << solution( std::vector< int >{ -5, -3, -1, 3, 6} ) << std::endl;
std::cout << solution( std::vector< int >{ -5, -3, -1, 0, 3, 4, 5} ) << std::endl;
return 0;
}
100% solution with Ruby
def solution(a)
a.each_with_object({}){ |el, acc| acc[el.abs] = true }.size
end
Got 100/100 using Java 8 streams.
return (int) Arrays.stream(A).map(Math::abs)
.distinct().count();
def solution(A):
# Creates an empty hashset
s = set()
n = len(A)
res = 0
for i in range(n):
# If not present, then put it in
# hashtable and increment result
if (A[i] not in s):
s.add(A[i])
res += 1
return res