How to avoid copying values to a separate array? - c++

I have the following program that computes the "partial sum" of an array. For example, if I input the consecutive integers 1, 1, 1, 1 through std::cin my program will calculate the result into an array as 1, 2, 3, 4.
#include <iostream>
int main()
{
int orig[10], copy[10];
std::cout << "please enter 10 numbers:" << std::endl;
for (int i = 0; i < 10; i++)
{
std::cin >> orig[i];
}
for (int i = 0; i < 10; ++i)
{
int sum = 0;
for (int k = i; k >= 0; --k)
{
sum += orig[k];
}
copy[i] = sum;
}
std::cout << "the ascending order is:\n" << endl;
for (int i = 0; i < 10; ++i)
std::cout << copy[i] << std::endl;
}
My problem is that I would like for there to be a way to do this without copying the value into another array. So far I haven't figured out how. As you can see, in the above code I have an integer array named copy into which I put the sum into its indicies. I know this can be done using std::vector and partial_sum but I would rather not use it as it does not allow me to fully understand how this works.
Any ideas? Thanks.

You don't need the two nested for loops. Move the initialization of sum out of the for loop to keep track of the sum as you iterate over orig. The simply overwrite the values in orig with sum as you go.
In psuedocode:
sum = 0
for each index i in array:
sum += array[i]
array[i] = sum

I know you don't want to use partial_sum, but here it is in all its simplicity:
#include <iostream>
#include <iterator>
#include <numeric>
int main()
{
using namespace std;
partial_sum(istream_iterator<int>(cin),
istream_iterator<int>(),
ostream_iterator<int>(cout, "\n"));
}
Code here.

Can't you print this out in the process without storing it?
sum = 0 ;
for ( int i = 0 ; i < 10 ; i++ )
{
sum += orig[ i ] ;
std::cout << sum << "\n" ;
}

Related

How do I calculate the sum of all the array numbers after the first negative?

Can you help me with this problem? All I could do was count all the negative numbers.
Here is my code:
using namespace std;
int main()
{
const int SIZE = 10;
int arr[SIZE]{};
int number=0;
srand(time(NULL));
cout << "Your array is: " << endl;
for (int i=0; i<SIZE; i++)
{
int newValue = rand()%20-10;
arr[i] = newValue;
cout << arr[i] << " ";
if (arr[i] < 0)
{
for (int j=-1; j<SIZE; j++)
{
number = arr[i];
sum += fabs(number);
break;
}
}
}
cout << endl;
cout << "Sum of elements after first element < 0 is: " << sum;
cout << endl;
}
One way is to have a flag that is zero to start with that is switched on after the first negative:
int flag = 0;
int sum = 0;
for (std::size_t i = 0; i < SIZE; ++i){
sum += flag * arr[i];
flag |= arr[i] < 0;
}
This approach carries the advantage that you don't need an array at all: substituting the next number from standard input for arr[i] is sufficient.
In your specific case, there are numerous simple and efficient solutions, like that offered by Bathsheba.
However, for a more general case of summing elements in an array after the first value satisfying a given condition, you can use the std::find_if and std::accumulate functions from the STL, providing appropriate lambda functions to do the test (checking for negative) and summation (the sum += fabs(number) in your code implies that you want to sum the absolute values of the remaining elements1).
Here's a possible implementation:
#include <cstdlib> // std::abs, std::rand
#include <ctime> // std::time
#include <algorithm> // std::find_if
#include <numeric> // std::accumulate
#include <iostream>
using std::cout, std::endl;
int main()
{
const int SIZE = 10;
int arr[SIZE]{};
// Generate random array...
std::srand(static_cast<unsigned int>(time(nullptr)));
cout << "Your array is: " << endl;
for (int i = 0; i < SIZE; i++) {
int newValue = std::rand() % 20 - 10;
arr[i] = newValue;
cout << arr[i] << " ";
}
// Sum all abs values after first negative ...
auto is_neg = [](int i) { return i < 0; };
auto fn = std::find_if(std::begin(arr), std::end(arr), is_neg);
auto sum_abs = [](int a, int b) { return a + std::abs(b); };
// Set the sum to ZERO if the first negative is the last element...
int sum = (fn == std::end(arr)) ? 0 : std::accumulate(++fn, std::end(arr), 0, sum_abs);
cout << endl;
cout << "Sum of elements after first element < 0 is: " << sum;
cout << endl;
return 0;
}
1 If this is not the case, and you just want the sum of the actual values, then you can omit the 4th (sum_abs) argument in the call to std::accumulate (and the definition of that lambda).

Print the array value which can produce the input by using addition operator

How do I edit the given program to get all possible combinations of array values which will provide the given data using addition operator?
The following code works fine only if there is only one combination. For example, in the array = {1,2,3,4,5}, the given value = 6; the only possibility is the sum of 2 and 4. Thus the output desired is array [1] & array[3]. Attached coding works fine for this. But for array ={1, 3, 3, 4, 2}, there is two possibilities but the code returns nothing...
#include<iostream>
using namespace std;
int main() {
int n = 5; int m = 0;
int givendata;
int a[n];
for (int i = 0; i < n; i++) {
cin >> a[i];
}
cin >> givendata;
if (m < n) {
for (int i = 0; i < n; i++) {
int sum = a[n - i] + a[m];
if (sum == givendata) {
cout << m << " " << n - i;
}
}
}
m = m + 1;
return 0;
}
You need to use a double loop to compare all the values:
// start at 0, the first position of the array. Loop until the 2nd to last element
for (int i=0; i<n-1;i++)
{
// start this index at one higher than i. Since a+b == b+a, there's no need to
// add the later values in the array with the previous ones, we've already
// done that
for (int j=i+1; j<n; j++)
{
int sum = a[i]+a[j];
if (sum == givendata)
{
std::cout << a[i] << " + " << a[j] << " = " << givendata << std::endl;
}
}
}
Demonstration
Also see Why is "using namespace std;" considered bad practice?

Create randomly sized (within a certain range) arrays over many iterations

I am trying to create many arrays consisting of random numbers and of random size between the range of, say, 1 and 20 elements. My code works SOMETIMES.
I am using a random number between my desired range to determine the array size. If the first iteration produces an array size of value 10, say, then for some reason my code does not want to create any arrays of size larger than 10. Various arrays will be created (and the list of those arrays will be outputed) until a certain iteration produces a random number larger than 10. Then I get this error:
Array index out of range numbers->[11] valid upto numbers[9]
"numbers" is the name of the array. Here is the relevant portion of my code:
srand(time(0));
int j, flag = 0;
int temp;
int rand=1;
for(int t=0; t<50; t++)
{
int length = rand()% 20 + 1;
cout<<"length is " << length << endl;
int numbers[length];
for(int i = 0; i < length; i++)
{
numbers[i]=rand();
cout << numbers[i] << endl;
}
for(j=0; (j<=length); j++)
{
for (int i=0; i<(length-1); i++)
{
if(numbers[i+1]<numbers[i])
{
temp=numbers[i];
numbers[i]=numbers[i+1];
numbers[i+1]=temp;
flag++;
}
}
}
cout << "Number of Swaps : " << flag << endl;
}
As #Bob__ wrote, allocating variable length arrays is not C++ standard. It might work sometimes on specific compilers, but it may break on others.
But there are good alternatives. You can allocate dynamic memory with new. For instance:
int *array = new int[size];
array[0] = 3;
array[1] = 5;
cout << array[1];
delete [] array;
Don't forget to delete the memory with delete afterwards.
Or you could use vector<int>. It's a STL-container, that was made for exactly this purpose.
#include <vector>
using namespace std;
...
vector<int> vec(size);
vec[0] = 3;
vec[1] = 5;
cout << vec[1];
Variable Length Arrays are not in C++ standard, but only offered as extension by some compilers. I wouldn't trust them and you don't really need anything like that in your code.
You can declare your array outside the outer for loop as you know its max lenght:
#define MAXL 20
int numbers[MAXL];
for ...
int length = rand() % MAXL + 1;
...
Besides, if you are implementing a bubble sort I think that the condition of the inner i loop should be i < length - j
rand is used in two contexts. As a variable int rand and as a function std::rand(). I'd suggest to delete any using namespace std; but since the variable is not needed anyways you could as well delete int rand = 1;. Note that rand() is a C function. You may use it but IMHO std::rand() is more pure C++.
int numbers[length]; will not compile because length is a non-constant. Use std::vector<int> numbers(length); instead.
And that's about it.
#include <iostream>
#include <vector>
#include <time.h>
int main()
{
std::srand(time(0));
int j, flag = 0;
int temp;
for (int t = 0; t < 50; t++)
{
int length = std::rand() % 20 + 1;
std::cout << "length is " << length << std::endl;
std::vector<int> numbers(length);;
for (int i = 0; i < length; i++)
{
numbers[i] = std::rand();
std::cout << numbers[i] << std::endl;
}
for (j = 0; (j <= length); j++)
{
for (int i = 0; i < (length - 1); i++)
{
if (numbers[i + 1] < numbers[i])
{
temp = numbers[i];
numbers[i] = numbers[i + 1];
numbers[i + 1] = temp;
flag++;
}
}
}
std::cout << "Number of Swaps : " << flag << std::endl;
}
}

Int to Char array(part sums)

I have problem with "tab" output. My program is going to show part sums.
I want to save those part sums in tab array but it shows only first sum.
here is code I wrote:
const char numbers[] = { "1 2 3 4" };
cout << numbers << endl;
for (int i = 0; i < strlen(numbers); ++i)
{
if (numbers[i] != ' ') cout << numbers[i] << endl;
}
int sum = 0;
char tab[20];
for (int i = 0; i < strlen(numbers); ++i){
if (numbers[i] != ' ') {
sum += atoi(&numbers[i]);
_itoa_s(sum,&tab[i],sizeof(tab),10);
}
}
cout << tab;
_getch();
return 0;
How I can make it to show proper part sums like: 1 3 6 10
sizeof shows the size of the array in bytes, not the number of elements in the array.
Something like this will give you the number of elements:
int num_element = sizeof(numbers)/sizeof(numbers[0]);
Or a full solution:
const char numbers[] = { "1 2 3 4" };
int num_elements = sizeof(numbers)/sizeof(numbers[0]);
cout << numbers << endl;
for (int i = 0; i < num_elements; ++i)
{
if (numbers[i] != ' ') cout << numbers[i] << endl;
}
int sum = 0;
char tab[20];
for (int i = 0; i < num_elements; ++i){
if (numbers[i] != ' ') {
sum += atoi(&numbers[i]);
_itoa_s(sum,&tab[i],sizeof(tab),10);
}
}
cout << tab;
_getch();
return 0;
Although the above should work after replacing num_element into your for loops, I suggest you looking into a std::array or std::vector
Your code has several problems. The first one is that function atoi will return an error because is will consider all string starting from &numbers[i] till the terminating zero. The other problem is that this in expression
_itoa_s(sum,&tab[i],sizeof(tab),10);
using tab[i] is incorrect.
Try the following code.
#include <iostream>
#include <cstring>
#include <cctype>
#include <cstdio>
//...
const char numbers[] = { "1 2 3 4" };
char tab[20];
char *p = tab;
int sum = 0;
for ( size_t i = 0, n = std::strlen( numbers ); i < n; i++ )
{
if ( std::isdigit( numbers[i] ) )
{
sum += numbers[i] - '0';
p += std::sprintf( p, "%d ", sum );
}
}
std::cout << tab << std::endl;
At least I got output
1 3 6 10
Also it would be better to use std::istringstream instead of the for loop where you are extracting digits.
You are not retrieving the size of your arrays here.
Use SIZEOF_ARRAY to get the size of numbers in C.
But you tagged C++, so consider using std::array<> instead of a C-style array (it will expose the size of the array for you)
Firstly, cout << tab; prints only the first element.
Secondly, instead of writing the result to tab[i], create int cnt = 0; _itoa_s(sum,&tab[cnt],sizeof(tab),10); cnt++ By that way, you won't have empty characters in you tab array.
Thirdly, you can keep int tab[20], rather than to keep in char tab[].
Forthly, int num_elem = sizeof(numbers)/sizeof(numbers[0]);(as said above).

copy one array to another without duplicates C++

The problem is that, I have an array of 10 integers, having some duplicates. The task is to copy this array to another array of same size, but without duplicate values. That is, read one element from array1, compare it with all the elements in array2, if it's already in array2, just skip it or print that it's already in array2, go to second element of array1, and repeat the process.
Now, I've tried this but don't know where's the problem:
#include <iostream>
using namespace std;
int main()
{
int temp;
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
break;
}
}
array2[i] = array1[i-1];
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl;
system("pause");
}
array1 has 10 elements and array2 has 11, so right away the requirements haven't been met. Presumably, having 11 elements was a workaround for using incorrect index values in the for loops; the index should run from 0 to 9, not from 1 to 10.
When you add an element to the second array, you should only check it value against the elements that have already been added, not against the values in the entire array.
Finally, there's an underspecification. Once you've eliminated duplicates, you have fewer than 10 elements; array2 has 10 elements; what values should the extra elements have?
std::unique_copy is your friend:
http://en.cppreference.com/w/cpp/algorithm/unique_copy
remember to sort the source array first
In C++, break immediately ends one loop structure, and starts execution immediately after it. Thus, the line array2[i] = array1[i-1]; executes redardless of whether the inner for loop finds a duplicate. One solution is to set a variable indicating that the value is a duplicate:
int main() {
int temp;
bool isDuplicate; //added this line
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
isDuplicate=false;//added this line
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
isDuplicate=true; //added this line
break;
}
}
if(!isDuplicate) //added this line
array2[i] = array1[i-1];
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl; system("pause"); }
Alternatively (though many programmers would disagree with this practice) you could use a goto statement instead of a break statement:
int main()
{
int temp;
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
goto duplicate; //added this line
}
}
array2[i] = array1[i-1];
//added next line
duplicate:
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl;
system("pause");
}
You could use a std::set to ensure uniqueness for you.
http://en.cppreference.com/w/cpp/container/set
You have three approaches:
compare each element one by one (O(N^2) performance)
sort your reference array and use a binary search to determine if the element exists (O(N*lnN) performance)
create a lookup hash (O(1) performance)
I can see two main sources of problems in your code: 1) the break statement, as it is, does not solve the problem of differentiating between the case when duplicate is found, and when the element in array1 should be added to array2. 2) There is no counter which would store the number of elements inserted so far into array2, this way they could not be copied to array2 next to each other. The code which fixes both is:
#include <iostream>
using namespace std;
int main()
{
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[10];
int array2_elements_inserted = 0;
for(int i = 0; i < 10; i++)
{
int temp = array1[i];
bool isDuplicate = false;
for(int j = 0; j < array2_elements_inserted; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
isDuplicate = true;
break;
}
}
if (!isDuplicate)
{
array2[array2_elements_inserted] = temp;
++array2_elements_inserted;
}
}
for(int k = 0; k < array2_elements_inserted; k++)
cout << array2[k] << " " << endl;
// system("pause");
}
Output:
10
2
5
4
6
9
8
First of all, use dynamic containers. Especially have a look at those provide by
the standard library, e.g. std::vector. Second, you should use a set data structure
to keep track of the elements you have seen before, e.g., std::set.
Then it's just an iteration on the input array and appending new elements to the
output array.
Here's an example:
#include <vector>
#include <set>
#include <iostream>
int main() {
// define and print input data
std::vector<int> v1 = {10,2,5,4,10,5,6,9,8,10};
for (int i : v1)
std::cout << i << " ";
std::cout << "\n";
// this will soon contain the output data
std::vector<int> v2;
// a set to keep track of the already seen elements
std::set<int> set;
// iterate the input array using range-based for loop
for (int i : v1) {
// check for duplicates
if (set.find(i) == set.end()) {
// first occurrence, insert to set, append to output data
set.insert(i);
v2.push_back(i);
}
else {
// seen before, do nothing
}
}
// print output data
for (int i : v2)
std::cout << i << " ";
std::cout << "\n";
}
The output:
$ g++ test.cc -std=c++11 && ./a.out
10 2 5 4 10 5 6 9 8 10
10 2 5 4 6 9 8
For reference:
http://en.cppreference.com/w/cpp/container/vector
http://en.cppreference.com/w/cpp/language/range-for
http://en.cppreference.com/w/cpp/container/set
http://en.cppreference.com/w/cpp/container/set/find