i am trying to wirte a function to find a the max value in a vector recursively. To do that i want to test in the findMax function if it can return the last value in the list right. But at the end, when the list has just one element, it returns me the adress of variable and not the value. Why is it?
/// finding max value in a list recursively
template <typename T>
int findMax(std::vector<T> arrayVector)
{
if(arrayVector.size()==1)
{
return arrayVector[0];
}
int op1= arrayVector[0];
std::vector<T> newVector (arrayVector.cbegin() + 1, arrayVector.cend());
disPlay(newVector);
int op2= findMax(newVector);
}
/// print vector
template <typename T>
void disPlay(std::vector<T> vectorArray)
{
for (int i=0; i< vectorArray.size(); i++)
{
std::cout << vectorArray[i] << "\t";
}
std::cout << "\n";
}
main()
{
std::vector<int> arrayVector = {6, 8, 19, 20, 23, 41, 49, 53, 56};
std::cout << findMax(arrayVector) << endl;
return 0;
}
I ran you program and it triggered several warnings, the one that probably justifies the unwanted behaviour is the lack of return value in int findMax(std::vector<T> arrayVector).
template <typename T>
int findMax(std::vector<T> arrayVector)
{
if(arrayVector.size()==1)
{
return arrayVector[0];
}
int op1= arrayVector[0];
std::vector<T> newVector (arrayVector.cbegin() + 1, arrayVector.cend());
disPlay(newVector);
int op2= findMax(newVector);
return op2; //<-- added return
}
I corrected the problems in https://wandbox.org/permlink/Kts9qs7MooG4dEQL
It seems ok now.
Use compiler warnings, it can save you a lot of time an headaches.
Now, this solves the issues with your code, but I would advise the use of std::max_element to get max values in a C++ data structure.
Here is a test sample of a function to get the max value recursively in an unordered vector witch loses the last element in each iteration:
template <typename T>
void findMax(std::vector<T>& arrayVector)
{
if(arrayVector.size() == 0) //stop condition
return;
int max = *std::max_element(arrayVector.begin(), arrayVector.end());
std::cout << "Max value: "<< max << std::endl;
arrayVector.erase(arrayVector.end() - 1); //last element being deleted in every recursion
findMax(arrayVector);
}
Check it in https://wandbox.org/permlink/0oyGnXoQdwhl3kUJ
template<typename T>
T findMax(const std::vector<T> vec, size_t index=0){
if(index==vec.size()-1) return vec[vec.size()-1];
return ( vec[index] > findMax(vec,index+1))?vec[index]:findMax(vec,index+1) ;
}
Your code is convoluted:
it's not actually computing the max of the vector
not all paths return a value
you are copying std::vector objects around with no real purpose
STL has the advantage of abstracting iterators, which make your attempt rather trivial:
template<typename T, typename C>
T findMax(C begin, C end)
{
if (begin+1 == end)
return *begin;
else
return std::max(*begin, findMax<T,C>(begin+1, end));
}
Mind: the code is not checking for correctness of input.
Can't be a recursive solution without ol' std::accumulate:
#include <iostream>
#include <vector>
#include <numeric>
#include <limits>
int main(int argc, char *argv[])
{
std::vector<int> arrayVector = {6, 8, 19, 20, 23, 41, 49, 53, 56};
const int max = std::accumulate(
arrayVector.cbegin(),
arrayVector.cend(),
std::numeric_limits<int>::min(),
[](int x, int y) { return x > y ? x : y; }
);
std::cout << max << '\n';
return 0;
}
Earlier solution by Rietty to similar question and solutions in this thread follow vector from 0 to end. Next follows vector from end to 0 to simplify recursive function:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
template<typename T>
T findMax (vector<T> values, size_t end) {
if (0 == end) return values[0];
return max (findMax (values, end - 1), values[end]);
}
template<typename T>
T inline findMax (vector<T> values) {
return findMax (values, values.size() - 1);
}
int main () {
vector<int> values = { 6, 8, 19, 20, 23, 41, 49, 53, 56 };
cout << findMax (values) << endl;
return 0;
}
Simple code:
int find_max(int a[], int length){
if (length == 0) return a[length];
return std::max(a[length-1], find_max(a, length-1));
}
#include "iostream"
#include "vector"
using namespace std;
int maxre(vector<int> array);
int main()
{
vector<int> data = {210, 800, 2,150 ,19,600};
cout << maxre(data);
return 0;
}
int maxre(vector<int> array)
{
static int index = -1;
if (array.size() == index + 1)
{
return 0;
}
else
{
index++;
int current = array[index];
int back = maxre(array);
return current > back ? current : back;
}
return 0;
}
Related
I keep getting a compilation error if I use an array passed as parameter to a method on std::begin or std::end such as this:
#include <iostream>
#include <algorithm>
using namespace std;
class Test
{
public:
static bool exists(int ints[], int size, int k)
{
if (std::find(std::begin(ints), std::end(ints), k) != std::end(ints)) {
return true;
}
return false;
}
};
I tried casting it to &int[0] but it will still not compile.
The parameter ints is not an array, so you aren't passing an array into std::begin / std::end in the example. A function parameter is never an array in C++. When you declare a function array to be an array such as in your example, that parameter is adjusted to be a pointer to the element of such array. In your case, the type of the parameter ints has been adjusted to be a pointer to int i.e. int*, and you cannot pass a pointer into std::begin / std::end, as the error message surely explains.
You have passed the size as another parameter, so you could instead use:
std::find(ints, ints + size, k)
A more modern API design is to wrap the pointer and the size into a single class. The C++20 standard library comes with such class template: std::span. It also has convenient range algorithms that are quite convenient:
static bool exists(std::span<const int> ints, int k)
{
if (std::ranges::find(ints, k) != std::end(ints)) {
Even moreso, C++20 standard library has a function template that makes your function unnecessary:
std::ranges::contains(some_array, k);
Use std::span.
try this:
#include <algorithm>
#include <iostream>
#include <span>
bool exists(std::span<int> span, int needle) {
return std::find(span.begin(), span.end(), needle) != span.end();
}
int main() {
int arr[] = {0, 1, 2, 3, 4};
bool ok = exists(arr, 3);
if (ok) {
std::cout << "ok" << '\n';
} else {
std::cout << "not ok" << '\n';
}
return 0;
}
Here is a working example.
#include <iostream>
#include <vector>
bool exists(int x[], const int size, const int k)
{
std::vector<int> v(x, x + size);
if (std::find( v.begin(), v.end(), k) != v.end()) {
return true;
}
return false;
}
int main()
{
int const sz = 10;
int arrayi[sz] = { 1, 2, 3,4 ,5 ,6 ,7 , 8, 9, 0 };
if (exists(arrayi, sz, 4))
std::cout << "exist" << std::endl;
else
std::cout << "it does not" << std::endl;
}
I'm trying to return indexes of lowest values in an array, and i'm unable to find a good solution anywhere.
int indexofSmallestElement(double array[], int size)
{
int index = 0;
for(int i = 1; i < size; i++)
{
if(array[i] < array[index])
index = i;
}
return index;
}
This is the probably the simplest way of finding index of one value, but what if I have multiple lowest values in an array?
EDIT: Oh, I just realized from the comment that there is the possibility of duplicate values, so if the question is actually that, you could do this, it also returning a std::vector:
std::vector<int> indexesOfSmallestElements(double array[], int size)
{
std::vector<int> indexes = { 0 };
for (int i = 1; i < size; i++)
{
double current_smallest = array[indexes.front()];
if (array[i] < current_smallest) {
indexes.clear();
indexes.emplace_back(i);
}
else if (array[i] == current_smallest) {
indexes.emplace_back(i);
}
}
return indexes;
}
ORIGINAL:
"Lowest" is always only one, if you want "lower than a value", just return a std::vector.
std::vector<int> indexesOfSmallElements(double array[], int size, double value)
{
std::vector<int> indexes;
for (int i = 0; i < size; i++)
{
if (array[i] < value) {
indexes.emplace_back(i);
}
}
return indexes;
}
Array indices are a fairly inflexible concept, in C++ you can gain plenty of generality with iterators - there's a whole lot of C++ algorithms that take iterators directly, and essentially next to nothing in the standard library uses naked indices.
C++20 & onwards
We can create a minimums range view (lazy range combinator) that takes a range, and returns a range that only contains the minimums from the original range. The range isn't a new vector with filtered elements: it is a view onto the original range (e.g. onto the original vector of doubles).
#include <algorithm>
#include <ranges>
#include <vector>
template <typename Range>
auto minimums(Range && range) {
using namespace std::ranges;
auto first_min = min_element(range);
auto const is_min = [=](auto const &el){ return el == *first_min; };
return subrange(first_min, std::end(range)) | views::filter(is_min);
}
You definitely do not need to recover the indices of the array - iterators are a generic concept and apply quite widely. But just to show a solution equivalent to the one for C++17 & prior below, let's write some adapters that'll help with index recovery:
template <typename Range>
auto addressof(Range && range) {
using namespace std::ranges;
return views::transform(range, [](auto &el){ return ⪙ });
}
template <typename Range, typename It>
auto array_indices(Range && range, It && reference) {
using namespace std::ranges;
auto to_index = [ref_addr = &*reference](auto *el){ return ref_addr - el; };
return range | addressof | views::transform(to_index);
}
And now we can test it:
#include <cassert>
#include <iostream>
int main()
{
const double array[] = {8, 3, -1, -1, 9, -1, 5};
auto min_range = minimums(array);
{ // test
auto min = std::ranges::min_element(array);
// have we got the correct number of minimums?
auto min_size = std::distance(std::begin(min_range), std::end(min_range));
assert(min_size == std::count(std::begin(array), std::end(array), *min));
// are all of the minimums indeed minimums?
assert(std::ranges::all_of(min_range,
[=](auto &el){ return el == *min; }));
// are all of the minimums references to the array
assert(std::ranges::all_of(min_range,
[&](auto &el){ return &el >= std::begin(array) && &el < std::end(array); }));
}
for (auto &min : min_range)
std::cout << std::distance(std::begin(array), &min) << ' ';
std::cout << '\n';
}
Output:
2 3 5
C++17 through C++11
Thus, let's have a minimumLocations function that takes two forward iterators that define a range, and return a vector of iterators to all the minimums that were found:
#include <iterator>
#include <type_traits>
#include <vector>
template <typename I1, typename I2>
std::vector<I1> minimumLocations(I1 start, I2 end)
{
if (start == end) return {};
std::vector<I1> locations = {start};
std::decay<decltype(*start)>::type min = *start;
std::advance(start, 1);
for (; start != end; std::advance(start, 1)) {
auto const &value = *start;
if (value < min) {
// new minimum
locations.clear();
locations.push_back(start);
min = *start;
}
else if (value == min)
locations.push_back(start);
}
return locations;
}
For convenience's sake, we can also have an adapter function that takes a range instead of a pair of iterators. In C++, a "range" is anything that has a beginning and an end:
template <typename R>
auto minimumLocations(R &range) {
return minimumLocations(std::begin(range), std::end(range));
}
Both of the functions will work on any container that provides forward iterators - not only on arrays, but also vectors, lists, forward lists, etc. A specialized version could also be provided for pre-sorted containers.
And now a test and a demo:
#include <algorithm>
#include <cassert>
#include <iostream>
int main()
{
const double array[] = {8, 3, -1, -1, 9, -1, 5};
auto min_indices = minimumLocations(array);
{ // test
auto min = std::min_element(std::begin(array), std::end(array));
// have we got the correct numer of locations?
assert(min_indices.size() == std::count(std::begin(array), std::end(array), *min));
// are all of the locations indeed minimums?
assert(std::all_of(std::begin(min_indices), std::end(min_indices),
[=](auto it){ return *it == *min; }));
}
for (auto i : min_indices)
std::cout << std::distance(array, i) << ' ';
std::cout << '\n';
}
Output:
2 3 5
My goal is to create an immutable function (functional programming) using "accumulate" in C++. I created a dummy list that generates 1's based on the position I send, which will be 6. So the list at the start contains {1,1,1,1,1,1}. I tried using accumulate to somehow use the information on this list and make the fibonacci sequence into a new list. The result has to be {1,1,2,3,5,8}
Here is what I have.
list<int> immutableFibonacci(int position)
{
const size_t fixedListSize(position);
list<int> newList(position, int(1));
list<int> copyList;
list<int>::iterator it = newList.begin();
if (position <=2)
{
return newList; //returns {1,1} or {1}
}
while (position>0)
{
advance(it, 1);
sum = accumulate(newList.begin(),it, 0);
copyList.push_back(sum);
position--;
}
return copyList;
}
What I have so far will return copyList as {1,2,3,4,5,6}. Can someone please push me in the right direction on what to do? I tried researching quite a bit.
this method creates a 'container-like' object which exposes iterators via begin() and end()
#include <iterator>
#include <iostream>
struct fib_iterator : std::iterator<std::forward_iterator_tag, long long>
{
fib_iterator(std::size_t torun = 0) : to_run(torun) {}
value_type operator*() const {
return value();
}
fib_iterator& operator++()
{
--to_run;
switch(preamble)
{
case 2:
--preamble;
return *this;
case 1:
--preamble;
return *this;
}
auto next = value();
x = y;
y = next;
return *this;
}
value_type value() const
{
switch(preamble)
{
case 2:
return 0;
case 1:
return 1;
}
return x + y;
}
bool operator==(const fib_iterator& r) const {
return to_run == r.to_run;
}
bool operator!=(const fib_iterator& r) const {
return to_run != r.to_run;
}
long long x = 0;
long long y = 1;
std::size_t preamble = 2;
std::size_t to_run;
};
struct fibonacci_sequence
{
fibonacci_sequence(std::size_t length) : length_(length) {}
fib_iterator begin() const { return { length_ }; }
fib_iterator end() const { return { }; }
std::size_t length_;
};
int main()
{
for (auto i : fibonacci_sequence(50))
std::cout << i << ", ";
std::cout << '\n';
}
sample output:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987,
1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393,
196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887,
9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141,
267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073,
4807526976, 7778742049,
How about this:
#include <iostream>
#include <vector>
#include <numeric>
#include <string>
#include <functional>
int main()
{
std::vector<int> v{1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
std::vector<int> s = std::accumulate(v.begin(), v.end(),std::vector<int>{},
[](const std::vector<int>& a, int b)
{
std::vector<int> d = a;
if(a.size()<2)
{
d.push_back(1);
}
else
{
auto start = d.rbegin();
auto first = *start;
start++;
auto second = *start;
d.push_back(first+second);
}
return d;
});
std::cout << "Fibo: " <<'\n';
for( auto c : s )
{
std::cout << c << "-";
}
std::cout << '\n';
}
But I also think it is a bit too much overhead, for something that simple.
EDIT: Remember to compile that with: g++ --std=c++14 fibo.cpp -o fibo.
EDIT: If you don't want to use the lambda function look here: How can I modify this Fibonacci code in C++ to use a function instead of lambda?
In Matlab, it is possible to do the following:
% init
a = 1:10;
b = 18:23;
% wrapping assignment
a([8:end 1:3]) = b;
Is something like this possible with Eigen? I'm hoping to make a member function for a circular buffer class that returns some reference to an Eigen type, perhaps something like:
VectorXd b(5);
b << 1,2,3,4,5 ;
CircularBuf a( 6 /*capacity*/ );
a.push(1);a.push(2);a.push(3);
// 3 elements in buf
a.pop();a.pop();
// 1 element in buf
// next line probably wraps around internal buffer, depending on impl
a.pushRef( b.size() /*number of elements in ref*/ ) = b;
I am not sure if this is what you are looking for...Following an answer I got from Jerry Coffin, I came up with this:
#include <iostream>
#include <vector>
#include <iterator>
template <class T>
class CircularVector {
typedef std::vector<T> DVector;
public:
CircularVector(const DVector& v) : v(v){}
T at(int i){return v.at(i);}
int size(){return v.size();}
class iterator :
public std::iterator < std::random_access_iterator_tag, T > {
CircularVector *vec;
int index;
public:
iterator(CircularVector &d, int index) : vec(&d), index(index) {}
iterator &operator++() { nextIndex(); return *this; }
iterator operator++(int) {
iterator tmp(*vec, index); nextIndex(); return tmp;
}
iterator operator+(int off) {
return iterator(*vec, (index + off)%vec->size());
}
iterator operator-(int off) {
return iterator(*vec, (index - off + vec->size())%vec->size());
}
T& operator*() { return (*vec).v[index]; }
bool operator!=(iterator const &other) { return index != other.index; }
//bool operator<(iterator const &other) { return index < other.index; }
private:
void nextIndex(){
++index;
if (index==vec->size()){index=0;}
}
};
iterator begin() { return iterator(*this, 0); }
//iterator end() { return iterator(*this, size()); }
private:
DVector v;
};
Your first example then can be written as:
int main() {
std::vector<int> a;
std::vector<int> b;
for(int i=1;i<11;i++){a.push_back(i);}
for(int i=18;i<24;i++){b.push_back(i);}
CircularVector<int> ca(a);
std::copy(b.begin(),b.end(),ca.begin()+7); // copy elements starting
// at index 8
for (int i=0;i<ca.size();i++){std::cout << ca.at(i) << std::endl;}
}
Actually, I was just curious to try it and I believe there are nicer ways to implement it. It is not the most efficient way to check if the index has to be wrapped each time it is increased. Obviously < and end() are not quite meaningful for a circular buffer and I decided not to implement them (e.g. for(it=begin();it<end();it++) would be an infinite loop. However, those are not needed to use it as input/output iterator.
I have another solution as described in my answer to this question. The code posted in the answer defines a custom expression for the circular shift, so you can benefit from Eigen's optimisations.
Given the circ_shift.h from the mentioned answer, you can do the following to achieve your goal: I hope this helps...
// main.cpp
#include "stdafx.h"
#include "Eigen/Core"
#include <iostream>
#include "circ_shift.h" // posted in the answer to the other quesiton.
using namespace Eigen;
int main()
{
VectorXi a(10), b(6);
a << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
b << 18, 19, 20, 21, 22, 23;
std::cout << "a = " << a.transpose() << std::endl << "b = " << b.transpose() << std::endl;
circShift(a, 3, 0).block(0, 0, b.size(), 1) = b;
std::cout << "now: a = " << a.transpose() << std::endl; // prints 21, 22, 23, 4, 5, 6, 7, 18, 19, 20
return 0;
}
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;
}