Maximum product C++ - c++

I am given a few array of both negative and positive numbers.
I should Find the maximum product obtained from multiplying 2 adjacent numbers in the array.
This is the code I wrote :
#include <vector>
#include <iostream>
using namespace std;
int adjacentElementsProduct(vector<int> inputArray)
{
for(int i = 0; i < inputArray.size(); i++) {
if((inputArray[i] * inputArray[i+1])>(inputArray[i+1] * inputArray[i+2])) {
std::cout << inputArray[i] * inputArray[i+1] << "\n";
} else if((inputArray[i+1] * inputArray[i+2])>(inputArray[i+2] * inputArray[i+3])) {
std::cout << inputArray[i+1] * inputArray[i+2] << "\n";
} else if((inputArray[i+2] * inputArray[i+3])>(inputArray[i+3] * inputArray[i+4])) {
std::cout << inputArray[i+2] * inputArray[i+3] << "\n";
} else if((inputArray[i+3] * inputArray[i+4])>(inputArray[i+4] * inputArray[i+5])) {
std::cout << inputArray[i+3] * inputArray[i+4] << "\n";
} else {
std::cout << "Unknow" << "\n";
} return 1;
}
}
int main() {
adjacentElementsProduct({5, 8});
adjacentElementsProduct({1,2,3});
adjacentElementsProduct({1,5,10,9});
adjacentElementsProduct({5,1,2,3,1,4});
adjacentElementsProduct({4,12,3,1,5});
adjacentElementsProduct({3,6,-2,-5,7,3});
adjacentElementsProduct({9, 5, 10, 2, 24, -1, -48});
adjacentElementsProduct({5, 6, -4, 2, 3, 2, -23});
adjacentElementsProduct({-23, 4, -5, 99, -27, 329, -2, 7, -921});
adjacentElementsProduct({1,0,1,0,1000});
adjacentElementsProduct({1,2,3,0});
return 1 ;
}
Output:
40
6
90
5
48
18
50
30
-20
Unknow
6
The code only compares the product of inputArray[i] * inputArray[i+1] and inputArray[i+1] * inputArray[i+2] But I want to find the maximum product among all the numbers in array.

You want to loop over the input vector and compute the products of adjacent elements.
Then, you want to find the maximum of those products. You don't need all that hardcoded [i+1], [i+2], [i+3], ... shenanigans, you already have something that can get all those numbers for you -- a for loop.
int adjacentElementsProduct(vector<int> inputArray)
{
// Set initial max product to a very small number so that
// it is always replaced by our first product
int maxProduct = std::numeric_limits<int>::min();
for(int i = 0;
i < inputArray.size() - 1; /* because we will be doing i + 1 inside the loop */
i++) {
// Calculate product of this and next element
int product = inputArray[i] * inputArray[i + 1];
if (product > maxProduct)
maxProduct = product; // This product is the greatest so far,
// so keep it and get rid of the old max.
}
return maxProduct;
}
To explain how this works, let's look at the execution of the function for an example input. Let's say we do adjacentElementsProduct({5,1,2,3,1,4});
maxProduct is set to some very large negative number (let's say -99999999)
inputArray.size() is 6. inputArray.size() - 1 is 5.
i = 0. Is 0 < 5? Yes. Go inside loop
product = inputArray[0] * inputArray[1] = 5
is 5 > maxProduct (-99999999)? Yes. Set maxProduct = 5
Increment i to 1.
i = 1. Is 1 < 5? Yes. Go inside loop
product = inputArray[1] * inputArray[2] = 2
is 2 > maxProduct (5)? No.
Increment i to 2.
i = 2. Is 2 < 5? Yes. Go inside loop
product = inputArray[2] * inputArray[3] = 6
is 6 > maxProduct (5)? Yes. Set maxProduct = 6
Increment i to 3.
i = 3. Is 3 < 5? Yes. Go inside loop
product = inputArray[3] * inputArray[4] = 3
is 3 > maxProduct (6)? No.
Increment i to 4.
i = 4. Is 4 < 5? Yes. Go inside loop
product = inputArray[4] * inputArray[5] = 4
is 4 > maxProduct (6)? No.
Increment i to 5.
i = 5. Is 5 < 5? No.
Return maxProduct, which is 6.

I think your function is overkill. You can do this with a running maxima:
const unsigned int length = inputArray.length();
int maximum = inputArray[0] * inputArray[1];
for (unsigned int i = 1U; i < (length - 1U); ++i)
{
const int product = inputArray[i] * inputArray[i + 1];
if (product > maximum) maximum = product;
}
This can be further optimized but that is an exercise for the OP.
Edit 1: Via Pointers
This may be more optimal, but only assembly language will tell (or profiling):
const unsigned int length = inputArray.length();
int const * p_first = &inputArray[0];
int const * p_second = &inputArray[1];
int maximum = (*p_first++) * (*p_second++);
for (unsigned int i = 1u; i < (length - 1); ++i)
{
int product = (*p_first++) * (*p_second++);
if (product > maximum) maximum = product;
}
In the above code fragment, the two array locations are maintained in pointers. The pointers can be maintained in registers. No need to calculate the offset within the loop each time. Incrementing pointers is simple and quick operation. Some processors have instructions that can dereference a pointer and increment in a single instruction. Some compilers may perform this optimization depending on the optimization setting.
Edit 2: Tracking Previous Value
Another optimization is to reduce the memory accesses by about half, by remembering the previous value in the array:
const unsigned int length = inputArray.length();
int previous = inputArray[0];
int next = inputArray[1];
int maximum = previous * next;
previous = next;
for (unsigned int i = 1u; i < length; ++i)
{
next = inputArray[i];
const int product = previous * next;
if (product > maximum) maximum = product;
previous = next;
}
In the above code fragment, the previous array value is remembered in a variable. This eliminates the need to access the array for the previous value; only one array access is required.
The compiler may perform this optimization at higher optimization levels. The proof is to compare the assembly language of the variables fragments.

There's an algorithm in <numeric> that does this for you:
int adjacentElementsProduct(std::vector<int> const & inputArray)
{
// [[assert: inputArray.size > 1 ]]
return std::inner_product(inputArray.begin(), inputArray.end() - 1,
inputArray.begin() + 1,
0,
[](int i, int j) { return std::max(i, j); },
std::multiplies{});
}
which is about as efficient, and readable as it gets.

For starters the function should not output any message. It is the caller of the function will decide whether to output a message or not.
The function should return an iterator or a pair of iterators that point to the two adjacent elements with the maximum product.
As for your function implementation then it has undefined behavior because it can access non-existent elements of the vector.
I can suggest the following function definition as it is shown in the demonstrative program below.
#include <iostream>
#include <utility>
#include <vector>
#include <iterator>
std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator>
adjacentElementsProduct( const std::vector<int> &v )
{
std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator>
p = { std::begin( v ), std::end( v ) };
if (not ( v.size() < 2 ))
{
p.second = std::next( std::begin( v ) );
long long int max_product = static_cast<long long int>( *p.first ) * *p.second;
for (auto prev = p.second, current = std::next( p.second );
current != std::end( v );
std::advance( prev, 1 ), std::advance( current, 1 ))
{
if (max_product < static_cast<long long int>( *prev ) * *current)
{
p = { prev, current };
}
}
}
return p;
}
int main()
{
std::vector<int> v = { 5, 8 };
auto p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 1,2,3 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 1,5,10,9 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 5,1,2,3,1,4 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 4,12,3,1,5 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 3,6,-2,-5,7,3 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 9, 5, 10, 2, 24, -1, -48 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 5, 6, -4, 2, 3, 2, -23 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { -23, 4, -5, 99, -27, 329, -2, 7, -921 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 1, 0, 1, 0, 1000 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
v = { 1,2,3,0 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
}
The program output is
40
6
90
6
48
21
48
30
-14
0
6
If you do not know yet iterators than the function can be defined the following way
#include <iostream>
#include <utility>
#include <vector>
std::pair<std::vector<int>::size_type, std::vector<int>::size_type>
adjacentElementsProduct( const std::vector<int> &v )
{
std::pair<std::vector<int>::size_type, std::vector<int>::size_type>
p = { 0, v.size() };
if (not ( v.size() < 2 ))
{
p.second = 1;
long long int max_product = static_cast<long long int>( p.first ) * p.second;
for (std::vector<int>::size_type i = 3; i < v.size(); i++ )
{
if (max_product < static_cast<long long int>( v[i - 1] ) * v[i] )
{
p = { i - 1, i };
}
}
}
return p;
}
int main()
{
std::vector<int> v = { 5, 8 };
auto p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 1,2,3 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 1,5,10,9 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 5,1,2,3,1,4 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 4,12,3,1,5 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 3,6,-2,-5,7,3 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 9, 5, 10, 2, 24, -1, -48 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 5, 6, -4, 2, 3, 2, -23 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { -23, 4, -5, 99, -27, 329, -2, 7, -921 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 1, 0, 1, 0, 1000 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
v = { 1,2,3,0 };
p = adjacentElementsProduct( v );
std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
}

Related

find_if is not returning the expected output

I am using find_if() to find the next higher value in a vector. It is returning the next index and not a higher value.
The input vector is:
vector<int> height = { 1,8,6,2,5,4,8,3,7 };
I am looking for the next highest value, starting at i=0, height[0] = 1. The code updates to set i=1, height[1] = 8. I expect to get i=7. I get i=2 instead.
for (size_t i = 0; i < height.size() - 1; i++)
{
auto res = std::find_if((height.begin() + i + 1), height.end(),
[&height, i](int x) {
return height[x] >= height[i];
});
auto higher_index = std::distance(height.begin(), res);
if (res != height.end() && higher_index < height.size())
{
// found the next highest height
// calculate new area and make i the same as highest height
area = min(height[i], height[higher_index]) * (higher_index - i);
maxA = max(maxA, area);
i = higher_index - 1;
}
}
Your lambda should look like this
[&height, i](int x) {
return x >= height[i];
}
find_if passes the value of each element of the given sequence to the predicate. Not the index of each element.
It seems you mean:
auto res = std::find_if((height.begin() + i + 1), height.end(),
[&height, i](int x) {
return x >= height[i];
});
Or, it will be simpler to write:
auto res = std::find_if((height.begin() + i + 1), height.end(),
[value = height[i]](int x) {
return x >= value;
});
Here is a demonstration program:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<int> height = { 1, 8, 6, 2, 5, 4, 8, 3, 7 };
for ( size_t i = 0; i < height.size(); i++ )
{
auto it = std::find_if( std::next( std::begin( height ), i + 1 ),
std::end( height ),
[value = height[i]]( const auto &x )
{
return not ( x < value );
} );
if ( it != std::end( height ) )
{
std::cout << "The next element is at position "
<< std::distance( std::begin( height ), it )
<< " with the value " << *it << '\n';
}
}
}
The program output is
The next element is at position 1 with the value 8
The next element is at position 6 with the value 8
The next element is at position 6 with the value 8
The next element is at position 4 with the value 5
The next element is at position 6 with the value 8
The next element is at position 6 with the value 8
The next element is at position 8 with the value 7

How do I find out if I can sum some elements in an array to K?

Let's say I have been given an arbitrary array, with only positive values, for instance A[5] = {2,3,4,2}. And I wish to check if, given an int x, let's say x=2, to see if A[2] can be the sum of the other elements in the array. In this case it can, hence we can print out TRUE because A[0] and A[3] add up to A[2].For bigger arrays with for instance 100 elements or more, what's a good way to find out if A[x] can be summed to by other elements in the same array?
This is somewhat brute force O(n*log(n)).
#include <iostream>
#include <algorithm>
#include <vector>
bool check_helper( std::vector< int > & data, std::vector< int >::iterator position, int value )
{
#if 0
std::cout << "check2helper( data, " << *position << ", " << value << ")\n";
#endif
if( *position == value )
return true;
else if( position == data.begin() )
return false;
else return check_helper( data, position - 1, value - *position ) || check_helper( data, position - 1, value );
}
bool check( const std::vector< int > & data, size_t element_index )
{
std::vector< int > data_copy( data );
int value = data_copy[element_index];
data_copy.erase( data_copy.begin() + element_index );
std::sort( data_copy.begin(), data_copy.end() );
std::vector< int >::iterator iter( std::lower_bound( data_copy.begin(), data_copy.end(), value ) );
#if 0
std::cout << " Checking " << value << " in ";
for( std::vector< int >::iterator i( data_copy.begin() ); i <= iter; ++i )
std::cout << *i << " , ";
std::cout << std::endl;
#endif
return check_helper( data_copy, iter, value );
}
int main( int argc, char ** argv )
{
std::vector< int > ints{ 1, 2, 4, 23, 97, 146, 11, 17, 301, 24, 12, 2 };
std::cout << "Testing ints = ";
for( auto v : ints )
std::cout << v << ", ";
std::cout << std::endl;
for( size_t i = 0; i < ints.size(); ++i )
{
std::cout << "ints[" << i << "] == " << ints[i] << " ---> " << ( check( ints, i ) ? "TRUE" : "FALSE" ) << std::endl;
}
return 0;
}
Results:
Testing ints = 1, 2, 4, 23, 97, 146, 11, 17, 301, 24, 12, 2,
ints[0] == 1 ---> FALSE
ints[1] == 2 ---> TRUE
ints[2] == 4 ---> TRUE
ints[3] == 23 ---> TRUE
ints[4] == 97 ---> FALSE
ints[5] == 146 ---> TRUE
ints[6] == 11 ---> FALSE
ints[7] == 17 ---> TRUE
ints[8] == 301 ---> TRUE
ints[9] == 24 ---> TRUE
ints[10] == 12 ---> TRUE
ints[11] == 2 ---> TRUE

Is there in OpenCV operation that is like op1:op2 in Matlab? [duplicate]

How can I do the equivalent of the following using C++/STL? I want to fill a std::vector with a range of values [min, max).
# Python
>>> x = range(0, 10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I suppose I could use std::generate_n and provide a functor to generate the sequence, but I was wondering if there is a more succinct way of doing this using STL?
In C++11, there's std::iota:
#include <vector>
#include <numeric> //std::iota
int main() {
std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0); //0 is the starting number
}
C++20 introduced a lazy version (just like Python) as part of the ranges library:
#include <iostream>
#include <ranges>
namespace views = std::views;
int main() {
for (int x : views::iota(0, 10)) {
std::cout << x << ' '; // 0 1 2 3 4 5 6 7 8 9
}
}
There is boost::irange:
std::vector<int> x;
boost::push_back(x, boost::irange(0, 10));
I ended up writing some utility functions to do this. You can use them as follows:
auto x = range(10); // [0, ..., 9]
auto y = range(2, 20); // [2, ..., 19]
auto z = range(10, 2, -2); // [10, 8, 6, 4]
The code:
#include <vector>
#include <stdexcept>
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop, IntType step)
{
if (step == IntType(0))
{
throw std::invalid_argument("step for range must be non-zero");
}
std::vector<IntType> result;
IntType i = start;
while ((step > 0) ? (i < stop) : (i > stop))
{
result.push_back(i);
i += step;
}
return result;
}
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop)
{
return range(start, stop, IntType(1));
}
template <typename IntType>
std::vector<IntType> range(IntType stop)
{
return range(IntType(0), stop, IntType(1));
}
I've been using this library for this exact purpose for years:
https://github.com/klmr/cpp11-range
Works very well and the proxies are optimized out.
for (auto i : range(1, 5))
cout << i << "\n";
for (auto u : range(0u))
if (u == 3u)
break;
else
cout << u << "\n";
for (auto c : range('a', 'd'))
cout << c << "\n";
for (auto i : range(100).step(-3))
if (i < 90)
break;
else
cout << i << "\n";
for (auto i : indices({"foo", "bar"}))
cout << i << '\n';
There is boost::irange, but it does not provide floating point, negative steps and can not directly initialize stl containers.
There is also numeric_range in my RO library
In RO, to initialize a vector:
vector<int> V=range(10);
Cut-n-paste example from doc page (scc - c++ snippet evaluator):
// [0,N) open-ended range. Only range from 1-arg range() is open-ended.
scc 'range(5)'
{0, 1, 2, 3, 4}
// [0,N] closed range
scc 'range(1,5)'
{1, 2, 3, 4, 5}
// floating point
scc 'range(1,5,0.5)'
{1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5}
// negative step
scc 'range(10,0,-1.5)'
{10, 8.5, 7, 5.5, 4, 2.5, 1}
// any arithmetic type
scc "range('a','z')"
a b c d e f g h i j k l m n o p q r s t u v w x y z
// no need for verbose iota. (vint - vector<int>)
scc 'vint V = range(5); V'
{0, 1, 2, 3, 4}
// is lazy
scc 'auto NR = range(1,999999999999999999l); *find(NR.begin(), NR.end(), 5)'
5
// Classic pipe. Alogorithms are from std::
scc 'vint{3,1,2,3} | sort | unique | reverse'
{3, 2, 1}
// Assign 42 to 2..5
scc 'vint V=range(0,9); range(V/2, V/5) = 42; V'
{0, 1, 42, 42, 42, 5, 6, 7, 8, 9}
// Find (brute force algorithm) maximum of `cos(x)` in interval: `8 < x < 9`:
scc 'range(8, 9, 0.01) * cos || max'
-0.1455
// Integrate sin(x) from 0 to pi
scc 'auto d=0.001; (range(0,pi,d) * sin || add) * d'
2
// Total length of strings in vector of strings
scc 'vstr V{"aaa", "bb", "cccc"}; V * size || add'
9
// Assign to c-string, then append `"XYZ"` and then remove `"bc"` substring :
scc 'char s[99]; range(s) = "abc"; (range(s) << "XYZ") - "bc"'
aXYZ
// Hide phone number:
scc "str S=\"John Q Public (650)1234567\"; S|isdigit='X'; S"
John Q Public (XXX)XXXXXXX
For those who can't use C++11 or libraries:
vector<int> x(10,0); // 0 is the starting number, 10 is the range size
transform(x.begin(),x.end(),++x.begin(),bind2nd(plus<int>(),1)); // 1 is the increment
A range() function similar to below will help:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
// define range function (only once)
template <typename T>
vector <T> range(T N1, T N2) {
vector<T> numbers(N2-N1);
iota(numbers.begin(), numbers.end(), N1);
return numbers;
}
vector <int> arr = range(0, 10);
vector <int> arr2 = range(5, 8);
for (auto n : arr) { cout << n << " "; } cout << endl;
// output: 0 1 2 3 4 5 6 7 8 9
for (auto n : arr2) { cout << n << " "; } cout << endl;
// output: 5 6 7
I don't know of a way to do it like in python but another alternative is obviously to for loop through it:
for (int i = range1; i < range2; ++i) {
x.push_back(i);
}
chris's answer is better though if you have c++11
If you can't use C++11, you can use std::partial_sum to generate numbers from 1 to 10. And if you need numbers from 0 to 9, you can then subtract 1 using transform:
std::vector<int> my_data( 10, 1 );
std::partial_sum( my_data.begin(), my_data.end(), my_data.begin() );
std::transform(my_data.begin(), my_data.end(), my_data.begin(), bind2nd(std::minus<int>(), 1));
Some time ago I wrote the following _range class, which behaves like Python range (put it to the "range.h"):
#pragma once
#include <vector>
#include <cassert>
template < typename T = size_t >
class _range
{
const T kFrom, kEnd, kStep;
public:
///////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////
//
// INPUT:
// from - Starting number of the sequence.
// end - Generate numbers up to, but not including this number.
// step - Difference between each number in the sequence.
//
// REMARKS:
// Parameters must be all positive or all negative
//
_range( const T from, const T end, const T step = 1 )
: kFrom( from ), kEnd( end ), kStep( step )
{
assert( kStep != 0 );
assert( ( kFrom >= 0 && kEnd > 0 && kStep > 0 ) || ( kFrom < 0 && kEnd < 0 && kStep < 0 ) );
}
// Default from==0, step==1
_range( const T end )
: kFrom( 0 ), kEnd( end ), kStep( 1 )
{
assert( kEnd > 0 );
}
public:
class _range_iter
{
T fVal;
const T kStep;
public:
_range_iter( const T v, const T step ) : fVal( v ), kStep( step ) {}
operator T () const { return fVal; }
operator const T & () { return fVal; }
const T operator * () const { return fVal; }
const _range_iter & operator ++ () { fVal += kStep; return * this; }
bool operator == ( const _range_iter & ri ) const
{
return ! operator != ( ri );
}
bool operator != ( const _range_iter & ri ) const
{
// This is a tricky part - when working with iterators
// it checks only once for != which must be a hit to stop;
// However, this does not work if increasing kStart by N times kSteps skips over kEnd
return fVal < 0 ? fVal > ri.fVal : fVal < ri.fVal;
}
};
const _range_iter begin() { return _range_iter( kFrom, kStep ); }
const _range_iter end() { return _range_iter( kEnd, kStep ); }
public:
// Conversion to any vector< T >
operator std::vector< T > ( void )
{
std::vector< T > retRange;
for( T i = kFrom; i < kEnd; i += kStep )
retRange.push_back( i );
return retRange; // use move semantics here
}
};
// A helper to use pure range meaning _range< size_t >
typedef _range<> range;
And some test code looks like the following one:
#include "range.h"
#include <iterator>
#include <fstream>
using namespace std;
void RangeTest( void )
{
ofstream ostr( "RangeTest.txt" );
if( ostr.is_open() == false )
return;
// 1:
ostr << "1st test:" << endl;
vector< float > v = _range< float >( 256 );
copy( v.begin(), v.end(), ostream_iterator< float >( ostr, ", " ) );
// 2:
ostr << endl << "2nd test:" << endl;
vector< size_t > v_size_t( range( 0, 100, 13 ) );
for( auto a : v_size_t )
ostr << a << ", ";
// 3:
ostr << endl << "3rd test:" << endl;
auto vvv = range( 123 ); // 0..122 inclusive, with step 1
for( auto a : vvv )
ostr << a << ", ";
// 4:
ostr << endl << "4th test:" << endl;
// Can be used in the nested loops as well
for( auto i : _range< float >( 0, 256, 16.5 ) )
{
for( auto j : _range< int >( -2, -16, -3 ) )
{
ostr << j << ", ";
}
ostr << endl << i << endl;
}
}
As an iterator:
#include <iostream>
class Range {
int x, y, z;
public:
Range(int x) {this->x = 0; this->y = x; this->z = 1;}
Range(int x, int y) {this->x = x; this->y = y; this->z = 1;}
Range(int x, int y, int z) {this->x = x; this->y = y; this->z = z;}
struct Iterator
{
Iterator (int val, int inc) : val{val}, inc{inc} {}
Iterator& operator++(){val+=inc; return *this;}
int operator*() const {return val;}
friend bool operator!=(const Iterator& a, const Iterator& b){return a.val < b.val;}
private:
int val, inc;
};
Iterator begin() {return Iterator(x,z);}
Iterator end() {return Iterator(y,z);}
};
int main() {
for (auto i: Range(10))
{
std::cout << i << ' '; //0 1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(1,10))
{
std::cout << i << ' '; //1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(-10,10,3))
{
std::cout << i << ' '; //-10 -7 -4 -1 2 5 8
}
return 0;
}

converting vector<unsigned long> to char buffer[]

How to convert vector<unsigned long> v; to char buffer[sizeof(unsigned long)*v.size()]; and vice-versa.
i tried with
std::copy(b.begin(), b.end(), buffer);
and v.insert() but result is ambiguous. Could any one suggest how to do this.
If you just need to pass the data to some library function which expects a char*
assert(v.size());
char *p = (char*) &v[0];
otherwise here is some sample code copying data back and forth from std::vector and char*, although I'd suggest sticking to one interface unless you have a reason for doing this.
#include <iostream>
#include <vector>
#include <memory>
#include <assert.h>
int main()
{
size_t count = 20;
std::vector<unsigned int> v;
v.resize(count);
assert(v.size());
// make a vector with the numbers 1 through count
for (size_t index = 0; index < count; ++index)
v[index] = index + 1;
// make a buffer of char[] (using unique_ptr to handle cleanup)
std::unique_ptr<char> buffer(new char[v.size() * sizeof(v[0])]);
// copy from v into a buffer of char[]
memcpy(buffer.get(), &v[0], v.size() * sizeof(v[0]));
// next we get rid of v, and copy the elements back in from the char buffer
v.clear();
// now suppose we have a char array of count unsigned ints (which we do)
// (the count better be right)
// just say it's an unsigned int* and you get pointer arithmetic for unsigned int
unsigned int * pInt = reinterpret_cast<unsigned int*>(buffer.get());
for (size_t index = 0; index < count; ++index)
v.push_back(*pInt++);
// print out as proof
for (auto &x : v)
std::cout << x << " ";
return 0;
}
For example you can try the following approach
#include <iostream>
#include <vector>
#include <cstring>
#include <numeric>
int main()
{
std::vector<unsigned long> v = { 1, 2, 3 };
char *p = new char[sizeof( unsigned long ) * v.size()];
std::accumulate( v.begin(), v.end(), p,
[]( char *p, unsigned long x)
{
return memcpy( p, &x, sizeof( x ) ), p + sizeof( x );
} );
std::vector<unsigned long> v2( v.size() );
char *q = p;
for ( auto &x : v2 )
{
memcpy( &x, q, sizeof( x ) );
q += sizeof( x );
}
for ( auto x : v2 ) std::cout << x << ' ';
std::cout << std::endl;
delete []p;
return 0;
}
The output is
1 2 3
The return statement in the lambda expression can be written also like
return ( char * )memcpy( p, &x, sizeof( x ) ) + sizeof( x );
Or indeed you could copy the whole vector in the character buffer the following way
std::memcpy( p, v.data(), v.size() * sizeof( unsigned long ) );
For example
#include <iostream>
#include <cstring>
#include <vector>
int main()
{
std::vector<unsigned long> v = { 1, 2, 3 };
char *p = new char[sizeof( unsigned long ) * v.size()];
memcpy( p, v.data(), v.size() * sizeof( unsigned long ) );
std::vector<unsigned long> v2( v.size() );
char *q = p;
for ( auto &x : v2 )
{
memcpy( &x, q, sizeof( x ) );
q += sizeof( x );
}
for ( auto x : v2 ) std::cout << x << ' ';
std::cout << std::endl;
delete []p;
return 0;
}
And instead of this loop
char *q = p;
for ( auto &x : v2 )
{
memcpy( &x, q, sizeof( x ) );
q += sizeof( x );
}
you also could use memcpy. For example
memcpy( v2.data(), p, v2.size() * sizeof( unsigned long ) );

Is there a compact equivalent to Python range() in C++/STL

How can I do the equivalent of the following using C++/STL? I want to fill a std::vector with a range of values [min, max).
# Python
>>> x = range(0, 10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I suppose I could use std::generate_n and provide a functor to generate the sequence, but I was wondering if there is a more succinct way of doing this using STL?
In C++11, there's std::iota:
#include <vector>
#include <numeric> //std::iota
int main() {
std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0); //0 is the starting number
}
C++20 introduced a lazy version (just like Python) as part of the ranges library:
#include <iostream>
#include <ranges>
namespace views = std::views;
int main() {
for (int x : views::iota(0, 10)) {
std::cout << x << ' '; // 0 1 2 3 4 5 6 7 8 9
}
}
There is boost::irange:
std::vector<int> x;
boost::push_back(x, boost::irange(0, 10));
I ended up writing some utility functions to do this. You can use them as follows:
auto x = range(10); // [0, ..., 9]
auto y = range(2, 20); // [2, ..., 19]
auto z = range(10, 2, -2); // [10, 8, 6, 4]
The code:
#include <vector>
#include <stdexcept>
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop, IntType step)
{
if (step == IntType(0))
{
throw std::invalid_argument("step for range must be non-zero");
}
std::vector<IntType> result;
IntType i = start;
while ((step > 0) ? (i < stop) : (i > stop))
{
result.push_back(i);
i += step;
}
return result;
}
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop)
{
return range(start, stop, IntType(1));
}
template <typename IntType>
std::vector<IntType> range(IntType stop)
{
return range(IntType(0), stop, IntType(1));
}
I've been using this library for this exact purpose for years:
https://github.com/klmr/cpp11-range
Works very well and the proxies are optimized out.
for (auto i : range(1, 5))
cout << i << "\n";
for (auto u : range(0u))
if (u == 3u)
break;
else
cout << u << "\n";
for (auto c : range('a', 'd'))
cout << c << "\n";
for (auto i : range(100).step(-3))
if (i < 90)
break;
else
cout << i << "\n";
for (auto i : indices({"foo", "bar"}))
cout << i << '\n';
There is boost::irange, but it does not provide floating point, negative steps and can not directly initialize stl containers.
There is also numeric_range in my RO library
In RO, to initialize a vector:
vector<int> V=range(10);
Cut-n-paste example from doc page (scc - c++ snippet evaluator):
// [0,N) open-ended range. Only range from 1-arg range() is open-ended.
scc 'range(5)'
{0, 1, 2, 3, 4}
// [0,N] closed range
scc 'range(1,5)'
{1, 2, 3, 4, 5}
// floating point
scc 'range(1,5,0.5)'
{1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5}
// negative step
scc 'range(10,0,-1.5)'
{10, 8.5, 7, 5.5, 4, 2.5, 1}
// any arithmetic type
scc "range('a','z')"
a b c d e f g h i j k l m n o p q r s t u v w x y z
// no need for verbose iota. (vint - vector<int>)
scc 'vint V = range(5); V'
{0, 1, 2, 3, 4}
// is lazy
scc 'auto NR = range(1,999999999999999999l); *find(NR.begin(), NR.end(), 5)'
5
// Classic pipe. Alogorithms are from std::
scc 'vint{3,1,2,3} | sort | unique | reverse'
{3, 2, 1}
// Assign 42 to 2..5
scc 'vint V=range(0,9); range(V/2, V/5) = 42; V'
{0, 1, 42, 42, 42, 5, 6, 7, 8, 9}
// Find (brute force algorithm) maximum of `cos(x)` in interval: `8 < x < 9`:
scc 'range(8, 9, 0.01) * cos || max'
-0.1455
// Integrate sin(x) from 0 to pi
scc 'auto d=0.001; (range(0,pi,d) * sin || add) * d'
2
// Total length of strings in vector of strings
scc 'vstr V{"aaa", "bb", "cccc"}; V * size || add'
9
// Assign to c-string, then append `"XYZ"` and then remove `"bc"` substring :
scc 'char s[99]; range(s) = "abc"; (range(s) << "XYZ") - "bc"'
aXYZ
// Hide phone number:
scc "str S=\"John Q Public (650)1234567\"; S|isdigit='X'; S"
John Q Public (XXX)XXXXXXX
For those who can't use C++11 or libraries:
vector<int> x(10,0); // 0 is the starting number, 10 is the range size
transform(x.begin(),x.end(),++x.begin(),bind2nd(plus<int>(),1)); // 1 is the increment
A range() function similar to below will help:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
// define range function (only once)
template <typename T>
vector <T> range(T N1, T N2) {
vector<T> numbers(N2-N1);
iota(numbers.begin(), numbers.end(), N1);
return numbers;
}
vector <int> arr = range(0, 10);
vector <int> arr2 = range(5, 8);
for (auto n : arr) { cout << n << " "; } cout << endl;
// output: 0 1 2 3 4 5 6 7 8 9
for (auto n : arr2) { cout << n << " "; } cout << endl;
// output: 5 6 7
I don't know of a way to do it like in python but another alternative is obviously to for loop through it:
for (int i = range1; i < range2; ++i) {
x.push_back(i);
}
chris's answer is better though if you have c++11
If you can't use C++11, you can use std::partial_sum to generate numbers from 1 to 10. And if you need numbers from 0 to 9, you can then subtract 1 using transform:
std::vector<int> my_data( 10, 1 );
std::partial_sum( my_data.begin(), my_data.end(), my_data.begin() );
std::transform(my_data.begin(), my_data.end(), my_data.begin(), bind2nd(std::minus<int>(), 1));
Some time ago I wrote the following _range class, which behaves like Python range (put it to the "range.h"):
#pragma once
#include <vector>
#include <cassert>
template < typename T = size_t >
class _range
{
const T kFrom, kEnd, kStep;
public:
///////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////
//
// INPUT:
// from - Starting number of the sequence.
// end - Generate numbers up to, but not including this number.
// step - Difference between each number in the sequence.
//
// REMARKS:
// Parameters must be all positive or all negative
//
_range( const T from, const T end, const T step = 1 )
: kFrom( from ), kEnd( end ), kStep( step )
{
assert( kStep != 0 );
assert( ( kFrom >= 0 && kEnd > 0 && kStep > 0 ) || ( kFrom < 0 && kEnd < 0 && kStep < 0 ) );
}
// Default from==0, step==1
_range( const T end )
: kFrom( 0 ), kEnd( end ), kStep( 1 )
{
assert( kEnd > 0 );
}
public:
class _range_iter
{
T fVal;
const T kStep;
public:
_range_iter( const T v, const T step ) : fVal( v ), kStep( step ) {}
operator T () const { return fVal; }
operator const T & () { return fVal; }
const T operator * () const { return fVal; }
const _range_iter & operator ++ () { fVal += kStep; return * this; }
bool operator == ( const _range_iter & ri ) const
{
return ! operator != ( ri );
}
bool operator != ( const _range_iter & ri ) const
{
// This is a tricky part - when working with iterators
// it checks only once for != which must be a hit to stop;
// However, this does not work if increasing kStart by N times kSteps skips over kEnd
return fVal < 0 ? fVal > ri.fVal : fVal < ri.fVal;
}
};
const _range_iter begin() { return _range_iter( kFrom, kStep ); }
const _range_iter end() { return _range_iter( kEnd, kStep ); }
public:
// Conversion to any vector< T >
operator std::vector< T > ( void )
{
std::vector< T > retRange;
for( T i = kFrom; i < kEnd; i += kStep )
retRange.push_back( i );
return retRange; // use move semantics here
}
};
// A helper to use pure range meaning _range< size_t >
typedef _range<> range;
And some test code looks like the following one:
#include "range.h"
#include <iterator>
#include <fstream>
using namespace std;
void RangeTest( void )
{
ofstream ostr( "RangeTest.txt" );
if( ostr.is_open() == false )
return;
// 1:
ostr << "1st test:" << endl;
vector< float > v = _range< float >( 256 );
copy( v.begin(), v.end(), ostream_iterator< float >( ostr, ", " ) );
// 2:
ostr << endl << "2nd test:" << endl;
vector< size_t > v_size_t( range( 0, 100, 13 ) );
for( auto a : v_size_t )
ostr << a << ", ";
// 3:
ostr << endl << "3rd test:" << endl;
auto vvv = range( 123 ); // 0..122 inclusive, with step 1
for( auto a : vvv )
ostr << a << ", ";
// 4:
ostr << endl << "4th test:" << endl;
// Can be used in the nested loops as well
for( auto i : _range< float >( 0, 256, 16.5 ) )
{
for( auto j : _range< int >( -2, -16, -3 ) )
{
ostr << j << ", ";
}
ostr << endl << i << endl;
}
}
As an iterator:
#include <iostream>
class Range {
int x, y, z;
public:
Range(int x) {this->x = 0; this->y = x; this->z = 1;}
Range(int x, int y) {this->x = x; this->y = y; this->z = 1;}
Range(int x, int y, int z) {this->x = x; this->y = y; this->z = z;}
struct Iterator
{
Iterator (int val, int inc) : val{val}, inc{inc} {}
Iterator& operator++(){val+=inc; return *this;}
int operator*() const {return val;}
friend bool operator!=(const Iterator& a, const Iterator& b){return a.val < b.val;}
private:
int val, inc;
};
Iterator begin() {return Iterator(x,z);}
Iterator end() {return Iterator(y,z);}
};
int main() {
for (auto i: Range(10))
{
std::cout << i << ' '; //0 1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(1,10))
{
std::cout << i << ' '; //1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(-10,10,3))
{
std::cout << i << ' '; //-10 -7 -4 -1 2 5 8
}
return 0;
}