I'm trying to compile the following C++ code but its showing the errors shown in the image attached.compiler used is visual studio. Please inspect the code and tell me what is the problem here:
#include <iostream>
#include <vector>
#include <iterator>
template<typename T>
struct MinMax {
pair<> operator()(T itrStart, T itrEnd) {
auto max = *itrStart;
auto min = *itrStart;
for (auto itr = itrStart; itr != itrEnd; itr++) {
min = *itr < min ? *itr : min;
max = *itr > max ? *itr : max;
}
std::cout << min << std::endl;
std::cout << max << std::endl;
return { min,max };
}
};
int main() {
std::vector<int> arr{ 2,3,4,5 };
MinMax<std::vector<int>::iterator> Z;
std::pair<int,int> p = Z(arr.begin(), arr.end());
std::cout << p.first << std::endl;
std::cout << p.second << std::endl;
return 0;
}
The problem is that you've not specified any template argument for std::pair when using it to specify the return type of operator().
To solve this you can make use of std::make_pair and the placeholder type auto as shown below:
vvvv-------------------------------------------->use auto
auto operator()(T itrStart, T itrEnd) {
auto max = *itrStart;
auto min = *itrStart;
//other code here
//-------------vvvvvvvvvvvvvv------------------->use std::make_pair
return std::make_pair( min,max );
}
Working demo.
Related
I am trying to solve a question on leetcode which is finding the top k frequent elements. I think my code is correct but the output for a test case is failing.
Input: [ 4,1,-1,2,-1,2,3]
K=2
My answer comes out to be {1,-1} but the expected is {-1,2}. I am not sure where am i getting wrong.
struct myComp{
constexpr bool operator()(pair<int,int> & a,pair<int,int> &b)
const noexcept
{
if(a.second==b.second)
{
return a.first<b.first;
}
return a.second<b.second;
}
};
class Solution {
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> mp;
for(int i=0;i<nums.size();i++)
{
mp[nums[i]]++;
}
priority_queue<pair<int,int>,vector<pair<int,int>>,myComp> minheap;
for(auto x:mp)
{
minheap.push(make_pair(x.second,x.first));
if(minheap.size()>k)
{
minheap.pop();
}
}
vector<int> x;
while(minheap.size()>0)
{
x.push_back(minheap.top().second);
minheap.pop();
}
return x;
link: https://leetcode.com/problems/top-k-frequent-elements
In the minheap, pairs of <frequency, element> are being pushed. Since we want to sort these pairs on basis of frequency, we need to compare on the basis of frequency only.
Let's say there are two pairs a and b. Then for normal sorting, the comparison would be :
a.first < b.first;
And for reverse sorting, the comparison would be :
a.first > b.first;
In case of min-heap, we need reverse sorting. Hence, the following comparator makes your code pass all the test cases :
struct myComp
{
constexpr bool operator()(pair<int,int> & a,pair<int,int> &b)
const noexcept
{
return a.first > b.first;
}
};
There are several issues with your code.
Obviously there is somewhere using namespace std; in your code. This should be avoided. You will find many posts here on SO explaining, why it this should not be done.
Then we need to qualify all elements from the std library with std::, which makes the scope very clear.
Next: You do not need your own sorting function. Since you insert the elements from the pair in swapped order into the std::priority_queue, the sorting criteria is valid for the counter part, not for the key value. So, your sorting function was anyway wrong, because it was sorting accodring to "second" and not to "first". But if we have a standard sorting, we do not need a special sorting algorithm. A std::pair has a less-than operator. So, the definition can be simply:
std::priority_queue<std::pair<int, int>> minheap;
Then, your if statement
if(minheap.size()>k)
{
minheap.pop();
}
is wrong. You will allow only k values to be inserted. And this are not necessarily the biggest ones. So, you need to insert all values from the std::unordered map. And then they are sorted.
With some cosmetic changes the code will look like the below:
#include <iostream>
#include <utility>
#include <unordered_map>
#include <vector>
#include <queue>
std::vector<int> topKFrequent(std::vector<int>& nums, size_t k) {
std::unordered_map<int, int> mp;
for (size_t i = 0; i < nums.size(); i++)
{
mp[nums[i]]++;
}
std::priority_queue<std::pair<int, int>> minheap;
for (auto x : mp)
{
minheap.push(std::make_pair(x.second, x.first));
}
std::vector<int> x;
for (size_t i{}; i< k; ++i)
{
x.push_back(minheap.top().second);
minheap.pop();
}
return x;
}
int main() {
std::vector data{ 4,1,-1,2,-1,2,3 };
std::vector result = topKFrequent(data, 2);
for (const int i : result) std::cout << i << ' '; std::cout << '\n';
return 0;
}
An additional solution
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <utility>
auto topKFrequent(std::vector<int>& nums, size_t k) {
// Count occurences
std::unordered_map<int, size_t> counter{};
for (const int& i : nums) counter[i]++;
// For storing the top k
std::vector<std::pair<int, size_t>> top(k);
// Get top k
std::partial_sort_copy(counter.begin(), counter.end(), top.begin(), top.end(),
[](const std::pair<int, size_t >& p1, const std::pair<int, size_t>& p2) { return p1.second > p2.second; });
return top;
}
// Test code
int main() {
std::vector data{ 4,1,-1,2,-1,2,3 };
for (const auto& p : topKFrequent(data, 2))
std::cout << "Value: " << p.first << " \t Count: " << p.second << '\n';
return 0;
}
And of course, we do have also the universal solution for any kind of iterable container. Including the definition for type traits using SFINAE and checking for the correct template parameter.
#include <iostream>
#include <utility>
#include <unordered_map>
#include <algorithm>
#include <vector>
#include <iterator>
#include <type_traits>
// Helper for type trait We want to identify an iterable container ----------------------------------------------------
template <typename Container>
auto isIterableHelper(int) -> decltype (
std::begin(std::declval<Container&>()) != std::end(std::declval<Container&>()), // begin/end and operator !=
++std::declval<decltype(std::begin(std::declval<Container&>()))&>(), // operator ++
void(*std::begin(std::declval<Container&>())), // operator*
void(), // Handle potential operator ,
std::true_type{});
template <typename T>
std::false_type isIterableHelper(...);
// The type trait -----------------------------------------------------------------------------------------------------
template <typename Container>
using is_iterable = decltype(isIterableHelper<Container>(0));
// Some Alias names for later easier reading --------------------------------------------------------------------------
template <typename Container>
using ValueType = std::decay_t<decltype(*std::begin(std::declval<Container&>()))>;
template <typename Container>
using Pair = std::pair<ValueType<Container>, size_t>;
template <typename Container>
using Counter = std::unordered_map<ValueType<Container>, size_t>;
// Function to get the k most frequent elements used in any Container ------------------------------------------------
template <class Container>
auto topKFrequent(const Container& data, size_t k) {
if constexpr (is_iterable<Container>::value) {
// Count all occurences of data
Counter<Container> counter{};
for (const auto& d : data) counter[d]++;
// For storing the top k
std::vector<Pair<Container>> top(k);
// Get top k
std::partial_sort_copy(counter.begin(), counter.end(), top.begin(), top.end(),
[](const std::pair<int, size_t >& p1, const std::pair<int, size_t>& p2) { return p1.second > p2.second; });
return top;
}
else
return data;
}
int main() {
std::vector testVector{ 1,2,2,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,6,7 };
for (const auto& p : topKFrequent(testVector, 2)) std::cout << "Value: " << p.first << " \t Count: " << p.second << '\n';
std::cout << '\n';
double cStyleArray[] = { 1.1, 2.2, 2.2, 3.3, 3.3, 3.3 };
for (const auto& p : topKFrequent(cStyleArray, 2)) std::cout << "Value: " << p.first << " \t Count: " << p.second << '\n';
std::cout << '\n';
std::string s{"abbcccddddeeeeeffffffggggggg"};
for (const auto& p : topKFrequent(s, 2)) std::cout << "Value: " << p.first << " \t Count: " << p.second << '\n';
std::cout << '\n';
double value = 12.34;
std::cout << topKFrequent(value,2) << "\n";
return 0;
}
Developed and tested with Microsoft Visual Studio Community 2019, Version 16.8.2.
Additionally compiled and tested with clang11.0 and gcc10.2
Language: C++17
For example, if I have a sorted array
{1,1,1,1,1,4,5}
and I want to know the rightmost index of 1, is there a function that will allow me to do that? (Apart from reverse sorting the array)
This should work:
auto p = std::equal_range( std::begin(v), std::end(v), 1 );
if( p.first != p.second ) {
auto it = p.second - 1;
//...
}
live example
There's none so you should craft one on your own.
template<class Ctr, class Elem> auto rightmost(Ctr &&c, Elem &&e) {
using std::begin;
using std::end;
auto b{begin(c)};
auto retVal{std::upper_bound(b, end(c), e)};
return retVal == b? b : --retVal;
}
#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>
int main()
{
std::array<int, 6> data({2,2,2,2,4,7});
auto it = std::upper_bound(data.begin(), data.end(), 2);
int index = std::distance(data.begin(), it) - 1;
std::cout << "index for last '2' is " << index << std::endl;
}
output:
index for last '2' is 3
I have classes that collect index values from different constant STL vectors. Problem is, even if these vectors are different in content and they have different purposes, their indexes are of type std::size_t, so one might erroneusly use the index stored for one vector to access the elements of another vector. Can the code be changed in order to have a compile time error when a index is not used with the correct vector?
A code example:
#include <iostream>
#include <string>
#include <vector>
struct Named
{
std::string name;
};
struct Cat : Named { };
struct Dog : Named { };
struct Range
{
std::size_t start;
std::size_t end;
};
struct AnimalHouse
{
std::vector< Cat > cats;
std::vector< Dog > dogs;
};
int main( )
{
AnimalHouse house;
Range cat_with_name_starting_with_a;
Range dogs_with_name_starting_with_b;
// ...some initialization code here...
for( auto i = cat_with_name_starting_with_a.start;
i < cat_with_name_starting_with_a.end;
++i )
{
std::cout << house.cats[ i ].name << std::endl;
}
for( auto i = dogs_with_name_starting_with_b.start;
i < dogs_with_name_starting_with_b.end;
++i )
{
// bad copy paste but no compilation error
std::cout << house.cats[ i ].name << std::endl;
}
return 0;
}
Disclaimer: please do not focus too much on the example itself, I know it is dumb, it is just to get the idea.
Here is an attempt following up on my comment.
There are of course a lot of room to change the details of how this would work depending on the use-case, this way seemed reasonable to me.
#include <iostream>
#include <vector>
template <typename T>
struct Range {
Range(T& vec, std::size_t start, std::size_t end) :
m_vector(vec),
m_start(start),
m_end(end),
m_size(end-start+1) {}
auto begin() {
auto it = m_vector.begin();
std::advance(it, m_start);
return it;
}
auto end() {
auto it = m_vector.begin();
std::advance(it, m_end + 1);
return it;
}
std::size_t size() {
return m_size;
}
void update(std::size_t start, std::size_t end) {
m_start = start;
m_end = end;
m_size = end - start + 1;
}
Range copy(T& other_vec) {
return Range(other_vec, m_start, m_end);
}
typename T::reference operator[](std::size_t index) {
return m_vector[m_start + index];
}
private:
T& m_vector;
std::size_t m_start, m_end, m_size;
};
// This can be used if c++17 is not supported, to avoid
// having to specify template parameters
template <typename T>
Range<T> make_range(T& t, std::size_t start, std::size_t end) {
return Range<T>(t, start, end);
}
int main() {
std::vector<int> v1 {1, 2, 3, 4, 5};
std::vector<double> v2 {0.5, 1., 1.5, 2., 2.5};
Range more_then_2(v1, 1, 4); // Only works in c++17 or later
auto more_then_1 = make_range(v2, 2, 4);
for (auto v : more_then_2)
std::cout << v << ' ';
std::cout << std::endl;
for (auto v : more_then_1)
std::cout << v << ' ';
std::cout << std::endl;
more_then_2.update(2,4);
for (auto v : more_then_2)
std::cout << v << ' ';
std::cout << std::endl;
auto v3 = v1;
auto more_then_2_copy = more_then_2.copy(v3);
for (unsigned i=0; i < more_then_2_copy.size(); ++i)
std::cout << more_then_2_copy[i] << ' ';
return 0;
}
How can you displace the location you iterate through a vector? I've tried something like:
for(auto x : vect+2)
but this doesn't work. I'm sure there's a simple resolve, but I haven't been able to find anything online.
If you want to use the range-based for, you could use Boost.Range to create a range that starts from the third element of your vector (begin() + 2):
for (auto x : boost::make_iterator_range(begin(v) + 2, end(v)))
{
std::cout << x << " ";
}
Here is a simple example:
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
int main()
{
std::vector<int> v(10);
iota(begin(v), end(v), 1);
for (auto x : boost::make_iterator_range(begin(v) + 2, end(v)))
{
std::cout << x << " ";
}
}
If you want to loop through every second element, instead, you could change your range as follows:
namespace rng = boost::adaptors;
for (auto x : v | rng::strided(2))
{
std::cout << x << " ";
}
Which in a full program would be:
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
int main()
{
namespace rng = boost::adaptors;
std::vector<int> v(10);
iota(begin(v), end(v), 1);
for (auto x : v | rng::strided(2))
{
std::cout << x << " ";
}
}
Boost.Range is pretty flexible, so you can for instance combine the two adapters above:
for (auto x : boost::make_iterator_range(begin(v) + 2, end(v)) |
rng::strided(3))
{
std::cout << x << " ";
}
If you do not want or cannot use Boost, you could use a classical for loop with iterators:
for (auto i = begin(v) + 2; i != end(v); ++i)
{
std::cout << *i << " ";
}
This is how the whole program would look like:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v(10);
iota(begin(v), end(v), 1);
for (auto i = begin(v) + 2; i != end(v); ++i)
{
std::cout << *i << " ";
}
}
This can be achieved very simply, and has a number of solutions to suit any programming style.
The Classical Approach
int main()
{
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1);
for (auto i = v.begin() + 2; i != v.end(); ++i)
{
std::cout << *i << " ";
}
}
The Functional Approach
int main()
{
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 1);
std::for_each(v.begin() + 2, v.end(), [](int val)
{
std::cout << val << " ";
}
);
}
You could add a light wrapper to make it work with range-based for:
#include <iostream>
#include <vector>
#include <iterator>
namespace range
{
template <typename C>
struct make_range
{
C t;
make_range(C t, int offset)
: t(std::begin(t) + offset, std::end(t))
{}
auto begin() -> decltype(t.begin())
{
return t.begin();
}
auto end() -> decltype(t.end())
{
return t.end();
}
};
}
int main()
{
std::vector<int> v{1, 2, 3, 4, 5};
for (auto i : range::make_range<decltype(v)>(v, 2))
{
std::cout << i << std::endl;
}
}
Perhaps it would be better to just store the iterators:
namespace range
{
template <typename C>
struct make_range
{
typename C::iterator beg_iter;
typename C::iterator end_iter;
make_range(C& t, int offset)
: beg_iter(std::begin(t) + offset), end_iter(std::end(t))
{}
auto begin() -> decltype(beg_iter)
{
return beg_iter;
}
auto end() -> decltype(end_iter)
{
return end_iter;
}
};
}
I'm trying to re-write some MatLab code in C++ and I've come across this:
currentsign = sign(vector(i));
I have looked on the internet and found this link: http://www.mathworks.co.uk/help/techdoc/ref/sign.html
I'm just wondering if there's a sign function in C++? If not, can anyone suggest any tutorials on creating it.
Thank you :)
template <typename T>
int sign (const T &val) { return (val > 0) - (val < 0); }
Credit due to Ambroz Bizjak.
template <typename T>
std::vector<int> sign (const std::vector<T> &v) {
std::vector<int> r(v.size());
std::transform(v.begin(), v.end(), r.begin(), (int(*)(const T&))sign);
return r;
}
Full example on ideone.
I would suggest
First, write a function of functor that takes a single element and returns 1, -1 or 0 depending on the element's value
Second, use std::transform together with this function/functor to take an input container and fill a second container with the desired values
template <typename T>
int signum(const T& val) {
// implement signum logic
}
#include <vector>
#include <algorithm>
int main() {
std::vector<int> data = ....;
std::vector<int> signs(data.size());
std::transform(data.begin(), data.end(), signs.begin(), signum<int>);
}
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <vector>
inline int get_signum(int val) {
return val < 0 ? -1
: val == 0 ? 0
: 1;
}
int main() {
std::vector<int> values;
for (int i = -5; i < 6; ++i)
values.push_back(i);
std::vector<int> signum(values.size());
std::transform(values.begin(), values.end(), signum.begin(), get_signum);
for (int i = 0; i < values.size(); ++i) {
std::cout << std::setw(2) << values[i] << ' ' << signum[i] << std::endl;
}
return 0;
}
Well You can do It at compile time using template Specialization.
You can use sign<n>::Positive, sign<n>::Negetive and sign<n>::Zero also you can use sign<n>::Sign which is 1|0|-1 which is same as sign of Matlab.
#include <iostream>
template<int n>
struct sign{
enum{
Positive = (n > 0),
Negetive = (n < 0),
Zero = 0,
Sign = ((n > 0) ? 1 : -1)
};
};
template<>
struct sign<0>{
enum{
Positive = 0,
Negetive = 0,
Zero = 1,
Sign = 0
};
};
int main(){
std::cout << sign<0>::Positive << sign<0>::Negetive << sign<0>::Zero << sign<0>::Sign << std::endl;
std::cout << sign<1>::Positive << sign<1>::Negetive << sign<1>::Zero << sign<1>::Sign << std::endl;
std::cout << sign<-1>::Positive << sign<-1>::Negetive << sign<-1>::Zero << sign<-1>::Sign << std::endl;
return 0;
}
You used to do sign(n) there and here you will do sign<n>::Sign.
C99 has signbit() and copysign(), which seem to be implemented in glibc on Linux. You didn't specify what platform you're on though, so I'm not sure that helps...