I want a function that works.
I believe my logic is correct, thus my (vector out of range error) must be coming from the lack of familiarity and using the code correctly.
I do know that there is long code out there for this fairly simple algorithm.
Please help if you can.
Basically, I take the length as the "moving" window as it loops through j to the end of the size of the vector. This vector is filled with stock prices.
If the length equaled 2 for a 2 day moving average for numbers 1 2 3 4. I should be able to output 1.5, 2.5, and 3.5. However, I get an out of range error.
The logic is shown in the code. If an expert could help me with this simple moving average function that I am trying to create that would be great! Thanks.
void Analysis::SMA()
{
double length;
cout << "Enter number days for your Simple Moving Average:" << endl;
cin >> length;
double sum = 0;
double a;
while (length >= 2){
vector<double>::iterator it;
for (int j = 0; j < close.size(); j++){
sum = vector1[length + j - 1] + vector1[length + j - 2];
a = sum / length;
vector2.push_back(a);
vector<double>::iterator g;
for (g = vector2.begin(); g != vector2.end(); ++g){
cout << "Your SMA: " << *g;
}
}
}
}
You don't need 3 loops to calculate a moving average over an array of data, you only need 1. You iterate over the array and keep track of the sum of the last n items, and then just adjust it for each new value, adding one value and removing one each time.
For example suppose you have a data set:
4 8 1 6 9
and you want to calculate a moving average with a window size of 3, then you keep a running total like this:
iteration add subtract running-total output average
0 4 - 4 - (not enough values yet)
1 8 - 12 -
2 1 - 13 13 / 3
3 6 4 15 15 / 3
4 9 8 16 16 / 3
Notice that we add each time, we start subtracting at iteration 3 (for a window size of 3) and start outputting the average at iteration 2 (window size minus 1).
So the code will be something like this:
double runningTotal = 0.0;
int windowSize = 3;
for(int i = 0; i < length; i++)
{
runningTotal += array[i]; // add
if(i >= windowSize)
runningTotal -= array[i - windowSize]; // subtract
if(i >= (windowSize - 1)) // output moving average
cout << "Your SMA: " << runningTotal / (double)windowSize;
}
You can adapt this to use your vector data structure.
Within your outermost while loop you never change length so your function will run forever.
Then, notice that if length is two and closes.size() is four, length + j - 1 will be 5, so my psychic debugging skills tell me your vector1 is too short and you index off the end.
This question has been answered but I thought I'd post complete code for people in the future seeking information.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<double> vector1 { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
double length;
cout << "Enter number days for your Simple Moving Average:" << endl;
cin >> length;
double sum = 0;
int cnt = 0;
for (int i = 0; i < vector1.size(); i++) {
sum += vector1[i];
cnt++;
if (cnt >= length) {
cout << "Your SMA: " << (sum / (double) length) << endl;
sum -= vector1[cnt - length];
}
}
return 0;
}
This is slightly different than the answer. A 'cnt' variable in introduced to avoid an additional if statement.
Related
After providing an answer to a question here, I was testing this code that I edited and noticed some strange behavior:
#include <iostream>
#define MAX 100
using namespace std;
int main()
{
int size = 0;
int array[MAX];
int i, j;
int input;
cout << "Array: ";
for(i = 0; i < MAX; i++)
{
cin >> input;
if(input == -1)
break;
else
{
array[i] = input;
size++;
}
}
cout << "Size: " << size << "\n\n";
int left[size / 2];
int right[size / 2];
for(i = 0; i < size / 2; i++)
left[i] = array[i];
for(i = size / 2, j = 0; i < size; i++, j++)
right[j] = array[i];
cout << "Left: ";
for(i = 0; i < size / 2; i++)
cout << left[i] << ' ';
cout << '\n';
cout << "Right: ";
for(i = 0; i < size - size / 2; i++)
cout << right[i] << ' ';
cout << '\n';
return 0;
}
This code is supposed to split the array into two separate arrays. Somehow the output is wrong when these are the input:
1 2 3 4 5 6 7 8 9 -1
Left: 9 2 3 4
Right: 5 6 7 8 9
After debugging If the elements of left were printed like this:
for(i = size / 2, j = 0; i < size; i++, j++)
{
right[j] = array[i];
cout << left[0] << ' ';
}
cout << '\n';
It says that the value of left[0] is modified after the 5th iteration:
1 1 1 1 9
Left: 9 2 3 4
Right: 5 6 7 8 9
This only happens when the array size is 9. I haven't tested beyond 16 yet. I could fix the code so that it would have the correct size
int right[size - size / 2];
or use malloc() to adhere to the C++ Standard,
int *left = (int *) malloc(sizeof(*left) * n / 2);
int *right = (int *) malloc(sizeof(*left) * n / 2);
so that left wouldn't be affected, but that's not what I'm asking. Why does it only happen when splitting an array size of 9? Why was left[0] overwritten? Is this is a bug in g++ that should be reported or is the problem something else?
It says that the value of left[0] is modified after the 5th iteration:
That is your answer. The problem occurs in the fifth iteration over an array with four elements.
When size is odd, the calculation of size/2 rounds down. So the sum size/2 + size/2 is strictly less than size, yet your loops ensure that all size elements from the original array are assigned somewhere. Something has to be assigned to an unexpected location. We call this "undefined behavior", and whatever the compiler does at that point is correct according to the C++ standard. (Whatever happens, the compiler gets to blame your code for it.) It just happens that when size is 9, the compiler used left[0] as the location for right[4].
Behind the scenes, the left and right arrays are probably more-or-less adjacent in memory. The layout would have right[0] through right[size/2], then possibly some unused space (also known as "padding"), then left[0] through left[size/2]. When you access one-past the last element of right, you end up either in the unused space or in left[0]. When you overwrite the unused space, you see no symptoms since that space is otherwise unused. However, when you overwrite left[0] you definitely see a symptom.
Your compiler apparently uses padding to make sure the arrays are aligned to 4*sizeof(int). (Must be faster that way, as compilers rarely introduce waste without a reason. Still, I am surprised it's not 2*sizeof(int) instead.) That is, there is no padding when size/2 is a multiple of 4. If this guesswork is accurate, you should see this behavior when size is odd and size/2 is a multiple of 4; that is when size is one more than a multiple of 8, as in 9, 17, 25, 33, etc.
Given Question: Given n companies and m oil mines with values, design an algorithm to
distribute the sites among the companies in a fair manner, where the company getting the highest
total value of its assigned sites and the one getting the lowest total value is minimal. Your
algorithm should output this minimum difference. Note that oil mines sites assigned to each
company should be adjacent to each other, and that the number of mines m is always bigger than
or equal to the number of companies n
Sample Input: Input : n = 3, site values = [6, 10, 13, 2]
Output : 9 → for the assignment of [6] to company #1, [10] to company #2, and [13, 2]
to company #3, making the minimum difference (13+2) - 6 = 9
My attempt at solving:
Add all previous elements in array, so the new array becomes [6, 16, 29, 31].
Then, I form all possible solution arrays which are: note: 31 stays constant because it is the largest and I need to subtract the largest from the smallest
31, 29, 16
31, 29, 6
31, 16, 6
Then, I subtract all previous elements in array, so the new arrays become
2, 13, 16
2, 23, 6
15, 10, 6
Then I subtract the highest number from the lowest number in each array which would be:
16 - 2 = 14
23 - 2 = 21
15 - 6 = 9 // **answer**
I would pick the smallest difference which is 9
My question:
(1) Is there an easier way to solve this? As this seems like it a bit too complex and I'm just overthinking things. (2) How would I go about implementing generating all the possible combinations to the array? Should I use permutations? Recursion? This is the part that I'm stuck on the most, generating all possible solutions where 31 (in the example stays the same) and I select only 2 out of the 3 other elements in the array.
void Func (int n, int m, int prosValues[], int solArray[], bool summed) {
if (!summed) {
for (int i = 1; i < m; i++) {
prosValues[i] = prosValues[i] + prosValues[i-1];
}
solArray[0] = prosValues[m-1];
summed = true;
}
// generate all possible combinations as shown in example
}
Interesting problem! I chose a different approach to solve this. I don't know, if it is more elegant, but I spend some time thinking about it and wanted to share my solution at least.
I make the following convention for the site assignment:
The indices in the site array describe the start index for site values, from which the site values are assigned to that site. Let's make it clearer using two examples.
values = {2,6,3,8,2,1}
sites1 = {0,1,2}
sites2 = {0,2,5}
The two site distributions site1 and site2 will assign the site values as follows:
distribution for site1:
0: 2
1: 6
2: 3, 8, 2, 1
distribution for site2:
0: 2, 6
1: 3, 8
2: 2, 1
This way we can iterate through all combinations by shifting the indices in sites up. In the example for 6 site values, we would get:
{0,1,2}
{0,1,3}
{0,1,4}
{0,1,5}
{0,2,3}
{0,2,4}
{0,2,5}
{0,3,4}
{0,3,5}
{0,4,5}
{1,2,3}
{1,3,4}
{1,3,5}
.
.
.
{3,4,5}
For all these site distributions we sum up the site values for each site, calculate the maximum difference and pick the distribution with the smallest difference.
Putting it all together, here is the code I came up with:
#include <iostream>
#include <algorithm>
int calc_diff(int m, int n, int* values, int* sites)
{
// stores the sum of values for each site
int *result = new int[n] {0};
// iterate through all site values
for (int j = 0; j < m; j++)
{
// find the correct site index to which the value is assigned
int index = 0;
for (int i = n-1; i >= 0; i--)
{
if (j >= sites[i])
{
index = i;
break;
}
}
// sum up the site vaues
result[index] += values[j];
// debug print
// std::cout << index << ":\t" << result[index] << std::endl;
}
// print the site results
std::cout << "result:\t";
for (int i = 0; i < n; i++)
std::cout << result[i] << "\t";
// get the highest difference
auto min = std::min_element(result, result+n);
auto max = std::max_element(result, result+n);
int diff = *max - *min;
delete[] result;
return diff;
}
int main()
{
int n = 3;
int m = 6;
auto values = new int[m] {2,6,3,8,2,1};
auto sites = new int[n] {0,1,2};
// start index of the first site
int start_index = 0;
// current best difference (some really high number)
int max = 100000000;
// the current best solution
auto best = new int[n];
bool end = false;
while(!end)
{
std::cout << "sites:\t";
for (int i = 0; i < n; i++)
std::cout << sites[i] << "\t";
std::cout << std::endl;
// calculate the maximal difference of the current site distribution
auto diff = calc_diff(m, n, values, sites);
std::cout << "\nmax diff:\t" << diff << std::endl << std::endl;
// if we find a better solution than the current best, we store it as new best solution
if (diff < max)
{
max = diff;
memcpy(best, sites, n*sizeof(int));
}
// calculate new site distribution
int index = 0;
for (int i = n-1; i >= 0; i--)
{
// get the current index
index = sites[i];
// can we still move the index one position up?
// the index of the last site should not exceed m-1
// the index of all other sites should be less than the index of the next site
if ((i == n-1 && index < m-1) ||
(i < n-1 && i > 0 && index < sites[i+1]-1))
{
// increase the index of the current site
sites[i]++;
break;
}
// all site index have moved to maximum position?
// (we iterated through all indices (so i=0) and moved none of them)
if (i == 0)
{
// increase the start index of the first site
start_index++;
// reset the indices by starting from the current start_index
for (int j = 1; j < n; j++)
{
sites[j] = start_index + j;
// if we exceed the numbers of site values, we can stop the loop
if (sites[j] >= m)
end = true;
}
}
}
}
// print best soluition
std::cout << "Best distribution: ";
for (int i = 0; i < n; i++)
std::cout << best[i] << " ";
delete[] sites;
delete[] values;
delete[] best;
}
So I am working on a very "basic" problem for my c++ class and have encountered some errors. The problem is this
An interesting problem in number theory is sometimes called the “necklace problem.” This problem begins with two single-digit numbers. The next number is obtained by adding the first two numbers together and saving only the ones-digit. This process is repeated until the “necklace” closes by returning to the original two numbers. For example, if the starting numbers are 1 and 8, twelve steps are required to close the “necklace”:
18976392134718
Write a program that asks the user for two starting numbers, and then displays the sequence and the number of steps taken. The program output should look similar to:
Enter first number: 1
Enter ssecond number: 8
18976392134718
Your numbers required 12 steps.
What I have done is this:
` #include <iostream>
using namespace std;
int necklace(){
int firstNumber, secondNumber, total = 0, counter = 10, sumOfTwo, tempOne, tempTwo, count;
// 2 single digit numbers
// add first two numbers and save only one digit
// process keeps going until original numbers are found
cout << "Enter the first number: \n";
cin >> firstNumber;
cout << "Enter the second number: \n";
cin >> secondNumber;
sumOfTwo = firstNumber + secondNumber;
while (sumOfTwo >= 10){
sumOfTwo /= 10;
}
int numbersArray[] = {firstNumber, secondNumber, sumOfTwo};
for(int i = 0; i <= 20; i++){
tempOne = numbersArray[i + 1];
tempTwo = numbersArray[i + 2];
sumOfTwo = tempOne + tempTwo;
while (sumOfTwo >= 10){
sumOfTwo %= 10;
}
numbersArray[i + 3] = sumOfTwo;
total++;
if(tempOne == firstNumber && tempTwo == secondNumber){
break;
}
}
for(int i = 0; i < sizeof(numbersArray); i++){
cout << numbersArray[i];
}
cout << endl << "It took " << total << " steps to finish. \n";
return total;
}
int main() {
necklace();
}
`
The problem I am getting is that it will print out all the numbers except the original 2, for example if I use the example with 1 and 8, it will print out 189763921347 and then crash, when it is supposed to print out 18976392134718 with the 1 and 8 at the end of it. Any suggestions? Thanks!
int numbersArray[] = {firstNumber, secondNumber, sumOfTwo};
with three elements on the right hand side makes it an array of size 3. Meaning with indexes 0, 1 and 2.
The use of higher indexes will result in Undefined Behaviour (UB).
On the other hand:
for(int i = 0; i <= 20; i++){
tempOne = numbersArray[i + 1];
tempTwo = numbersArray[i + 2];
[...]
numbersArray[i + 3] = sumOfTwo;
with i up to 20 (included) indexes this very same array from 0 to 23 for the last line!
Next:
for(int i = 0; i < sizeof(numbersArray); i++){
sizeof(numbersArray) returns the size in bytes of the array:
sizeof(numbersArray) = 3 * sizeof(int)
Higher than 3, the real size of the array.
But, if you intend to print the values but not store them, you don't need an array. You just need to "exchange" the values like:
one two // beginning of loop
___|
| __ new_digit
| |
v v
one two // end of loop
I want to create a matrix of 5 lines and 5 columns which contains values from 1 to 9. The following programs displays numbers from 1 to 25 instead, when I input 5 to the program..
#include <iostream>
using namespace std;
int a[20][20], n, x = 0;
int main()
{
cout << "n=";
cin >> n;
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
{
a[i][j] = x+1;
x = x+1;
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
cout << a[i][j] << " ";
cout << endl;
}
}
I'm a c++ beginner, so maybe it's simple to do but i don't know how to make it show values from 1 to 9. This is the matrix I except:
1 2 3 4 5
6 7 8 9 1
2 3 4 5 6
7 8 9 1 2
3 4 5 6 7
There are some issues in your code.
C arrays or STL containers?
First off, a your matrix may only hold matrices as big as 20x20. Your program will silently fail if you enter n bigger than 20, because you will access memory out of bounds; which causes an undefined behavior (see other common UB cases here).
You may want to use a dynamic size array - A good way to achieve this is to use std::vector. Unfortunately, this isn't as comfortable to use as a C-style array with two dimensions - you can achieve the same access syntax using a std::vector<std::vector<int>>, but this is not very efficient (see this answer if you are interested why) nor quite comfortable.
The Boost C++ library provides a multidimensional array library. Once you get experienced enough, you may find an use in it.
<= or <? 0-index or 1-indexed?
Many programming languages today uses 0-indexing for arrays. This means the first element of the array is located at index 0, not 1. Some languages, such as Lua, doesn't do this.
This means you should iterate i and j from 0 to n. This also means n is excluded, so you should use <, not <=.
Filling the matrix with numbers from 1 to 9
Your code doesn't do anything so you get numbers from 1 to 9 - it only fills the matrix with numbers from 1 to n * n. You could change this using an if clause to set x every time it goes above 9:
if (x > 9) { x = 0; } // x = 0 because it will be 1 on the next iteration
That being said, there is more convenient, as #PMar's answer says. The modulo operator % will do the task as well.
a[i][j] = (x % 9) + 1;
x = (x % 9) + 1;
This way, you will get every number from 1 to 9.
Now, you can also do another cleanup: Why are you calculating x's next value, and only then setting it? You could assign the new x value before the assignment to your matrix's cell. This allows having clearer code, with less copy pasting, which implies better maintainability.
x = (x % 9) + 1;
a[i][j] = x;
Another code quality consideration
I cannot say if your original code source was indented like your question (before it was edited), but you should really indent your code, for the future you and other people that will have to read your code. It allows for much better readability.
Same goes for different parts of your code : Add some space! It only can get more readable if you make a clear distinction between even just expressions.
You need to use the modulus operator (%). If you want the values in the matrix to be as you have computed them, but only need to change the display, you would output the matrix values as follows:
cout << (a[i][j] % 10) << " ";
If you want the one-digit values to be in the matrix itself, you would instead change the increment on 'x' to the following:
x = (x+1) % 10;}
#include <iostream>
int main()
{
int a[5][5];
int x = 1;
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
if(x > 9)
x = 1;
a[i][j] = x;
x++;
}
}
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 5; j++)
{
if(a[i][j] < 10)
std::cout << " ";
std::cout << a[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
return 0;
}
I have an assignment in which I am supposed to
1.) Read in 2 char arrays of numbers
2.) add together the arrays, performing carry addition, carrying the tens place
3.) print out the newly added array.
I am also supposed to print an error if I need to carry on the last digit of the array (overflow)
so something like 99999999999999999999 +
1 =
________________________
ERROR
That's the part I'm having trouble with.
The above outputs something like "99999999999999999:0" so I have no idea what's going wrong.
I'll post my code, but please be nice :( I know it certainly isn't the most efficient, but I'm just trying to lay things out in a way that is easy for my brain to understand right now.
And yes, I HAVE to use char arrays. I guess it's to help us understand the ascii table.
#include <iostream>
using namespace std;
void InitNumber(char[]);
int AddArrays(char first[], char second[], char combined[]);
void OutputNumber (char[]);
const int LENGTH = 20; // global variable
int main()
{
char set1[LENGTH];
char set2[LENGTH];
char sum[LENGTH];
InitNumber (set1);
InitNumber (set2);
if(AddArrays (set1, set2, sum)) {
cout << "overflow!" << endl;
}
OutputNumber(sum);
}
void InitNumber (char list[])
{
int numberOfDigits;
cout << "Please enter the number of digits in the number: ";
cin >> numberOfDigits;
cout << "Please enter the digits in the number with the LEAST significant first: ";
for (int i = 0; i < numberOfDigits; i++) {
cin >> list [i];
}
for (int l=(numberOfDigits); l < LENGTH; l++) {
list [l] = '0';
}
}
int AddArrays(char first[], char second[], char combined[])
{
for (int h = 0; h < LENGTH; h++)
combined[h]= '0';
int overflow = 0;
for (int i = 0; i < LENGTH; i++) {
int currentSum = (first[i]-'0' + second[i]-'0');
cout << "currentSum = " << currentSum << endl;
if(currentSum / 10 == 0 )
combined[i] += currentSum;
else if (currentSum/10 !=0) {
if (i == LENGTH-1 && currentSum/10 !=0){
overflow = 1;
}
else{
combined [i] += currentSum%10;
cout << "current i: " << combined[i] << endl;
combined [i+1] += currentSum/10;
cout << "current i+1: " << combined[i+1] << endl;
}
}
}
return overflow;
}
void OutputNumber(char arrayOut[])
{
for (int l=LENGTH - 1; l >= 0; l--)
cout << arrayOut[l];
}
working input
input
6
1 2 3 4 5 6
7
1 2 3 4 5 6 7
output
00000000000008308642
Not-working output
input
20
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
1
1
output
999999999999999999:0
I'm going to reproduce small parts of your inner loop where you are carrying out the addition, in order to explain why your overflow detection is broken.
for (int i = 0; i < LENGTH; i++) {
int currentSum = (first[i]-'0' + second[i]-'0');
if(currentSum / 10 == 0 )
combined[i] += currentSum;
Here you're adding the corresponding pair of digits from the two numbers you're adding, and checking (in your particular style) if they overflowed. Try to remember this part, it's important. In order to check for overflow, you're only checking the result of adding the pair of digits from the two large numbers you're adding.
else if (currentSum/10 !=0) {
This is a completely useless check. You can only get here if the division is known to produce a non-zero result. This if() can be removed completely. Now, the relevant part of your code is
combined [i] += currentSum%10;
combined [i+1] += currentSum/10;
Do you see the problem yet?
Your approach is, once overflow is detected, is to increment the next higher order digit in the result.
Unfortunately, on the next loop iteration, in order to check for carry over, you're just checking the sum of the next corresponding digit pair, from the two large numbers you're adding. The carry-over you're saving here is going to get completely ignored.
Say your numbers are two digits long max, rather than 20, and you entered the numbers 99 and 1.
On the first iteration, you'll add 9 and 1, save 0 as the first digit, and add 1 to the second digit in the sum.
On the second iteration, you'll add 9 and 0, and, given your logic above, conclude that nothing overflowed.