C++ Sign function - From MatLab? - c++

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...

Related

The following C++ template code is showing error. Please inspect why

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.

Finding the top K frequent Elements

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

How to create my own loop version in C++?

I was wondering if it possible to create custom functions like for, for_each, while etc.
There's nothing that I want to do that the existing loops won't do it. I am just curious to learn how they work and if I ever need to create my own.
For example if one wants to create another version of the for function that would take only parameter.
In this example, I want to to create a for that only takes one parameter, an integer.
Instead of writing
for (int i = 0; i < 50; ++i)
I would create a for version like this
for_(50)
and they would act the same. How would I do something like that?
I have posted this question in another forum.
In addition to the proposals in other answers, you could create a function like the one below, but it is, at the very end, very similar to using the standard std::for_each.
#include <iostream>
#include <functional>
template<typename C, typename F>
void for_(C begin_, C end_, F&& f) { // [begin_, end_)
for (C i = begin_; i < end_; ++i) {
f(i);
}
}
template<typename C, typename F>
void for_(C count, F&& f) { // special case for [0, count)
for_(0, count, f);
}
void mul2(int x) {
std::cout << x*2 << " ";
}
int main() {
for_(10, [](int i) { std::cout << i << "\n"; });
for_(2, 10, mul2);
}
An ugly and unsafe solution is to use macro:
#define REPEAT(i,N) for(int (i) = 0; (i) < (N); ++(i))
int main()
{
REPEAT(i,10) std::cout << i << std::endl;
return 0;
}
You can't extend the C++ syntax for new loops.
You could use a macro, but this is pretty ugly, and generally best avoided. Another way to get something similar is by passing a functor as a parameter, greatly helped by the introduction of lambda expressions to C++. You can find some examples of such in the <algorithm> header.
For example:
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> numbers = { 1, 4, 5, 7, 10 };
int even_count = 0;
for (auto x : numbers)
{
if (x % 2 == 0)
{
++even_count;
}
}
auto even_count2 = std::count_if(numbers.begin(), numbers.end(), [](int x) { return x % 2 == 0; });
}
You could use a lambda function and pass in a function object as a parameter to be performed for every iteration of the loop.
#include <iostream>
#include <functional>
int main()
{
auto for_ = [](int start, int size, std::function<void (int i)> fn)
{
int end = start + size;
for (int i = start; i < end; ++i)
{
fn(i);
}
};
for_(0, 10, [](int i) { std::cout << i << std::endl; });
for_(0, 10, [](int i) { std::cout << i*2 << std::endl; });
}
It seems like you are reinventing the wheel here a bit. You could just use std::for_each.
However, you could have custom lambda functions that do different things and just implement the operation within the lambda itself without taking in a function object for the operation.

Calling a generic lambda in boost::mpl::for_each()

A few answers here (How to loop through a boost::mpl::list? being the one I started with) imply that I should be able to construct a generic lambda to feed to a boost::mpl::for_each() but I'm unable to find a working example, or build one myself.
Idealy what I would like to be able to do in a lambda is take a function like
template<typename T>
void TestFunction(const int &p)
{
T t(p);
std::cout << "p = " << p << ", t = " << t << std::endl;
};
that I'm currently calling in a loop with something like
for(int k = 0; k < 2; ++k)
{
TestFunction<int>(k);
TestFunction<long>(k);
TestFunction<float>(k);
TestFunction<double>(k);
};
and replace it with something like
typedef boost::mpl::list<int, long, float, double> ValidTypes;
for(int k = 0; k < 2; ++k)
{
// lambda definition that captures k
// boost::mpl::for_each(ValidTypes, ...) that calls the lambda.
};
Is this possible? If not with for_each() with one of the other mpl constructs? I've got a version of the code running where I overload operator() but I'd like to see a lambda solution if it's possible.
Thanks,
Andy.
If you can use C++14's generalized lambdas, you can capture the value of p and also infer the type of the current valid type being passed to the lambda:
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/list.hpp>
#include <iostream>
int main()
{
using ValidTypes = boost::mpl::list<int, long, float, double>;
for (auto k = 0; k < 2; ++k) {
boost::mpl::for_each<ValidTypes>([p = k](auto arg) {
using T = decltype(arg);
T t(p);
std::cout << "p = " << p << ", t = " << t << '\n';
});
}
}
Live Example.
Edit: for extra credit, here's a slightly more advanced version that also works for non-default constructible types:
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/list.hpp>
#include <iostream>
class NonDefaultConstructible
{
int value;
public:
NonDefaultConstructible(int const& p) : value(p) {}
friend auto& operator<<(std::ostream& ostr, NonDefaultConstructible const& ndc)
{
return ostr << ndc.value;
}
};
int main()
{
using ValidTypes = boost::mpl::list<int, long, float, double, NonDefaultConstructible>;
for (auto k = 0; k < 2; ++k) {
boost::mpl::for_each<ValidTypes, boost::mpl::make_identity<boost::mpl::_1>>([p = k](auto arg) {
using T = typename decltype(arg)::type;
T t(p);
std::cout << "p = " << p << ", t = " << t << '\n';
});
}
}
Live Example.
For an explanation of the somewhat convoluted use of make_identity, see my very first Q&A here!

How to convert arrays to vectors using STL

This code is a linear search program using arrays. Out of curiosity, I was wondering how this code could be rewritten using STL vectors in place of arrays but still have the same output.
#include <iostream>
#include <string>
using namespace std;
template <typename T>
int linearSearch(T list[], int key, int arraySize)
{
for (int i = 0; i < arraySize; i++)
{
if (key == list[i])
return i;
}
return -1;
}
int main()
{
int intArray[] =
{
1, 2, 3, 4, 8, 15, 23, 31
};
cout << "linearSearch(intArray, 3, 8) is " << linearSearch(intArray, 3, 8) << endl;
cout << "linearSearch(intArray, 10, 8) is " << linearSearch(intArray, 10, 8) << endl;
return 0;
}
you can do it by changing your parameter type and in main.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template <typename T>
int linearSearch(vector<T> list, int key)
{
for (size_t i = 0; i < list.size(); i++)
{
if (key == list[i])
return i;
}
return -1;
}
int main()
{
int intArray[] =
{
1, 2, 3, 4, 8, 15, 23, 31
};
vector<int> list(intArray, intArray+8);
cout << "linearSearch(list, 3,) is " << linearSearch(list, 3) << endl;
cout << "linearSearch(list, 10) is " << linearSearch(list, 10) << endl;
return 0;
}
This could work (it is based on the STL implementation):
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template <typename ForwardIter, typename Type>
int linearSearch(ForwardIter beg, ForwardIter end, Type key )
{
int i = 0;
for (;beg != end; ++beg)
{
if (key == *beg)
return i;
i++;
}
return -1;
}
int main()
{
vector< int > vec = { 1, 2, 3, 4, 5, 6, 7 };
cout << "linearSearch 1 is " << linearSearch(vec.begin(), vec.end(), 4) << endl;
cout << "linearSearch 2 is " << linearSearch(vec.begin()+2, vec.end(), 1) << endl;
return 0;
}
Note: it can also work for, std::list and std::deque. I think it will produce correct results even in a normal array.
template <typename T>
int linearSearch(const vector<T> &list, const T &key)
{
auto itr = std::find(list.begin(), list.end(), key);
if (itr != list.end())
return std::distance(list.begin(), itr);
else
return -1;
}
int main()
{
int intArray[] = {1, 2, 3, 4, 8, 15, 23, 31};
std::vector<int> vec(intArray, intArray + 8);
int i = linearSearch(vec, 15);
}
Note: C++11 is enabled
With as few changes as possible you could do this:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Using const std::vector<T> & to prevent making a copy of the container
template <typename T>
int linearSearch(const std::vector<T> &list, int key)
{
for (size_t i = 0; i < list.size(); i++)
{
if (key == list[i])
return i;
}
return -1;
}
int main()
{
std::vector<int> arr = { 1 ,2, 3, 4, 8, 15, 23, 31 } ;
cout << "linearSearch(intArray, 3) is " << linearSearch(arr, 3) << endl;
cout << "linearSearch(intArray, 10) is " << linearSearch(arr, 10) << endl;
return 0;
}
I would recommend not using using namespace std;.
template <typename T>
int linearSearch(T list, int key)
Changing the two first lines of your code as above, as well as replacing arraySize with list.size() should suffice for any kind of container supporting operator [] (including vectors), and indices as consecutive int.
Note that while your template tries to abstract the content of the array as the typename T, it implicitely assumes it is int in the type of key. A more generic implementation would be:
template <typename T>
int linearSearch(T list, typename T::value_type key)
Another issue in this solution is the passing mode of list. We can overcome this issue by converting it to a reference like so:
// includes ...
#include <type_traits>
using namespace std;
template <typename T>
int linearSearch(add_lvalue_reference<T> list, typename T::value_type key){
for (size_t i = 0; i < list.size(); i++) {
if (key == list[i])
return i;
}
return -1;
}
Please look at the following example that uses STL linear search algorithm. And see possible implementations of std::find and an example of usage it for a vector here: https://en.cppreference.com/w/cpp/algorithm/find
It would give you a good answer on your question.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> intsCollection {1, 2, 3, 4, 8, 15, 23, 31};
std::vector<int>::iterator val1 = std::find(intsCollection.begin(), intsCollection.end(), 3);
int pos1 = (val1 != intsCollection.end()) ? (val1 - intsCollection.begin()) : -1;
std::vector<int>::iterator val2 = std::find(intsCollection.begin(), intsCollection.end(), 10);
int pos2 = (val2 != intsCollection.end()) ? (val2 - intsCollection.begin()) : -1;
std::cout << "linearSearch(intsCollection, 3, 8) is " << pos1 << std::endl;
std::cout << "linearSearch(intsCollection, 10, 8) is " << pos2 << std::endl;
}