I've been trying to put the total income calculated for that particular day into an array. So that at the end so that I can later total all the values in the array for a grand total.
I've got 2 arrays so far that have the demand for pies and number of apples picked. To calculate the income from pies, apple trays and total income for that day I've put it into a for loop.
So far I've got this: (this is for inputting the calculated value in the array)
float total[30];
int i, incmPie, numPie, rApples, applesLeft, FTray, incmFTray, PFTray;
float totalincm, incmApples, incmRApples, incmPFTray, totalincome;
**float total[30];**
int pieDemand[30]={4, 4, 2, 7, 1, 6, 7, 8, 9, 12, 2,13,13, 5, 3, 9, 9, 9, 8, 7,
12, 1, 3, 3,10,12, 3, 6, 9, 3};
int applesPicked[30]={330,123,110,245,321,999,0,100,77,89,100,200,300,390,700,20,701,6,800,90,
600,45,690,700,719,790,800,1000,66,666};
int date[30] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30};
printf("\n==============================================================================");
printf("\n Date Income from Pie Income from Apples Total income");
printf("\n==============================================================================");
for (i = 0 ; i <30; i++)
{
if (applesPicked[i] == 0)
{
incmPie = 0;
incmApples = 0;
totalincm = 0;
**total[i] = totalincm;**
}
else if (applesPicked[i] < (pieDemand[i]*8))
{
numPie = applesPicked[i]/8;
incmPie = numPie * 14;
rApples = applesPicked[i]%8;
incmRApples = rApples * 0.5;
incmApples = incmRApples;
totalincm = incmPie + incmRApples;
**total[i] = totalincm;**
}
else
{
incmPie = pieDemand[i] * 14;
applesLeft = applesPicked[i] - (pieDemand[i]*8);
FTray = applesLeft/20;
incmFTray = FTray * 12;
PFTray = applesLeft%20;
incmPFTray = PFTray * 0.5;
incmApples = incmFTray + incmPFTray;
totalincm = incmApples + incmPie;
**total[i] = totalincm;**
}
**totalincome** = total[1] + total[2] + total[3] + total[4] + total[5] + total[6] + total[7] + total[8] + total[9] + total[10] + total[11] + total[12] + total[13] + total[14] + total[15] + total[16] + total[17] + total[18] + total[19] + total[20] + total[21] + total[22] + total[23] + total[24] + total[25] + total[26] + total[27] + total[28] + total[29] + total[30];
printf("\n"); //prints onto the next line.
printf("%d/04/2013",date[i]); // prints the date.
printf("%15d", incmPie); // prints the income from pies for each value in the arrays.
printf("%20g", incmApples); // prints the income from apples from both full trays and remaining apples for each value in the arrays.
printf("%28g", totalincm);
}
printf("\n==============================================================================");
**printf("\n Total income for the entire month: $%g", totalincome);**
printf("\n------------------------------------------------------------------------------");
_getch();
}
and i'm using this code to sum the total of the array:
totalincome = total[1] + total[2] + ... + total[30];
Any help will be appreciated! :)
In C++ (almost all programming languages), array index starts at 0, not 1! Check out Zero-based numbering for more info.
Change it to
totalincome = total[0] + total[1] + ... + total[29];
Or simply, to make your life much easier, use a loop:
totalincome = 0;
for (int i = 0; i < sizeof(total)/sizeof(total[0]); ++i)
totalincome += total[i];
totalincome = 0;
for (int i = 0; i < sizeof(total)/sizeof(total[0]); ++i)
totalincome += total[i];
For static arrray, this will work. If the array is dynamically allocated or passed as a pointer, you have to keep track of the number of elements.
totalincome = 0;
for (int i = 0; i < numelements; ++i)
totalincome += total[i];
You need to put totalincome out of the loop.
Related
I'm trying to figure out, how can I calculate fft row by row of the following matrix (stored as an array) using fftw3:
double signal[9] = {
1, 2, 3,
4, 5, 6,
7, 8, 9
}
to obtain the matrix with rows (pseudo-code)
fft([signal[0], signal[1], signal[2]])
fft([signal[3], signal[4], signal[5]])
fft([signal[6], signal[7], signal[8]])
I can check the result using Python just applying np.fft.fft([[1, 2, 3], [4, 5, 6], [7, 8, 9]], axis=1) and I want to get the same result with fftw3.
My code:
#include <fftw3.h>
#include <iostream>
int main()
{
// it is needed to compute fft row-by-row of the following matrix
double signal[9] {
1, 2, 3,
4, 5, 6,
7, 8, 9
}; // 3x3 matrix
// so that the output will have the form (pseudo-code)
// fft(signal[0], signal[1], signal[2])
// fft(signal[3], signal[4], signal[5])
// fft(signal[6], signal[7], signal[8])
fftw_complex result[9]{ };
// prepare parameters
int rank = 1;
int n[] = { 3 };
int howmany = 3;
int idist = 3;
int odist = 3;
int istride = 1;
int ostride = 1;
auto plan_ = fftw_plan_many_dft_r2c(
rank, // 1D problem
n, // 1D transforms of length n[0] = 3
howmany, // 3 1D transforms
signal, // input matrix (array)
NULL, // will be assigned to n
istride, // distance between two elements in the same row
idist, // distance between the first elements of neighboring rows
result, // output
NULL, // will be assigned to n
ostride, // distance between two elements in the same row
odist, // distance between the firsn elements of neighboring rows
FFTW_ESTIMATE
);
fftw_execute(plan_);
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
std::cout << result[i * 3 + j][0] << " + 1j*" << result[i * 3 + j][1] << '\t';
}
std::cout << '\n';
}
fftw_destroy_plan(plan_);
return 0;
}
The corresponding explanations are in the code. Python gives the following answer:
array([[ 6. +0.j , -1.5+0.8660254j, -1.5-0.8660254j],
[15. +0.j , -1.5+0.8660254j, -1.5-0.8660254j],
[24. +0.j , -1.5+0.8660254j, -1.5-0.8660254j]])
My code gives the following
6 + 1j*0 -1.5 + 1j*0.866025 0 + 1j*0
15 + 1j*0 -1.5 + 1j*0.866025 0 + 1j*0
24 + 1j*0 -1.5 + 1j*0.866025 0 + 1j*0
I see that the output almost the same as with Python, but third elements of each row are zeros. Can someone help me?
Thank you.
I have an array of numbers with length L, and I have to make the program check the sums of every array element with its preceding and following neighbors.
So, for example, if I have the array being {1, 2, 3}, the output for the 2nd element should be 6 because 1 + 2 + 3 = 6 and they are all neighbors.
If the chosen element is the first element in the array, its preceding neighbor is the last element of the array, and if the element is the last element in the array, the following neighbor is the first element of the array. So, in the {1, 2, 3} example, no matter what number you check, you always get 6, but if it were {1, 2, 3, 4} instead, the answer for the 3rd element would be 9 because 3 + 2 + 4 = 9.
I hope you understood how it should work.
The problem I am getting is that the output is out of control. I tried to check the array itself and it is completely normal. In the {1, 2, 3} example, I get an output of 7208681 and I don't know why.
#include <iostream>
using namespace std;
int main()
{
int total;
cin >> total;
int Bush[total]; //array of numbers
int temp, output = 0; //output variable and a container for the last resurt a.k.a temp
for (int i = 0; i <= total - 1; i++)
{
cin >> Bush[i]; //inputting the array elements
}
for (int i = 0; i < total; i++)
{
if (i == 0)
output = Bush[i] + Bush[i + 1] + Bush[total]; //checking if the loop checks the first number
if (i == total - 1)
output = Bush[i] + Bush[0] + Bush[i - 1]; //checking if the loop checks the first number
temp = output; //assigning the temp value to the current output value
output = Bush[i] + Bush[i + 1] + Bush[i - 1]; //assigning a new output value
if (temp > output)
output = temp; //checking values
}
cout << output << endl; //outputting
return 0;
}
When i = 0, the expression Bush[i-1] results in accessing an invalid location of the array (- 1).
Similarly, when i = total - 1 (last index of iteration), the expression Bush[i+1] gives you an index of total which is out of bounds of the array.
The last element of Bush is at index total -1, but you are accessing Bush[total] when i==0
At the end, there are many mistakes in your code, nonetheless, the problem with the if/else structure.
I would suggest you to use another inner loop, based on module operator that simplify the code a lot:
int max = 0;
for(int i = 0; i<total; i++)
{
output = Bush[i] + Bush[(i+1)%total] + Bush[(i-1+total)%total];
if(max < output) max = output;//checking the max
}
cout<<max<<endl;//outputting
that does the operation you required.
Hope this may help.
I think the below code would work
int main()
{
int total;
cout << "Enter Number of Elements " << endl;
cin>>total;
int Bush[total];//array of numbers
int temp = 0, output = INT_MIN; //output variable and a container for the last resurt a.k.a temp
cout << "Enter the Elements " << endl;
for(int i = 0; i<=total - 1; i++)
{
cin>>Bush[i];//inputting the array elements
}
for(int i = 0; i<total; i++)
{
if(i == 0)
temp = Bush[i] + Bush[i+1] + Bush[total -1];//checking if the loop checks the first number
else if(i == total - 1)
temp = Bush[i] + Bush[0] + Bush[i-1];//checking if the loop checks the first number
else
temp = Bush[i] + Bush[i+1] + Bush[i-1]; //assigning the temp value to the current output value
output = (temp > output)?temp:output;
}
cout<<output<<endl;//outputting
return 0;
}
I have a problem:
You are given a sequence, in the form of a string with characters ‘0’, ‘1’, and ‘?’ only. Suppose there are k ‘?’s. Then there are 2^k ways to replace each ‘?’ by a ‘0’ or a ‘1’, giving 2^k different 0-1 sequences (0-1 sequences are sequences with only zeroes and ones).
For each 0-1 sequence, define its number of inversions as the minimum number of adjacent swaps required to sort the sequence in non-decreasing order. In this problem, the sequence is sorted in non-decreasing order precisely when all the zeroes occur before all the ones. For example, the sequence 11010 has 5 inversions. We can sort it by the following moves: 11010 →→ 11001 →→ 10101 →→ 01101 →→ 01011 →→ 00111.
Find the sum of the number of inversions of the 2^k sequences, modulo 1000000007 (10^9+7).
For example:
Input: ??01
-> Output: 5
Input: ?0?
-> Output: 3
Here's my code:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <math.h>
using namespace std;
void ProcessSequences(char *input)
{
int c = 0;
/* Count the number of '?' in input sequence
* 1??0 -> 2
*/
for(int i=0;i<strlen(input);i++)
{
if(*(input+i) == '?')
{
c++;
}
}
/* Get all possible combination of '?'
* 1??0
* -> ??
* -> 00, 01, 10, 11
*/
int seqLength = pow(2,c);
// Initialize 2D array of integer
int **sequencelist, **allSequences;
sequencelist = new int*[seqLength];
allSequences = new int*[seqLength];
for(int i=0; i<seqLength; i++){
sequencelist[i] = new int[c];
allSequences[i] = new int[500000];
}
//end initialize
for(int count = 0; count < seqLength; count++)
{
int n = 0;
for(int offset = c-1; offset >= 0; offset--)
{
sequencelist[count][n] = ((count & (1 << offset)) >> offset);
// cout << sequencelist[count][n];
n++;
}
// cout << std::endl;
}
/* Change '?' in former sequence into all possible bits
* 1??0
* ?? -> 00, 01, 10, 11
* -> 1000, 1010, 1100, 1110
*/
for(int d = 0; d<seqLength; d++)
{
int seqCount = 0;
for(int e = 0; e<strlen(input); e++)
{
if(*(input+e) == '1')
{
allSequences[d][e] = 1;
}
else if(*(input+e) == '0')
{
allSequences[d][e] = 0;
}
else
{
allSequences[d][e] = sequencelist[d][seqCount];
seqCount++;
}
}
}
/*
* Sort each sequences to increasing mode
*
*/
// cout<<endl;
int totalNum[seqLength];
for(int i=0; i<seqLength; i++){
int num = 0;
for(int j=0; j<strlen(input); j++){
if(j==strlen(input)-1){
break;
}
if(allSequences[i][j] > allSequences[i][j+1]){
int temp = allSequences[i][j];
allSequences[i][j] = allSequences[i][j+1];
allSequences[i][j+1] = temp;
num++;
j = -1;
}//endif
}//endfor
totalNum[i] = num;
}//endfor
/*
* Sum of all Num of Inversions
*/
int sum = 0;
for(int i=0;i<seqLength;i++){
sum = sum + totalNum[i];
}
// cout<<"Output: "<<endl;
int out = sum%1000000007;
cout<< out <<endl;
} //end of ProcessSequences method
int main()
{
// Get Input
char seq[500000];
// cout << "Input: "<<endl;
cin >> seq;
char *p = &seq[0];
ProcessSequences(p);
return 0;
}
the results were right for small size input, but for bigger size input I got time CPU time limit > 1 second. I also got exceeded memory size. How to make it faster and optimal memory use? What algorithm should I use and what better data structure should I use?, Thank you.
Dynamic programming is the way to go. Imagine You are adding the last character to all sequences.
If it is 1 then You get XXXXXX1. Number of swaps is obviously the same as it was for every sequence so far.
If it is 0 then You need to know number of ones already in every sequence. Number of swaps would increase by the amount of ones for every sequence.
If it is ? You just add two previous cases together
You need to calculate how many sequences are there. For every length and for every number of ones (number of ones in the sequence can not be greater than length of the sequence, naturally). You start with length 1, which is trivial, and continue with longer. You can get really big numbers, so You should calculate modulo 1000000007 all the time. The program is not in C++, but should be easy to rewrite (array should be initialized to 0, int is 32bit, long in 64bit).
long Mod(long x)
{
return x % 1000000007;
}
long Calc(string s)
{
int len = s.Length;
long[,] nums = new long[len + 1, len + 1];
long sum = 0;
nums[0, 0] = 1;
for (int i = 0; i < len; ++i)
{
if(s[i] == '?')
{
sum = Mod(sum * 2);
}
for (int j = 0; j <= i; ++j)
{
if (s[i] == '0' || s[i] == '?')
{
nums[i + 1, j] = Mod(nums[i + 1, j] + nums[i, j]);
sum = Mod(sum + j * nums[i, j]);
}
if (s[i] == '1' || s[i] == '?')
{
nums[i + 1, j + 1] = nums[i, j];
}
}
}
return sum;
}
Optimalization
The code above is written to be as clear as possible and to show dynamic programming approach. You do not actually need array [len+1, len+1]. You calculate column i+1 from column i and never go back, so two columns are enough - old and new. If You dig more into it, You find out that row j of new column depends only on row j and j-1 of the old column. So You can go with one column if You actualize the values in the right direction (and do not overwrite values You would need).
The code above uses 64bit integers. You really need that only in j * nums[i, j]. The nums array contain numbers less than 1000000007 and 32bit integer is enough. Even 2*1000000007 can fit into 32bit signed int, we can make use of it.
We can optimize the code by nesting loop into conditions instead of conditions in the loop. Maybe it is even more natural approach, the only downside is repeating the code.
The % operator is, as every dividing, quite expensive. j * nums[i, j] is typically far smaller that capacity of 64bit integer, so we do not have to do modulo in every step. Just watch the actual value and apply when needed. The Mod(nums[i + 1, j] + nums[i, j]) can also be optimized, as nums[i + 1, j] + nums[i, j] would always be smaller than 2*1000000007.
And finally the optimized code. I switched to C++, I realized there are differences what int and long means, so rather make it clear:
long CalcOpt(string s)
{
long len = s.length();
vector<long> nums(len + 1);
long long sum = 0;
nums[0] = 1;
const long mod = 1000000007;
for (long i = 0; i < len; ++i)
{
if (s[i] == '1')
{
for (long j = i + 1; j > 0; --j)
{
nums[j] = nums[j - 1];
}
nums[0] = 0;
}
else if (s[i] == '0')
{
for (long j = 1; j <= i; ++j)
{
sum += (long long)j * nums[j];
if (sum > std::numeric_limits<long long>::max() / 2) { sum %= mod; }
}
}
else
{
sum *= 2;
if (sum > std::numeric_limits<long long>::max() / 2) { sum %= mod; }
for (long j = i + 1; j > 0; --j)
{
sum += (long long)j * nums[j];
if (sum > std::numeric_limits<long long>::max() / 2) { sum %= mod; }
long add = nums[j] + nums[j - 1];
if (add >= mod) { add -= mod; }
nums[j] = add;
}
}
}
return (long)(sum % mod);
}
Simplification
Time limit still exceeded? There is probably better way to do it. You can either
get back to the beginning and find out mathematically different way to calculate the result
or simplify actual solution using math
I went the second way. What we are doing in the loop is in fact convolution of two sequences, for example:
0, 0, 0, 1, 4, 6, 4, 1, 0, 0,... and 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,...
0*0 + 0*1 + 0*2 + 1*3 + 4*4 + 6*5 + 4*6 + 1*7 + 0*8...= 80
The first sequence is symmetric and the second is linear. It this case, the sum of convolution can be calculated from sum of the first sequence which is = 16 (numSum) and number from second sequence corresponding to the center of the first sequence, which is 5 (numMult). numSum*numMult = 16*5 = 80. We replace the whole loop with one multiplication if we are able to update those numbers in each step, which fortulately seems the case.
If s[i] == '0' then numSum does not change and numMult does not change.
If s[i] == '1' then numSum does not change, only numMult increments by 1, as we shift the whole sequence by one position.
If s[i] == '?' we add original and shiftet sequence together. numSum is multiplied by 2 and numMult increments by 0.5.
The 0.5 means a bit problem, as it is not the whole number. But we know, that the result would be whole number. Fortunately in modular arithmetics in this case exists inversion of two (=1/2) as a whole number. It is h = (mod+1)/2. As a reminder, inversion of 2 is such a number, that h*2=1 modulo mod. Implementation wisely it is easier to multiply numMult by 2 and divide numSum by 2, but it is just a detail, we would need 0.5 anyway. The code:
long CalcOptSimpl(string s)
{
long len = s.length();
long long sum = 0;
const long mod = 1000000007;
long numSum = (mod + 1) / 2;
long long numMult = 0;
for (long i = 0; i < len; ++i)
{
if (s[i] == '1')
{
numMult += 2;
}
else if (s[i] == '0')
{
sum += numSum * numMult;
if (sum > std::numeric_limits<long long>::max() / 4) { sum %= mod; }
}
else
{
sum = sum * 2 + numSum * numMult;
if (sum > std::numeric_limits<long long>::max() / 4) { sum %= mod; }
numSum = (numSum * 2) % mod;
numMult++;
}
}
return (long)(sum % mod);
}
I am pretty sure there exists some simple way to get this code, yet I am still unable to see it. But sometimes path is the goal :-)
If a sequence has N zeros with indexes zero[0], zero[1], ... zero[N - 1], the number of inversions for it would be (zero[0] + zero[1] + ... + zero[N - 1]) - (N - 1) * N / 2. (you should be able to prove it)
For example, 11010 has two zeros with indexes 2 and 4, so the number of inversions would be 2 + 4 - 1 * 2 / 2 = 5.
For all 2^k sequences, you can calculate the sum of two parts separately and then add them up.
1) The first part is zero[0] + zero[1] + ... + zero[N - 1]. Each 0 in the the given sequence contributes index * 2^k and each ? contributes index * 2^(k-1)
2) The second part is (N - 1) * N / 2. You can calculate this using a dynamic programming (maybe you should google and learn this first). In short, use f[i][j] to present the number of sequence with j zeros using the first i characters of the given sequence.
There are a lot of posts in this forum for finding largest sum contiguous subarray. However, a small variation of this problem is, the sub array should at least have two elements.
For example, for the input [-2, 3, 4, -5, 9, -13, 100, -101, 7] the below code gives 100. But, with the above restriction, it will be 98 with sub array [3, 4, -5, 9 , -13, 100]. Can someone help me do this? I could not get a proper logic for this.
#include<stdio.h>
int maxSubArraySum(int a[], int size)
{
int max_so_far = 0, max_ending_here = 0;
int i;
for(i = 0; i < size; i++)
{
max_ending_here = max_ending_here + a[i];
if(max_ending_here < 0)
max_ending_here = 0;
if(max_so_far < max_ending_here)
max_so_far = max_ending_here;
}
return max_so_far;
}
/*Driver program to test maxSubArraySum*/
int main()
{
int a[] = {-2, 3, 4, -5, 9, -13, 100, -101, 7};
int n = sizeof(a)/sizeof(a[0]);
int max_sum = maxSubArraySum(a, n);
printf("Maximum contiguous sum is %d\n", max_sum);
getchar();
return 0;
}
Update 1:
Made a change according to starrify but I do not get what I'm expecting. It gives 183 instead of 98.
#include<stdio.h>
const int size = 9;
int maxSubArraySum(int a[])
{
int max_so_far = 0;
int i;
int max_ending_here[size];
int sum_from_here[size];
max_ending_here[0] = a[0];
//sum_from_here[0] = a[0] + a[1];
for (i = 1; i < size; i++)
{
max_ending_here[i] = max_ending_here[i-1] + a[i];
sum_from_here[i] = a[i-1] + a[i];
if (max_so_far < (max_ending_here[i] + sum_from_here[i]))
max_so_far = max_ending_here[i] + sum_from_here[i];
}
return max_so_far;
}
/*Driver program to test maxSubArraySum*/
int main()
{
int a[] = { -2, 3, 4, -5, 9, -13, 100, -101, 7 };
int n = sizeof(a) / sizeof(a[0]);
int max_sum = maxSubArraySum(a);
printf("Maximum contiguous sum is %d\n", max_sum);
getchar();
return 0;
}
The approach:
Let max_ending_here be an array, whose element max_ending_here[i] denotes the maximum sum of subarrays (could be empty) that ends just before (not included) index i. To calculate it, use the same approach as it in your function maxSubArraySum. The time complexity is O(n), and space complexity is O(n).
Let sum_from_here be an array, whose element sum_from_here[i] denotes the sum of a length-2 subarray starting from (included) index i, which means sum_from_here[i] = a[i] + a[i + 1]. The time complexity is O(n), and space complexity is O(n).
Iterate through all valid indices and find the maximum value of max_ending_here[i] + sum_from_here[i]: that value is what you are looking for. The time complexity is O(n), and space complexity is O(1).
Thus the overall time complexity is O(n) and the space complexity is O(n).
This approach is extendable to arbitrary minimum length -- not only 2, and the time & space complexity do not grow.
Your original implement in maxSubArraySum is actually a special case of this approach above in which the minimum subarray length is 0.
EDITED:
According to the code you provide in update 1, I made a few changes and present a correct version here:
int maxSubArraySum(int a[])
{
int max_so_far = 0;
int i;
int max_ending_here[size];
int sum_from_here[size];
max_ending_here[0] = 0;
for (i = 1; i < size - 1; i++)
{
max_ending_here[i] = max_ending_here[i - 1] + a[i - 1];
if (max_ending_here[i] < 0)
max_ending_here[i] = 0;
sum_from_here[i] = a[i] + a[i + 1];
if (max_so_far < (max_ending_here[i] + sum_from_here[i]))
max_so_far = max_ending_here[i] + sum_from_here[i];
}
return max_so_far;
}
Notice the key is max_ending_here[i] and sum_from_here[i] shall not overlap. Here's an example:
-2 3 4 -5 9 -13 100 -101 7
| 3 4 -5 9 | -13 100 |
| |
| |
this |
is |
max_ending_here[5] |
|
this
is
sum_from_here[5]
You can solve this problem by using a sliding-window algorithm which I have implemented here.
At all points during the algorithm we maintain the following
A window [lo...hi].
The sum of the current window.
A variable called index that tracks the bad prefix in the current window removing which will increase the value of the sum. So if we remove the prefix [lo...index] then the new window becomes [index+1 ... hi] and the sum increases as [lo...index] had a negative sum.
The sum of the prefix stored in a variable prefixSum. It holds the sum for the interval [lo...index].
The bestSum found till now.
Initialize
window =[0 ... 1]
sum = arr[0] + arr1
index = 0
prefixSum = arr[0]
Now during each iteration of the while loop,
Check if a prefix exists in the current window removing which will increase the value of the sum
add the next value in the list to the current interval and change the window and sum variables.
Update bestSum variable.
The following working Java code realizes the above explanation.
int lo = 0;
int hi = 1;
int sum = arr[0] + arr[1];
int index = 0;
int prefixSum = arr[0];
int bestSum = sum;
int bestLo = 0;
int bestHi = 1;
while(true){
// Removes bad prefixes that sum to a negative value.
while(true){
if(hi-index <= 1){
break;
}
if(prefixSum<0){
sum -= prefixSum;
lo = index+1;
index++;
prefixSum = arr[index];
break;
}else{
prefixSum += arr[++index];
}
}
// Update the bestSum, bestLo and bestHi variables.
if(sum > bestSum){
bestSum = sum;
bestLo = lo;
bestHi = hi;
}
if(hi==arr.length-1){
break;
}
// Include arr[hi+1] in the current window.
sum += arr[++hi];
}
System.out.println("ANS : " + bestSum);
System.out.println("Interval : " + bestLo + " to " + bestHi);
At all points during the algorithm lo+1<=hi and at each step of the while loop we increment hi by 1. Also neither the variable lo nor index ever decrease. Hence time complexity is linear in the size of the input.
Time complexity : O(n)
Space complexity : O(1)
Can anybody find any potentially more efficient algorithms for accomplishing the following task?:
For any given permutation of the integers 0 thru 7, return the index which describes the permutation lexicographically (indexed from 0, not 1).
For example,
The array 0 1 2 3 4 5 6 7 should return an index of 0.
The array 0 1 2 3 4 5 7 6 should return an index of 1.
The array 0 1 2 3 4 6 5 7 should return an index of 2.
The array 1 0 2 3 4 5 6 7 should return an index of 5039 (that's 7!-1 or factorial(7)-1).
The array 7 6 5 4 3 2 1 0 should return an index of 40319 (that's 8!-1). This is the maximum possible return value.
My current code looks like this:
int lexic_ix(int* A){
int value = 0;
for(int i=0 ; i<7 ; i++){
int x = A[i];
for(int j=0 ; j<i ; j++)
if(A[j]<A[i]) x--;
value += x*factorial(7-i); // actual unrolled version doesn't have a function call
}
return value;
}
I'm wondering if there's any way I can reduce the number of operations by removing that inner loop, or if I can reduce conditional branching in any way (other than unrolling - my current code is actually an unrolled version of the above), or if there are any clever bitwise hacks or filthy C tricks to help.
I already tried replacing
if(A[j]<A[i]) x--;
with
x -= (A[j]<A[i]);
and I also tried
x = A[j]<A[i] ? x-1 : x;
Both replacements actually led to worse performance.
And before anyone says it - YES this is a huge performance bottleneck: currently about 61% of the program's runtime is spent in this function, and NO, I don't want to have a table of precomputed values.
Aside from those, any suggestions are welcome.
Don't know if this helps but here's an other solution :
int lexic_ix(int* A, int n){ //n = last index = number of digits - 1
int value = 0;
int x = 0;
for(int i=0 ; i<n ; i++){
int diff = (A[i] - x); //pb1
if(diff > 0)
{
for(int j=0 ; j<i ; j++)//pb2
{
if(A[j]<A[i] && A[j] > x)
{
if(A[j]==x+1)
{
x++;
}
diff--;
}
}
value += diff;
}
else
{
x++;
}
value *= n - i;
}
return value;
}
I couldn't get rid of the inner loop, so complexity is o(n log(n)) in worst case, but o(n) in best case, versus your solution which is o(n log(n)) in all cases.
Alternatively, you can replace the inner loop by the following to remove some worst cases at the expense of another verification in the inner loop :
int j=0;
while(diff>1 && j<i)
{
if(A[j]<A[i])
{
if(A[j]==x+1)
{
x++;
}
diff--;
}
j++;
}
Explanation :
(or rather "How I ended with that code", I think it is not that different from yours but it can make you have ideas, maybe)
(for less confusion I used characters instead and digit and only four characters)
abcd 0 = ((0 * 3 + 0) * 2 + 0) * 1 + 0
abdc 1 = ((0 * 3 + 0) * 2 + 1) * 1 + 0
acbd 2 = ((0 * 3 + 1) * 2 + 0) * 1 + 0
acdb 3 = ((0 * 3 + 1) * 2 + 1) * 1 + 0
adbc 4 = ((0 * 3 + 2) * 2 + 0) * 1 + 0
adcb 5 = ((0 * 3 + 2) * 2 + 1) * 1 + 0 //pb1
bacd 6 = ((1 * 3 + 0) * 2 + 0) * 1 + 0
badc 7 = ((1 * 3 + 0) * 2 + 1) * 1 + 0
bcad 8 = ((1 * 3 + 1) * 2 + 0) * 1 + 0 //First reflexion
bcda 9 = ((1 * 3 + 1) * 2 + 1) * 1 + 0
bdac 10 = ((1 * 3 + 2) * 2 + 0) * 1 + 0
bdca 11 = ((1 * 3 + 2) * 2 + 1) * 1 + 0
cabd 12 = ((2 * 3 + 0) * 2 + 0) * 1 + 0
cadb 13 = ((2 * 3 + 0) * 2 + 1) * 1 + 0
cbad 14 = ((2 * 3 + 1) * 2 + 0) * 1 + 0
cbda 15 = ((2 * 3 + 1) * 2 + 1) * 1 + 0 //pb2
cdab 16 = ((2 * 3 + 2) * 2 + 0) * 1 + 0
cdba 17 = ((2 * 3 + 2) * 2 + 1) * 1 + 0
[...]
dcba 23 = ((3 * 3 + 2) * 2 + 1) * 1 + 0
First "reflexion" :
An entropy point of view. abcd have the fewest "entropy". If a character is in a place it "shouldn't" be, it creates entropy, and the earlier the entropy is the greatest it becomes.
For bcad for example, lexicographic index is 8 = ((1 * 3 + 1) * 2 + 0) * 1 + 0 and can be calculated that way :
value = 0;
value += max(b - a, 0); // = 1; (a "should be" in the first place [to create the less possible entropy] but instead it is b)
value *= 3 - 0; //last index - current index
value += max(c - b, 0); // = 1; (b "should be" in the second place but instead it is c)
value *= 3 - 1;
value += max(a - c, 0); // = 0; (a "should have been" put earlier, so it does not create entropy to put it there)
value *= 3 - 2;
value += max(d - d, 0); // = 0;
Note that the last operation will always do nothing, that's why "i
First problem (pb1) :
For adcb, for example, the first logic doesn't work (it leads to an lexicographic index of ((0* 3+ 2) * 2+ 0) * 1 = 4) because c-d = 0 but it creates entropy to put c before b. I added x because of that, it represents the first digit/character that isn't placed yet. With x, diff cannot be negative.
For adcb, lexicographic index is 5 = ((0 * 3 + 2) * 2 + 1) * 1 + 0 and can be calculated that way :
value = 0; x=0;
diff = a - a; // = 0; (a is in the right place)
diff == 0 => x++; //x=b now and we don't modify value
value *= 3 - 0; //last index - current index
diff = d - b; // = 2; (b "should be" there (it's x) but instead it is d)
diff > 0 => value += diff; //we add diff to value and we don't modify x
diff = c - b; // = 1; (b "should be" there but instead it is c) This is where it differs from the first reflexion
diff > 0 => value += diff;
value *= 3 - 2;
Second problem (pb2) :
For cbda, for example, lexicographic index is 15 = ((2 * 3 + 1) * 2 + 1) * 1 + 0, but the first reflexion gives : ((2 * 3 + 0) * 2 + 1) * 1 + 0 = 13 and the solution to pb1 gives ((2 * 3 + 1) * 2 + 3) * 1 + 0 = 17. The solution to pb1 doesn't work because the two last characters to place are d and a, so d - a "means" 1 instead of 3. I had to count the characters placed before that comes before the character in place, but after x, so I had to add an inner loop.
Putting it all together :
I then realised that pb1 was just a particular case of pb2, and that if you remove x, and you simply take diff = A[i], we end up with the unnested version of your solution (with factorial calculated little by little, and my diff corresponding to your x).
So, basically, my "contribution" (I think) is to add a variable, x, which can avoid doing the inner loop when diff equals 0 or 1, at the expense of checking if you have to increment x and doing it if so.
I also checked if you have to increment x in the inner loop (if(A[j]==x+1)) because if you take for example badce, x will be b at the end because a comes after b, and you will enter the inner loop one more time, encountering c. If you check x in the inner loop, when you encounter d you have no choice but doing the inner loop, but x will update to c, and when you encounter c you will not enter the inner loop. You can remove this check without breaking the program
With the alternative version and the check in the inner loop it makes 4 different versions. The alternative one with the check is the one in which you enter the less the inner loop, so in terms of "theoretical complexity" it is the best, but in terms of performance/number of operations, I don't know.
Hope all of this helps (since the question is rather old, and I didn't read all the answers in details). If not, I still had fun doing it. Sorry for the long post. Also I'm new on Stack Overflow (as a member), and not a native speaker, so please be nice, and don't hesitate to let me know if I did something wrong.
Linear traversal of memory already in cache really doesn't take much times at all. Don't worry about it. You won't be traversing enough distance before factorial() overflows.
Move the 8 out as a parameter.
int factorial ( int input )
{
return input ? input * factorial (input - 1) : 1;
}
int lexic_ix ( int* arr, int N )
{
int output = 0;
int fact = factorial (N);
for ( int i = 0; i < N - 1; i++ )
{
int order = arr [ i ];
for ( int j = 0; j < i; j++ )
order -= arr [ j ] < arr [ i ];
output += order * (fact /= N - i);
}
return output;
}
int main()
{
int arr [ ] = { 11, 10, 9, 8, 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 };
const int length = 12;
for ( int i = 0; i < length; ++i )
std::cout << lexic_ix ( arr + i, length - i ) << std::endl;
}
Say, for a M-digit sequence permutation, from your code, you can get the lexicographic SN formula which is something like: Am-1*(m-1)! + Am-2*(m-2)! + ... + A0*(0)! , where Aj range from 0 to j. You can calculate SN from A0*(0)!, then A1*(1)!, ..., then Am-1 * (m-1)!, and add these together(suppose your integer type does not overflow), so you do not need calculate factorials recursively and repeatedly. The SN number is a range from 0 to M!-1 (because Sum(n*n!, n in 0,1, ...n) = (n+1)!-1)
If you are not calculating factorials recursively, I cannot think of anything that could make any big improvement.
Sorry for posting the code a little bit late, I just did some research, and find this:
http://swortham.blogspot.com.au/2011/10/how-much-faster-is-multiplication-than.html
according to this author, integer multiplication can be 40 times faster than integer division. floating numbers are not so dramatic though, but here is pure integer.
int lexic_ix ( int arr[], int N )
{
// if this function will be called repeatedly, consider pass in this pointer as parameter
std::unique_ptr<int[]> coeff_arr = std::make_unique<int[]>(N);
for ( int i = 0; i < N - 1; i++ )
{
int order = arr [ i ];
for ( int j = 0; j < i; j++ )
order -= arr [ j ] < arr [ i ];
coeff_arr[i] = order; // save this into coeff_arr for later multiplication
}
//
// There are 2 points about the following code:
// 1). most modern processors have built-in multiplier, \
// and multiplication is much faster than division
// 2). In your code, you are only the maximum permutation serial number,
// if you put in a random sequence, say, when length is 10, you put in
// a random sequence, say, {3, 7, 2, 9, 0, 1, 5, 8, 4, 6}; if you look into
// the coeff_arr[] in debugger, you can see that coeff_arr[] is:
// {3, 6, 2, 6, 0, 0, 1, 2, 0, 0}, the last number will always be zero anyway.
// so, you will have good chance to reduce many multiplications.
// I did not do any performance profiling, you could have a go, and it will be
// much appreciated if you could give some feedback about the result.
//
long fac = 1;
long sn = 0;
for (int i = 1; i < N; ++i) // start from 1, because coeff_arr[N-1] is always 0
{
fac *= i;
if (coeff_arr[N - 1 - i])
sn += coeff_arr[N - 1 - i] * fac;
}
return sn;
}
int main()
{
int arr [ ] = { 3, 7, 2, 9, 0, 1, 5, 8, 4, 6 }; // try this and check coeff_arr
const int length = 10;
std::cout << lexic_ix(arr, length ) << std::endl;
return 0;
}
This is the whole profiling code, I only run the test in Linux, code was compiled using G++8.4, with '-std=c++11 -O3' compiler options. To be fair, I slightly rewrote your code, pre-calculate the N! and pass it into the function, but it seems this does not help much.
The performance profiling for N = 9 (362,880 permutations) is:
Time durations are: 34, 30, 25 milliseconds
Time durations are: 34, 30, 25 milliseconds
Time durations are: 33, 30, 25 milliseconds
The performance profiling for N=10 (3,628,800 permutations) is:
Time durations are: 345, 335, 275 milliseconds
Time durations are: 348, 334, 275 milliseconds
Time durations are: 345, 335, 275 milliseconds
The first number is your original function, the second is the function re-written that gets N! passed in, the last number is my result. The permutation generation function is very primitive and runs slowly, but as long as it generates all permutations as testing dataset, that is alright. By the way, these tests are run on a Quad-Core 3.1Ghz, 4GBytes desktop running Ubuntu 14.04.
EDIT: I forgot a factor that the first function may need to expand the lexi_numbers vector, so I put an empty call before timing. After this, the times are 333, 334, 275.
EDIT: Another factor that could influence the performance, I am using long integer in my code, if I change those 2 'long' to 2 'int', the running time will become: 334, 333, 264.
#include <iostream>
#include <vector>
#include <chrono>
using namespace std::chrono;
int factorial(int input)
{
return input ? input * factorial(input - 1) : 1;
}
int lexic_ix(int* arr, int N)
{
int output = 0;
int fact = factorial(N);
for (int i = 0; i < N - 1; i++)
{
int order = arr[i];
for (int j = 0; j < i; j++)
order -= arr[j] < arr[i];
output += order * (fact /= N - i);
}
return output;
}
int lexic_ix1(int* arr, int N, int N_fac)
{
int output = 0;
int fact = N_fac;
for (int i = 0; i < N - 1; i++)
{
int order = arr[i];
for (int j = 0; j < i; j++)
order -= arr[j] < arr[i];
output += order * (fact /= N - i);
}
return output;
}
int lexic_ix2( int arr[], int N , int coeff_arr[])
{
for ( int i = 0; i < N - 1; i++ )
{
int order = arr [ i ];
for ( int j = 0; j < i; j++ )
order -= arr [ j ] < arr [ i ];
coeff_arr[i] = order;
}
long fac = 1;
long sn = 0;
for (int i = 1; i < N; ++i)
{
fac *= i;
if (coeff_arr[N - 1 - i])
sn += coeff_arr[N - 1 - i] * fac;
}
return sn;
}
std::vector<std::vector<int>> gen_permutation(const std::vector<int>& permu_base)
{
if (permu_base.size() == 1)
return std::vector<std::vector<int>>(1, std::vector<int>(1, permu_base[0]));
std::vector<std::vector<int>> results;
for (int i = 0; i < permu_base.size(); ++i)
{
int cur_int = permu_base[i];
std::vector<int> cur_subseq = permu_base;
cur_subseq.erase(cur_subseq.begin() + i);
std::vector<std::vector<int>> temp = gen_permutation(cur_subseq);
for (auto x : temp)
{
x.insert(x.begin(), cur_int);
results.push_back(x);
}
}
return results;
}
int main()
{
#define N 10
std::vector<int> arr;
int buff_arr[N];
const int length = N;
int N_fac = factorial(N);
for(int i=0; i<N; ++i)
arr.push_back(N-i-1); // for N=10, arr is {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
std::vector<std::vector<int>> all_permus = gen_permutation(arr);
std::vector<int> lexi_numbers;
// This call is not timed, only to expand the lexi_numbers vector
for (auto x : all_permus)
lexi_numbers.push_back(lexic_ix2(&x[0], length, buff_arr));
lexi_numbers.clear();
auto t0 = high_resolution_clock::now();
for (auto x : all_permus)
lexi_numbers.push_back(lexic_ix(&x[0], length));
auto t1 = high_resolution_clock::now();
lexi_numbers.clear();
auto t2 = high_resolution_clock::now();
for (auto x : all_permus)
lexi_numbers.push_back(lexic_ix1(&x[0], length, N_fac));
auto t3 = high_resolution_clock::now();
lexi_numbers.clear();
auto t4 = high_resolution_clock::now();
for (auto x : all_permus)
lexi_numbers.push_back(lexic_ix2(&x[0], length, buff_arr));
auto t5 = high_resolution_clock::now();
std::cout << std::endl << "Time durations are: " << duration_cast<milliseconds> \
(t1 -t0).count() << ", " << duration_cast<milliseconds>(t3 - t2).count() << ", " \
<< duration_cast<milliseconds>(t5 - t4).count() <<" milliseconds" << std::endl;
return 0;
}