The conditional operator is not allowing the program to terminate - c++

I just learnt about conditional operators and was doing an introductory exercise stating:
Write a program to use a conditional operator to find the elements in
a vector<int> that have odd value and double the value of each such
element.
Here is the code that I wrote:
int main()
{
vector<int> nums = { 1,2,3,4,5,6,7,8,9 };
int i;
auto beg = nums.begin();
while (*beg > 0) // This will always evaluate to true.
{
((*beg) % 2 == 0 && (beg < nums.end()) ? i = 0 : *beg = 2 * (*(beg++)));
/*If the number is even the program will just assign 0 to i*/
}
}
The program terminates AND gives you the correct output if you change the last line to:
((*beg)%2 == 0 && (beg < nums.end()) ? i = 0 : *beg = 2*(*(beg)));
++beg;
Why is this happening?

It stuck because, if the condition ((*beg)%2 == 0 && (beg < nums.end()) is true, the iterator will not increment for checking further. You have only setting i=0. You should increment the iterator as well.
You can use comma operator for this:
while (beg != nums.end() && *beg > 0)
{
(*beg) % 2 == 0 ? (beg++, i): (*beg = 2 * (*beg) , beg++, ++i );
}
Also note that the count i should be initialized before-hand, not in the while loop.
The complete working code as per the requirement would be:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> nums = { 1,2,3,4,5,6,7,8,9 };
int i{0};
auto beg = nums.begin();
while (beg != nums.end() && *beg > 0)
{
(*beg) % 2 == 0 ? (beg++, i): (*beg = 2 * (*beg) , beg++, ++i );
}
for (const int ele : nums)
std::cout << ele << " ";
std::cout << "\ncount: " << i << "\n";
}
Output:
2 2 6 4 10 6 14 8 18
count: 5
That being said, IMO using comma operator along with conditional operator like the above(the task) is not a good coding manner, which will only make confusions for the future readers of your codebase.
Also read: Why is "using namespace std;" considered bad practice?

If you want to double some values and not others, just do it:
#include <iostream>
#include <vector>
int main() {
std::vector<int> nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int& num : nums)
num = num % 2 ? 2 * num : num;
for (int num : nums)
std::cout << num << ' ';
std::cout << '\n';
return 0;
}
A conditional expression is an expression; you use it to compute a value. The code in the question does not do that; it uses the conditional expression as a way of selecting side effects, which is better done with an ordinary if statement.

Related

Comparing returned vectors from recursion tree branches

Suppose I have a given sum, say sum = 4. I am also given a vector = {2,4}. There are two ways to generate the given sum from the given vector (elements may be reused).
One way is just {4} cause 4 = 4.
Second way is {2,2} cause 2 + 2 = 4.
I have to find the shortest possible combination, therefore in this particular case the answer is {4}.
Here is my approach - I go through the tree, and when on the leaf I get a 0, we hit the base case, return {} vector, and fill up the vector while traversing the tree. When I get to a node, I choose the smaller of the two (or more) vectors. This way when I reach the root node, I should get a vector of the shortest combination that can yield me the target sum.
As of yet, I do not care about time constraints as such, I know there's a lot of repetitive computing going on so I will have to memoize it once I can get the basic version correct.
I have been trying to figure why this code is not working. Any insight would be appreciated.
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
vector<int> findBestSum(int targetSum, const vector<int> &elements, vector<vector<int>> &temp) {
if (targetSum == 0)
return {};
else if (targetSum < 0)
return {-1};
else {
vector<int> small;
for (auto &i : elements) {
int remainder = targetSum - i;
vector<int> returnedVector = findBestSum(remainder, elements, temp);
if ((!returnedVector.empty() && find(returnedVector.begin(), returnedVector.end(), -1) == returnedVector.end()) || returnedVector.empty()) {
returnedVector.push_back(i);
temp.push_back(returnedVector);
}
int smallestLength = temp[0].size();
for (auto &j : temp)
if (smallestLength >= j.size())
small = j;
}
return small;
}
}
int main() {
int targetSum = 6;
const vector<int> elements{2, 3, 5}; // answer should be [3,3] however I just get a 3...
vector<vector<int>> temp;
vector<int> bestSumVector = findBestSum(targetSum, elements, temp);
for (auto i : bestSumVector)
cout << i << " ";
}
Update (14th of July, 2021):
After a few busy months I have tried to lock horns with this problem and this time my code looks like this:
#include <iostream>
#include <vector>
#include <map>
#include <numeric>
using namespace std;
bool howSum(int &targetSum, vector<int> &elementVector, vector<int> &howSumVector, vector<vector<int>> &allSums) {
static int originaltargetsum = targetSum;
if (targetSum == 0)
return true;
else if (targetSum < 0)
return false;
else {
for (auto i : elementVector) {
int remainder = targetSum - i;
bool flag = howSum(remainder, elementVector, howSumVector, allSums);
if (flag) {
howSumVector.push_back(i);
if (targetSum == originaltargetsum ||
accumulate(howSumVector.begin(), howSumVector.end(), 0) == originaltargetsum) {
allSums.push_back(howSumVector);
howSumVector.clear();
}
return true;
}
}
return false;
}
}
int main() {
int sum = 8;
vector<int> elements = {1, 4, 5};
vector<vector<int>> allSums = {};
vector<int> workingBench = {};
howSum(sum, elements, workingBench, allSums);
for (auto &i : allSums) {
for (auto &j : i) {
cout << j << " ";
}
cout << endl;
}
}
For this I have sum as 8 and elements as {1, 4, 5}.
Also I'm storing and displaying all possible solutions right now (once that is correctly done, finding shortest vector and memoization should be easy). Possible solutions in this case are:
[1, 1, 1, 1, 1, 1, 1, 1]
[4, 4]
[5, 1, 1, 1]
[4, 1, 1, 1, 1]
Currently my code only shows the first possible combination. I'm pretty sure I'm returning true and false incorrectly, please help me out here.
I took a stab at this. I do have a working solution, hopefully it is what you want:
#include <iostream>
#include <vector>
#include <algorithm>
void howSum(int targetSum, const std::vector<int> & elementVector, const std::vector<int> & howSumVector, std::vector<std::vector<int>> & allSums)
{
static int originaltargetsum = targetSum;
if (targetSum == 0)
{
allSums.push_back(howSumVector);
return;
}
else if (targetSum < 0)
{
return;
}
else
{
for (const auto i : elementVector)
{
// an element less than or equal to 0 would cause an infinite loop
if (i <= 0)
continue;
std::vector<int> newSumVector = howSumVector;
newSumVector.push_back(i);
std::vector<int> newElementVector;
std::copy_if(std::begin(elementVector), std::end(elementVector), std::back_inserter(newElementVector), [i](int element){ return element >= i; });
howSum(targetSum - i, newElementVector, newSumVector, allSums);
}
}
}
int main()
{
int sum = 8;
std::vector<int> elements = { 1, 4, 5 };
std::vector<std::vector<int>> allSums = {};
std::vector<int> workingBench = {};
howSum(sum, elements, workingBench, allSums);
for (const auto & i : allSums)
{
for (const auto & j : i)
{
std::cout << j << " ";
}
std::cout << std::endl;
}
return 0;
}
I think, in general, you were over-thinking or over-engineering the problem. Like others have mentioned, your current code is returning true too early, and nothing besides the first element/combination is tested. With recursion, it is important to take care in your return cases - really, you only want a base case or two, and otherwise you want to recur.
With the solution I have here, the main thing I have added is copying the current combination of elements for each element you need to test. That solves your main issue of not testing every combination of numbers. In addition to that, it seemed better to append to allSums when the targetSum was reached. With those changes, I was able to do away with the bool return value and simplify the code a bit. Running the code above gives these solutions:
1 1 1 1 1 1 1 1
1 1 1 1 4
1 1 1 4 1
1 1 1 5
1 1 4 1 1
1 1 5 1
1 4 1 1 1
1 5 1 1
4 1 1 1 1
4 4
5 1 1 1
This does have some duplicates (because of the order things are tested) but I felt like it is good enough since you only want the smallest solution, 4 4. To find this, you would just need to sort the allSums vector by inner vector size and then take the first entry.
I think you need to change the implementation to correctly process elements of the vector.
In your implementation it doesn't go over all vector items, just the first one.
This is one way to do it if you use vector elements as the first parameter in your function.
vector<int> findBestSum(int element, int targetSum, const vector<int>& elements,
vector<vector<int>>& temp) {
if (targetSum == 0)
return {};
else if (targetSum < 0)
return { -1 };
else {
int remainder = targetSum - element;
vector<int> returnedVector = findBestSum(element, remainder, elements, temp);
if ((!returnedVector.empty() && find(returnedVector.begin(), returnedVector.end(), -1) == returnedVector.end()) || returnedVector.empty()) {
returnedVector.push_back(element);
return returnedVector;
}
return returnedVector;
}
}
int main() {
const int targetSum = 6;
const vector<int> elements{ 2, 3, 5 }; // answer should be [3,3] however I just get a 3...
vector<vector<int>> temp;
for (auto i : elements) {
vector<int> returnedVector = findBestSum(i, targetSum, elements, temp);
if ((!returnedVector.empty() && find(returnedVector.begin(), returnedVector.end(), -1) == returnedVector.end()) || returnedVector.empty())
temp.push_back(returnedVector);
}
if (temp.size() > 0) {
vector<int> bestSum = {};
size_t small = 0;
size_t smallestLength = temp[0].size();
for (auto& j : temp)
if (smallestLength >= j.size()) {
small = j.size();
bestSum = j;
}
for (auto i : bestSum)
cout << i << " ";
}
else
cout << " sum not found" << endl;
}

For loop crashes program while trying to read array c++

Exercise: The vector A[1 to N] and a value s is given. Build the program that writes backwards every group of s elements. If s divided by N has a remainder, then the remaining values should be unchanged. If s is bigger than N (the nr of elements of the vector) than there will be no modification.
Lets say s = 4 and A = (1, 2, 3, 4, 5, 6, 7, 8)then after execution the values will be A = (4, 3, 2, 1, 8, 7, 6, 5)
My teacher requires this kind of vector: int n, A[n] where n is a value given by the user. And i think this is what is causing my program to crash when i read the final values. If not, where is the problem?
#include <iomanip>
using namespace std;
int ordering(int s, int n, int A[]);
int main()
{
int n, A[n];
int s;
cout << "Vlera e s: ";
cin >> s;
if (s <= 0)
{
return 1;
}
cout << "\nN: ";
cin >> n;
if (n <= 0)
{
return 1;
}
cout << "\nVector:";
for (int i = 0; i < n; i++)
{
A[i] = i + 1;
cout << " " << A[i] << " ";
}
if (s > n)
{
cout << "\nNo change\n";
return 0;
}
else
{
ordering(s, n, A);
}
cout << "\nNew vector:";
for (int i = 0; i < n; i++)
{
cout << " " << A[i] << " ";
}
return 0;
}
int ordering(int s, int n, int A[])
{
int counter = 0;
for (int i = 0, divider = n / s; i < divider; i++)
{
int decrease = 0;
for (int j = counter, a = counter + s; j < a; j++)
{
A[j] = a - decrease;
decrease++;
}
counter += s;
}
return 0;
}
This program using a compiler extension to allow variable sized arrays in the form myArray[variableSize]. Whilst not standard, it does work on some compilers.
You are using this feature here:
int n, A[n];
However, n is uninitialised at this point. This is undefined behaviour even on the compilers that support such variable sized arrays. One possible (but not the only) outcome of undefined behaviour is your program crashing.
Undefined behaviour can do anything in theory, but the realistic set of things in can do in reality is smaller. Some of the likely implications of the undefined behaviour here:
n has some huge number in it, from whatever last used that bit of memory. As a result, A is huge.
n is 0. You can't have a 0 sized array. If the compiler doesn't notice this, you could end up trashing memory.
Since n is uninitialised, the optimiser for the compiler (they usually do very some optimisations, even when on -O0) assumes that undefined behaviour cannot occur, which is violated here, leading to strange behaviour.
n is a reasonable value, just by luck, but because it is later updated it no longer matches the size of the array and you end up reading / writing memory off the end of the array, trashing memory.
There are other possibilities, but this gives an idea of the kind of things that can happen as a result of this specific instance of undefined behaviour. If you're interested to know more, using a debugger to step through the code in assembly (you only need learn a little to understand the output, it looks more scary than it need be) will show you what's actually happening.
Variable length arrays is not a standard C++ feature.
int n, A[n];
Moreover in the above declaration the variable n was not initialized. So in any case the program has undefined behavior.
Instead of an array you could use the standard class template std::vector.
The program can look simpler and more safer is to use standard algorithms such as, for example, std::reverse.
Here is a demonstrative program.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <numeric>
void reorder( std::vector<int> &v, size_t s )
{
if ( not ( s < 2 ) )
{
for ( auto last = std::end( v );
not (std::distance( std::begin( v ), last ) < s ); )
{
auto first = std::prev( last, s );
std::reverse( first, last );
last = first;
}
}
}
int main()
{
std::cout << "Vlera e s: ";
size_t s = 0;
std::cin >> s;
std::cout << "N: ";
size_t n = 0;
std::cin >> n;
std::vector<int> v( n );
std::iota( std::begin( v ), std::end( v ), 1 );
putchar( '\n' );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
reorder( v, s );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
return 0;
}
The program output might look like
Vlera e s: 4
N: 10
1 2 3 4 5 6 7 8 9 10
1 2 6 5 4 3 10 9 8 7
But it seems you need write the corresponding code yourself using loops. In this case the program can look like
#include <iostream>
#include <vector>
void reorder( std::vector<int> &v, size_t s )
{
if ( not ( s < 2 ) )
{
for ( auto n = v.size(); !( n < s ); n -= s )
{
for ( size_t i = 0; i < s / 2; i++ )
{
int value = v[n - s + i];
v[n - s + i] = v[n - i - 1];
v[n - i - 1] = value;
}
}
}
}
int main()
{
std::cout << "Vlera e s: ";
size_t s = 0;
std::cin >> s;
std::cout << "N: ";
size_t n = 0;
std::cin >> n;
std::vector<int> v( n );
int value = 1;
for ( auto &item : v ) item = value++;
putchar( '\n' );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
reorder( v, s );
for ( const auto &item : v )
{
std::cout << item << ' ';
}
std::cout << '\n';
return 0;
}
The program output might look as already shown above
Vlera e s: 4
N: 10
1 2 3 4 5 6 7 8 9 10
1 2 6 5 4 3 10 9 8 7
Passing variable as array size is not valid you need to use constant const int n or create dinamic array int* arr = new int[n];, that array will be created in runtime, and you can pass variable as it size. Dont forget to delete that array whet it goes out of scope delete[] arr;

How to find a sequence of letter in a given string?

My string is "AAABBAABABB",
and I want to get the result as
A = 3
B = 2
A = 2
B = 1
A = 1
B = 2
I have tried to use
for (int i = 0; i < n - 1; i++) {
if (msg[i] == msg[i + 1]) {
if(msg[i]==A)
a++;
else
b++;
}
}
I tried this by it didn't work for me. And I don't understand if there any other ways to find it out. Please help me out.
Iterate through the array by followings:
If i = 0, we can set a variable as 0th character and counter by 1.
If ith character is equal to the previous character, we can increase the counter.
If ith character is not equal to the (i-1)th character we can print the character, counter and start counting the new character.
Try the following snippet:
char ch = msg[0];
int cnt = 1;
for (int i = 1; i < n; i ++){
if(msg[i] != msg[i-1]){
cout<<ch<<" "<<cnt<<endl;
cnt = 1;
ch = msg[i];
}
else {
cnt++;
}
}
cout<<ch<<" "<<cnt<<endl;
You can use std::vector<std::pair<char, std::size_t>> to store character occurrences.
Eventually, you would have something like:
#include <iostream>
#include <utility>
#include <vector>
#include <string>
int main() {
std::vector<std::pair<char, std::size_t>> occurrences;
std::string str{ "AAABBAABABB" };
for (auto const c : str) {
if (!occurrences.empty() && occurrences.back().first == c) {
occurrences.back().second++;
} else {
occurrences.emplace_back(c, 1);
}
}
for (auto const& it : occurrences) {
std::cout << it.first << " " << it.second << std::endl;
}
return 0;
}
It will output:
A 3
B 2
A 2
B 1
A 1
B 2
Demo
This is very similar to run length encoding. I think the simplest way (less line of codes) I can think of is like this:
void runLength(const char* msg) {
const char *p = msg;
while (p && *p) {
const char *start = p++; // start of a run
while (*p == *start) p++; // move p to next run (different run)
std::cout << *start << " = " << (p - start) << std::endl;
}
}
Please note that:
This function does not need to know the length of input string before hand, it will stop at the end of string, the '\0'.
It also works for empty string and NULL. Both these work: runLength(""); runLength(nullptr);
I can not comment yet, if you look carefully, mahbubcseju's code does not work for empty msg.
With std, you might do:
void print_sequence(const std::string& s)
{
auto it = s.begin();
while (it != s.end()) {
auto next = std::adjacent_find(it, s.end(), std::not_equal_to<>{});
next = next == s.end() ? s.end() : next + 1;
std::cout << *it << " = " << std::distance(it, next) << std::endl;
it = next;
}
}
Demo
Welcome to stackoverflow. Oooh, an algorithm problem? I'll add a recursive example:
#include <iostream>
void countingThing( const std::string &input, size_t index = 1, size_t count = 1 ) {
if( input.size() == 0 ) return;
if( input[index] != input[index - 1] ) {
std::cout << input[index - 1] << " = " << count << std::endl;
count = 0;
}
if( index < input.size() ) return countingThing( input, index + 1, count + 1 );
}
int main() {
countingThing( "AAABBAABABB" );
return 0;
}
To help work out algorithms and figuring out what to write in your code, I suggest a few steps:
First, write out your problem in multiple ways, what sort of input it expects and how you would like the output to be.
Secondly, try and solve it on paper, how the logic would work - a good tip to this is try to understand how YOU would solve it. Your brain is a good problem solver, and if you can listen to what it does, you can turn it into code (it isn't always the most efficient, though).
Thirdly, work it out on paper, see if your solution does what you expect it to do by following your steps by hand. Then you can translate the solution to code, knowing exactly what you need to write.

Compare all values of a array with a value from another array with C++

I have to compare two arrays, i need to know if the same name of a value in the other array exists. My problem is that it always returns only one matched value but there are two with the same name.
One array is 9 length big the other 3.
Is there maybe an easier solution because mine looks a little bit too complex, am I right?
Thank you in advance
Here is my Code:
for (int i=0;i<9;i++ )
{
int counter = 0;
int j = 0;
if (stockTest[j].getTestTitle() == products[i].getTitle())
{
cout << stockTest[j].getTestTitle() << " is available ";
counter = counter + 1; // counter + 1 because it is available
}
if ((j == 0) && (counter == 0) && (i == 9)) // try everything till i is 9 if counter is still 0 display message.
{
cout << stockTest[j].getTestTitle() << " is not available ";
}
if ((j == 1) && (counter == 0) && (i == 9)) // compare everything from stockTest[1], till i is 9 if counter is still 0 display message.
{
cout << stockTest[j].getTestTitle() << " is not available ";
}
if ((j == 2) && (counter == 0) && (i == 9)) //compare everything from stockTest[2], till i is 9 if counter is still 0 display message.
{
cout << stockTest[j].getTestTitle() << " is not available ";
}
if ( i == 9)
{
j = j + 1; //there are three values to compare in the other array so I will increment like this till 2 (the next if statement will end the loop if j == 2)
i = 0; // i again 0 so that again all 9 values from the array will be compared
counter = 0; // counter = 0 so that if the value is not found the counter == 0 is true
}
if ((j == 2) && ( i = 9 ))
i = 9; //i is now 9 which means that loop should end now however I can delete this line of code and the program would still display only one value. I expected an infinte loop if i delete it?
}
If the arrays can be sorted on title, then one solution would be to use std::set_intersection.
Pre C++ 11 code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <ostream>
struct stockTest
{
std::string title;
std::string getTitle() const { return title; }
stockTest(const std::string s) : title(s) {}
friend std::ostream& operator << (std::ostream& os, const stockTest&);
};
// for output purposes
std::ostream& operator << (std::ostream& os, const stockTest& s)
{
os << s.getTitle();
return os;
}
// compares two stockTest items
bool Comparer(const stockTest& f1, const stockTest& f2)
{
return f1.getTitle() < f2.getTitle();
}
using namespace std;
int main()
{
stockTest s1[] = {stockTest("abc"), stockTest("123"), stockTest("456")};
stockTest s2[] = {stockTest("123"), stockTest("Joe"), stockTest("789"), stockTest("456")};
// first, we sort our arrays
std::sort(s1, s1 + 3, Comparer);
std::sort(s2, s2 + 4, Comparer);
// this vector will contain the similar items
std::vector<stockTest> v_intersection;
// use set_intersection to do the hard work
std::set_intersection(s1, s1 + 3, s2, s2 + 4, std::back_inserter(v_intersection), Comparer);
// output the results
cout << "The similar names are: " << endl;
copy(v_intersection.begin(), v_intersection.end(), ostream_iterator<stockTest>(cout, "\n"));
}
Note that at the end, we created a vector that contains the common names. Also note that we had to sort the arrays first, plus provide set_intersection to know how the items are sorted (according to the Comparer functor).
Live Example: http://ideone.com/GA8ey0
First, you reinitialize counter to 0 every iteration of the first loop which probably has something to do with it.
Second, i would do something like the following with two for loops:
int counter = 0;
for(int i = 0; i<3; i++)
{
for(int j=0; j<9; j++)
{
if(array1[i] == array2[j])
{
counter++;
}
}
}
It is difficult to follow your logic as im not sure what you're using counter for or why (but breaking it down to simplicity, it is just a counter that stores how many times an equivalent value has been matched. Lets not over complicate it).
So its just a simple outer and inner for loop where you iterate and compare all 9 values of the second array to each value of the first array (3 values). I hope this helps.

C++ Primer 5th Edition exercise 3.24 - iterators in vectors

I just started learning C++ by myself using Lippman, Lajoie & Moo's C++ Primer Fifth Edition (5th printing, may 2014) in september 2014. Some exercises in that book I could do, some I had to look here for help and at this one I'm stuck for days. I searched Google, blogs and other forums and got nothing, so I ask you for help. It is the exercise 3.24 at page 113, which asks the same as the exercise 3.20 in page 105, but using iterators:
Read a set of integers into a vector. Print the sum of each pair of adjacent elements. Change your program so that it prints the sum of the first and last elements, followed by the sum of the second and second-to-last, and so on.
Using iterators as it asked, I could do the first part:
#include <iostream>
#include <vector>
using std::cin; using std::cout; using std::endl; using std::vector;
int main()
{
vector<int> lista;
int num_entra = 0;
while (cin >> num_entra)
lista.push_back(num_entra);
cout << "Sum of adjacent pairs: " << endl;
for (auto it = lista.begin(); it != lista.end() - 1; ++it)
{
*it += *(it + 1);
cout << *it << ' ';
}
return 0;
}
The code above works as intended, but the part where I need to sum the first and last, second and second to last... etc. has an issue I just can't solve:
int main()
{
vector<int> lista;
int num_entra = 0;
while (cin >> num_entra)
lista.push_back(num_entra);
auto ult = lista.end();
cout << "Sum of the first and last elements until the center: " << endl;
for (auto it = lista.begin(); it != lista.end() - 1; ++it)
{
*it = *it + *(--ult);
cout << *it << ' ';
}
return 0;
}
If the user enters 1 2 3 4 5 6, the program adds 1 + 6, 2 + 5 and 3 + 4 as it should,
but then it adds the last result (7) with 5 and then with 6 and I can't seem to find a way to stop this behavior. What can I do so the program shows only one sum for each pair until the center of the list?
Thank you in advance.
One way to do this would be to use two iterators
auto front = lista.begin(); // start at front and increment
auto back = lista.end() - 1; // start at back and decrement
for (;
back > front; // stop when the iterators cross each other
++front, --back)
{
int total = *front + *back;
std::cout << total << ' ';
}
The problem with your code is that you're modifying the vector as you compute the sums by dereferencing the iterator (might not be a problem but it's a likely unwanted side effect) and you're not even stopping the cycle when you've "surpassed" the middle of the vector.
A simple version could be
auto front = lista.begin();
auto back = lista.end() - 1;
for (; back > front; ++front, --back)
{
int total = *front + *back;
std::cout << total << ' ';
}
but this doesn't handle an odd number of elements like 1 2 3 4 5 6 7 (the central 4 isn't printed). If you don't want any "same element" couple, this is fine and this solution will handle every case you need, otherwise go ahead.
A fixed version could be
auto front = lista.begin();
auto back = lista.end() - 1;
for (; back >= front; ++front, --back)
{
if (front == back)
cout << *front;
else {
int total = *front + *back;
std::cout << total << ' ';
}
}
but this doesn't handle a null list [].
This solution handles both although it's more complex:
auto it = lista.begin();
auto ult = lista.rbegin();
size_t dist;
for ( ; it != lista.end() && // I have a valid front iterator
ult != lista.rend() && // I have a valid back iterator
(dist = std::distance(it,ult.base()), dist) > 0; // Their distance is greater than 0 (1 is included)
++it,++ult ) {
if (dist == 1)
cout << *it;
else
cout << *it + *ult << ' ';
}
In addition to incrementing one iterator while decrementing another, I think the best way is to use a reverse iterator.
auto it = list.begin();
auto rit = list.rbegin(); // a "reverse iterator"
while (it < rit.base()) {
cout << *it++ + *rit++ << ' ';
}
Using a reverse iterator means you don't have to worry about any "off-by-one" adjustments due to the asymmetry between begin and end.
Here is also one approach where mid is an iterator closest to the middle of the array, which is also commonly used in binary search implementation:
auto e = lista.end() - 1;
auto mid = lista.end() + (lista.begin() - lista.end()) / 2;
for (auto i = lista.begin(); i != mid; ++i, --e){
cout << *i << "+" << *e << " = " << (*i)+(*e) << endl;
}
Input: 1 2 3 4 5 6 7 8 9;
Positions/index: 0 1 2 3 4 5 6 7 8 9
Where mid = (0 - 10) / 2 => -5 + 10 => 5 The loop stops after reading number five.
And at index 5 is number 6. Therefore the loop stops when it hits the iterator closest to the middle:
i != mid;
/*Output*/
1+9 = 10
2+8 = 10
3+7 = 10
4+6 = 10
5+5 = 10
PS. I recommend you do checks to see if the vector is empty.
My five cents. Only instead of the explicitly initialized vector you should enter values for it as you did.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
if ( !v.empty() )
{
auto first = v.cbegin(), last = v.cend();
do
{
std::cout << *first + *--last;
} while ( first++ != last );
}
return 0;
}
The output is
666
This approach you also can use for example with std::list
If you need to skip the middle odd element then the general approach for containers that have no random access iterator is the following
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
for ( auto first = v.cbegin(), last = v.cend();
first != last && first != --last;
++first )
{
std::cout << *first + *last;
}
std::cout << std::endl;
return 0;
}
As vectors have random acces iterators then the code can be rewritten using operator <
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
if ( !v.empty() )
{
for ( auto first = v.cbegin(), last = v.cend();
first < --last;
++first )
{
std::cout << *first + *last;
}
std::cout << std::endl;
}
return 0;
}
In both cases the output will be
66