For loop acting on vector of integers is behaving strangely - c++

#include <iostream>
#include <vector>
std::vector<int> normalize(std::vector<int> a) {
for (int j = a.size() - 1; j > 0; --j) {
while (a[j] > 9) {
a[j] = a[j] - 10;
std::cout << '!'; //Just to test if the loop is executed (the correct # of times)
++a[j - 1];
}
}
// checks that the last digit isnt too large, makes new digit otherwise
if (a[0] > 9) {
a.insert(a.begin(), 0);
while (a[1] > 9) {
a[1] -= 10;
++a[0];
}
}
return a;
}
// for debugging convenience
void printVector(std::vector<int> a) {
for (int i = 0; i < a.size(); ++i) {
std::cout << a[i] << ' ';
}
std::cout << std::endl;
}
int main()
{
std::vector<int> a;
a.push_back(1); a.push_back(2); a.push_back(33);
normalize(a);
printVector(a);
return 0;
}
This program represents large integers as lists of digits, The normalize function would change {1,2,33} to {1,5,3}, representing 153, for instance. I'm new to C++ so I'm not using classes and I'm not using any big integer headers that would have this all much better implemented.
Returns: !!!1 2 33
as though the vector has not been changed. But then how would the "std::cout '!'" line print the correct number of times, or even the while loop terminate at all?

In your function
std::vector<int> normalize(std::vector<int> a)
you are passing a by value, so it won't be modified once the function exits. To make it work, you should use your current implementation as
auto result = normalize(a); // now we get the result
printVector(result); // and display it
To avoid making an un-necessary copy, you should pass the agument by const reference:
std::vector<int> normalize(std::vector<int> const& a)
If you want to modify the parameter that's passed to your function, you should pass by reference:
std::vector<int> normalize(std::vector<int>& a) // now we can modify a
However, it's a good idea to implement functions as black boxes without side effects (if possible), as it will make testing and multi-threading much easier, so I'd suggest passing by const reference then returning the result.

Your function uses pass-by-value. This means that the call normalize(a); does not modify a, it modifies a copy of a.
To fix this there are two ways:
Make the call a = normalize(a);
Make the function have void return type, and use pass-by-reference (put a & in the function prototype before the parameter name).
The first way is more natural but unfortunately has performance problems for large vectors, so most people would prefer the second way
NB. You currently don't handle the possibility of a[0] > 9 after the insert and adjustment; and it would be simpler to store the least-significant digit first, then you can append instead of inserting at the front, and you wouldn't need to divide your algorithm up into the two parts.

Related

Find a combination of elements from different arrays

I recently started learning C++ and ran into problems with this task:
I am given 4 arrays of different lengths with different values.
vector<int> A = {1,2,3,4};
vector<int> B = {1,3,44};
vector<int> C = {1,23};
vector<int> D = {0,2,5,4};
I need to implement a function that goes through all possible variations of the elements of these vectors and checks if there are such values a from array A, b from array B, c from array C and d from array D that their sum would be 0(a+b+c+d=0)
I wrote such a program, but it outputs 1, although the desired combination does not exist.
using namespace std;
vector<int> test;
int sum (vector<int> v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(vector<int> A,vector<int> B,vector<int> C,vector<int> D){
for ( int ai = 0; ai <= A.size(); ai++){
test[0] = A[ai];
for ( int bi = 0; bi <= B.size(); bi++){
test[1] = B[bi];
for ( int ci = 0; ci <= C.size(); ci++){
test[2] = C[ci];
for ( int di = 0; di <= D.size(); di++){
test[3] = D[di];
if (sum (test) == 0){
return true;
}
}
}
}
}
}
I would be happy if you could explain what the problem is
Vectors don't increase their size by themself. You either need to construct with right size, resize it, or push_back elements (you can also insert, but vectors arent very efficient at that). In your code you never add any element to test and accessing any element, eg test[0] = A[ai]; causes undefined behavior.
Further, valid indices are [0, size()) (ie size() excluded, it is not a valid index). Hence your loops are accessing the input vectors out-of-bounds, causing undefined behavior again. The loops conditions should be for ( int ai = 0; ai < A.size(); ai++){.
Not returning something from a non-void function is again undefined behavior. When your abcd0 does not find a combination that adds up to 0 it does not return anything.
After fixing those issues your code does produce the expected output: https://godbolt.org/z/KvW1nePMh.
However, I suggest you to...
not use global variables. It makes the code difficult to reason about. For example we need to see all your code to know if you actually do resize test. If test was local to abcd0 we would only need to consider that function to know what happens to test.
read about Why is “using namespace std;” considered bad practice?
not pass parameters by value when you can pass them by const reference to avoid unnecessary copies.
using range based for loops helps to avoid making mistakes with the bounds.
Trying to change not more than necessary, your code could look like this:
#include <vector>
#include <iostream>
int sum (const std::vector<int>& v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(const std::vector<int>& A,
const std::vector<int>& B,
const std::vector<int>& C,
const std::vector<int>& D){
for (const auto& a : A){
for (const auto& b : B){
for (const auto& c : C){
for (const auto& d : D){
if (sum ({a,b,c,d}) == 0){
return true;
}
}
}
}
}
return false;
}
int main() {
std::vector<int> A = {1,2,3,4};
std::vector<int> B = {1,3,44};
std::vector<int> C = {1,23};
std::vector<int> D = {0,2,5,4};
std::cout << abcd0(A,B,C,D);
}
Note that I removed the vector test completely. You don't need to construct it explicitly, but you can pass a temporary to sum. sum could use std::accumulate, or you could simply add the four numbers directly in abcd0. I suppose this is for exercise, so let's leave it at that.
Edit : The answer written by #463035818_is_not_a_number is the answer you should refer to.
As mentioned in the comments by #Alan Birtles, there's nothing in that code that adds elements to test. Also, as mentioned in comments by #PaulMcKenzie, the condition in loops should be modified. Currently, it is looping all the way up to the size of the vector which is invalid(since the index runs from 0 to the size of vector-1). For implementing the algorithm that you've in mind (as I inferred from your code), you can declare and initialise the vector all the way down in the 4th loop.
Here's the modified code,
int sum (vector<int> v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(vector<int> A,vector<int> B,vector<int> C,vector<int> D){
for ( int ai = 0; ai <A.size(); ai++){
for ( int bi = 0; bi <B.size(); bi++){
for ( int ci = 0; ci <C.size(); ci++){
for ( int di = 0; di <D.size(); di++){
vector<int> test = {A[ai], B[bi], C[ci], D[di]};
if (sum (test) == 0){
return true;
}
}
}
}
}
return false;
}
The algorithm is inefficient though. You can try sorting the vectors first. Loop through the first two of them while using the 2 pointer technique to check if desired sum is available from the remaining two vectors
It looks to me, like you're calling the function every time you want to check an array. Within the function you're initiating int sum_of_elements = 0;.
So at the first run, you're starting with int sum_of_elements = 0;.
It finds the element and increases sum_of_elements up to 1.
Second run you're calling the function and it initiates again with int sum_of_elements = 0;.
This is repeated every time you're checking the next array for the element.
Let me know if I understood that correctly (didn't run it, just skimmed a bit).

Sort Array By Parity the result is not robust

I am a new programmer and I am trying to sort a vector of integers by their parities - put even numbers in front of odds. The order inside of the odd or even numbers themselves doesn't matter. For example, given an input [3,1,2,4], the output can be [2,4,3,1] or [4,2,1,3], etc. Below is my c++ code, sometimes I got luck that the vector gets sorted properly, sometimes it doesn't. I exported the odd and even vectors and they look correct, but when I tried to combine them together it is just messed up. Can someone please help me debug?
class Solution {
public:
vector<int> sortArrayByParity(vector<int>& A) {
unordered_multiset<int> even;
unordered_multiset<int> odd;
vector<int> result(A.size());
for(int C:A)
{
if(C%2 == 0)
even.insert(C);
else
odd.insert(C);
}
merge(even.begin(),even.end(),odd.begin(),odd.end(),result.begin());
return result;
}
};
If you just need even values before odds and not a complete sort I suggest you use std::partition. You give it two iterators and a predicate. The elements where the predicate returns true will appear before the others. It works in-place and should be very fast.
Something like this:
std::vector<int> sortArrayByParity(std::vector<int>& A)
{
std::partition(A.begin(), A.end(), [](int value) { return value % 2 == 0; });
return A;
}
Because the merge function assumes that the two ranges are sorted, which is used as in merge sort. Instead, you should just use the insert function of vector:
result.insert(result.end(), even.begin(), even.end());
result.insert(result.end(), odd.begin(), odd.end());
return result;
There is no need to create three separate vectors. As you have allocated enough space in the result vector, that vector can be used as the final vector also to store your sub vectors, storing the separated odd and even numbers.
The value of using a vector, which under the covers is an array, is to avoid inserts and moves. Arrays/Vectors are fast because they allow immediate access to memory as an offset from the beginning. Take advantage of this!
The code simply keeps an index to the next odd and even indices and then assigns the correct cell accordingly.
class Solution {
public:
// As this function does not access any members, it can be made static
static std::vector<int> sortArrayByParity(std::vector<int>& A) {
std::vector<int> result(A.size());
uint even_index = 0;
uint odd_index = A.size()-1;
for(int element: A)
{
if(element%2 == 0)
result[even_index++] = element;
else
result[odd_index--] = element;
}
return result;
}
};
Taking advantage of the fact that you don't care about the order among the even or odd numbers themselves, you could use a very simple algorithm to sort the array in-place:
// Assume helper function is_even() and is_odd() are defined.
void sortArrayByParity(std::vector<int>& A)
{
int i = 0; // scanning from beginning
int j = A.size()-1; // scanning from end
do {
while (i < j && is_even(A[i])) ++i; // A[i] is an even at the front
while (i < j && is_odd(A[j])) --j; // A[j] is an odd at the back
if (i >= j) break;
// Now A[i] must be an odd number in front of an even number A[j]
std::swap(A[i], A[j]);
++i;
--j;
} while (true);
}
Note that the function above returns void, since the vector is sorted in-place. If you do want to return a sorted copy of input vector, you'd need to define a new vector inside the function, and copy the elements right before every ++i and --j above (and of course do not use std::swap but copy the elements cross-way instead; also, pass A as const std::vector<int>& A).
// Assume helper function is_even() and is_odd() are defined.
std::vector<int> sortArrayByParity(const std::vector<int>& A)
{
std::vector<int> B(A.size());
int i = 0; // scanning from beginning
int j = A.size()-1; // scanning from end
do {
while (i < j && is_even(A[i])) {
B[i] = A[i];
++i;
}
while (i < j && is_odd(A[j])) {
B[j] = A[j];
--j;
}
if (i >= j) break;
// Now A[i] must be an odd number in front of an even number A[j]
B[i] = A[j];
B[j] = A[i];
++i;
--j;
} while (true);
return B;
}
In both cases (in-place or out-of-place) above, the function has complexity O(N), N being number of elements in A, much better than the general O(N log N) for sorting N elements. This is because the problem doesn't actually sort much -- it only separates even from odd. There's therefore no need to invoke a full-fledged sorting algorithm.

For loop over vector vectorized using C style pointers but not using iterators

I have written a small piece of code that I use to accumulate the values of a vector which is faster than the std::accumulate because it allows the function to be vectorized. The main prerequisite for the function is that the vector is no longer used after the accumulation. The code is as follows:
template <typename floatType>
template <typename Iterator>
double Numeric_class<floatType>::AmDestructiveAccumulate(Iterator A, size_t length)
{
if (length == 1)
{
return A[0];
}
Iterator temp_;
while (length > 1)
{
if (length & 1) // odd
{
A[0] += A[length - 1]; // We add the last value which would otherwise be lost.
length >>= 1;
temp_ = A+length;
for (int i = 0; i < length; i++)
{
A[i] += temp_[i];
}
}
else // even
{
length >>= 1;
temp_ = A+length;
for (int i = 0; i < length; i++)
{
A[i] += temp_[i];
}
}
}
return A[0];
}
The function basically splits the vector in two halfs and takes the pairwise sum of the two halfs. After this it splits the summed first half in two equally long ranges and again sums the up pairwise and so on.
I used this function with std::vector<double> data. If I call it with A being data.data(). The vectorization tales place as expected and I also get a significant increase in execution speed. If I use data.begin(), no vectorization takes place. I compiled the code using VC2015 with full optimization. Is there a reason why it would be illegal to vectorized the iterator version of the code or does VC just not do it although it would be legal.
The core problem is going to be A[i] += temp_[i];. Note that A and temp alias each other, but that your run-time choices of [i] means that this is only theoretical. Now, what does [i] actually mean? If A is a pointer, that's just shorthand for *(A+i), but when A is an iterator, it's a function call.
Efficient vectorization requires the compiler to spot that the write to A[i] does not affect subsequent reads from temp[i], which is a non-trivial observation. There's no loop-carried dependency, but the optimizer must be able to prove it.

Deleting elements from a vector that meet a condition

I am trying to program the Sieve of Eratosthenes, but I am not sure how to delete elements from the vector I made given a specific condition. Does anyone know how to achieve this? Here is my code:
#include <iostream>
#include <vector>
using namespace std;
int prime(int n);
int prime(int n)
{
vector<int> primes;
for(int i = 2; i <= n; i++)
{
primes.push_back(i);
int t = i % (i + 1);
if(t == 0)
{
delete t; // is there a way of deleting the elements from
// the primes vector that follow this condition t?
}
cout << primes[i] << endl;
}
}
int main()
{
int n;
cout << "Enter a maximum numbers of primes you wish to find: " << endl;
cin >> n;
prime(n);
return 0;
}
Your algorithm is wrong:
t = i % (i + 1);
is
i
which is always != 0 because i is larger than 1.
By the way if you absolutely want to remove the t-th element you have to be sure that the vector is not empty and then you do:
primes.erase(primes.begin()+t);
Even if you fix the algorithm your approach is inefficient: erasing an element in the middle of a vector means copying back of one position all the ones following the erased element.
You don't usually want to delete elements in the middle of a Sieve of Eratosthenes, but when you do want to, you usually want to use the remove/erase idiom:
x.erase(std::remove_if(x.begin(), x.end(), condition), x.end());
std::remove basically just partitions the collection into those that don't meet the specified condition, followed by objects that may have been used as the source of either a copy or a move, so you can't count on their value, but they are in some stable state so erasing them will work fine.
The condition can be either a function or a functor. It receives (a reference to a const) object that it examines and determines whether it lives or dies (so to speak).
Find here a c++ pseudocode for the sieve algorithm. Once you've understood the algorithm you can start working on this.
primes(vector& primes, size_t max){
vector primesFlag(1,max);
i=1
while(i*i<max){
++i;
for(j=i*i; j < max; j+= i){
primesFlag[j] = 0;
}
}
primes.clear()
primes.reserve(...);
for(j >= 2;
if primesFlag[j] = 1
primes.push_back(j);
}

efficient way to copy array with mask in c++

I have two arrays. One is "x" factor the size of the second one.
I need to copy from the first (bigger) array to the second (smaller) array only its x element.
Meaning 0,x,2x.
Each array sits as a block in the memory.
The array is of simple values.
I am currently doing it using a loop.
Is there any faster smarter way to do this?
Maybe with ostream?
Thanks!
You are doing something like this right?
#include <cstddef>
int main()
{
const std::size_t N = 20;
const std::size_t x = 5;
int input[N*x];
int output[N];
for(std::size_t i = 0; i < N; ++i)
output[i] = input[i*x];
}
well, I don't know any function that can do that, so I would use the for loop. This is fast.
EDIT: even faster solution (to avoid multiplications)(C++03 Version)
int* inputit = input;
int* outputit = output;
int* outputend = output+N;
while(outputit != outputend)
{
*outputit = *inputit;
++outputit;
inputit+=x;
}
if I get you right you want to copy every n-th element. the simplest solution would be
#include <iostream>
int main(int argc, char **argv) {
const int size[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int out[5];
int *pout = out;
for (const int *i = &size[0]; i < &size[10]; i += 3) {
std::cout << *i << ", ";
*pout++ = *i;
if (pout > &out[4]) {
break;
}
}
std::cout << "\n";
for (const int *i = out; i < pout; i++) {
std::cout << *i << ", ";
}
std::cout << std::endl;
}
You can use copy_if and lambda in C++11:
copy_if(a.begin(), a.end(), b.end(), [&] (const int& i) -> bool
{ size_t index = &i - &a[0]; return index % x == 0; });
A test case would be:
#include <iostream>
#include <vector>
#include <algorithm> // std::copy_if
using namespace std;
int main()
{
std::vector<int> a;
a.push_back(0);
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
std::vector<int> b(3);
int x = 2;
std::copy_if(a.begin(), a.end(), b.begin(), [&] (const int& i) -> bool
{ size_t index = &i - &a[0]; return index % x == 0; });
for(int i=0; i<b.size(); i++)
{
std::cout<<" "<<b[i];
}
return 0;
}
Note that you need to use a C++11 compatible compiler (if gcc, with -std=c++11 option).
template<typename InIt, typename OutIt>
void copy_step_x(InIt first, InIt last, OutIt result, int x)
{
for(auto it = first; it != last; std::advance(it, x))
*result++ = *it;
}
int main()
{
std::array<int, 64> ar0;
std::array<int, 32> ar1;
copy_step_x(std::begin(ar0), std::end(ar0), std::begin(ar1), ar0.size() / ar1.size());
}
The proper and clean way of doing this is a loop like has been said before. A number of good answers here show you how to do that.
I do NOT recommend doing it in the following fashion, it depends on a lot of specific things, value range of X, size and value range of the variables and so on but for some you could do it like this:
for every 4 bytes:
tmp = copy a 32 bit variable from the array, this now contains the 4 new values
real_tmp = bitmask tmp to get the right variable of those 4
add it to the list
This only works if you want values <= 255 and X==4, but if you want something faster than a loop this is one way of doing it. This could be modified for 16bit, 32bit or 64bit values and every 2,3,4,5,6,7,8(64 bit) values but for X>8 this method will not work, or for values that are not allocated in a linear fashion. It won't work for classes either.
For this kind of optimization to be worth the hassle the code need to run often, I assume you've run a profiler to confirm that the old copy is a bottleneck before starting implementing something like this.
The following is an observation on how most CPU designs are unimaginative when it comes to this sort of thing.
On some OpenVPX you have the ability to DMA data from one processor to another. The one that I use has a pretty advanced DMA controller, and it can do this sort of thing for you.
For example, I could ask it to copy your big array to another CPU, but skipping over N elements of the array, just like you're trying to do. As if by magic the destination CPU would have the smaller array in its memory. I could also if I wanted perform matrix transformations, etc.
The nice thing is that it takes no CPU time at all to do this; it's all done by the DMA engine. My CPUs can then concentrate on harder sums instead of being tied down shuffling data around.
I think the Cell processor in the PS3 can do this sort of thing internally (I know it can DMA data around, I don't know if it will do the strip mining at the same time). Some DSP chips can do it too. But x86 doesn't do it, meaning us software programmers have to write ridiculous loops just moving data in simple patterns. Yawn.
I have written a multithreaded memcpy() in the past to do this sort of thing. The only way you're going to beat a for loop is to have several threads doing your for loop in several parallel chunks.
If you pick the right compiler (eg Intel's ICC or Sun/Oracles Sun Studio) they can be made to automatically parallelise your for loops on your behalf (so your source code doesn't change). That's probably the simplest way to beat your original for loop.