Optimal Selection for minimum total sum - c

This is a problem from competitive programmer's handbook:
We are given the prices of k
products over n days, and we want to buy each product exactly once. However,
we are allowed to buy at most one product in a day. What is the minimum total
price?
Day
0
1
2
3
4
5
6
7
Product 0
6
9
5
2
8
9
1
6
Product 1
8
2
6
2
7
5
7
2
Product 2
5
3
9
7
3
5
1
4
The Optimal Selection is:
product 0 on day 3 at price 2,
product 1 on day 1 at price 2,
product 2 on days 6 at price 1.
which gives us the total of 5.
The solution:
We either do not buy any product on day d or buy a product x
that belongs to set S. In the latter case, we remove x from set S and add the price of x to the total price.
Here's the code from book:
#include <stdio.h>
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
int main()
{
int price[3][8] = {{ 6, 9, 5, 2, 8, 9, 1, 6 },
{ 8, 2, 6, 2, 7, 5, 7, 2 },
{ 5, 3, 9, 7, 3, 5, 1, 4 }};
int n = 8, k = 3;
int total[1<<10][10];
//Buy all products on day 0
for (int x = 0; x < k; x++) {
total[1<<x][0] = price[x][0];
}
for (int d = 1; d < n; d++) {
for (int s = 0; s < (1<<k); s++) {
total[s][d] = total[s][d-1];
for (int x = 0; x < k; x++) {
if (s & (1<<x)) {
total[s][d] = min(total[s][d], total[s ^ (1<<x)][d-1] + price[x][d]);
break;
}
}
}
}
//Output
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printf("%d", total[i][j]);
}
printf("\n");
}
}
The problem restricts us to buy only one product a day but the code seems to not address that issue at all (also, we buy all products on first day which is fine). The output is just the minimum for each product available by that day [1,2,1]. What am I doing wrong here?

After quite a bit of time in the debugger I was able to make the algo from the book work. Suffice to say the snippet provided in the book is completely broken.
Most major edits:
we will only update a more complex sum if we are updating it from an adjacent sum, that is, we do not update a sum at 111 from the sum of 001 or 010. We use __builtin_popcount to find the difference between the current set index and the one we are tryign to update from.
we will only update higher order sets if enough days has passed for prior sets to be filled.
I hope that I didn't make a mistake here(again). If I did, feel free to correct me. I did try to verify multiple inputs this time and this seems to be working.
Note that I am using multiple local variables that are completely unnecessary. I just wanted some clarity and readability.
This is essentially the same algorithm as in the book, but with a set of restrictions necessary for it to function correctly. Without those restrictions it adds up completely incompatible stuff or adds up at the wrong time and ends up not working.
The algo does address that you can only buy 1 item a day in the sol[xorIndex][dayIndex-1] + currentPrice part. The sol part being accessed was filled on previous days with items excluding the one we are adding.
int optimalSelection(int products, int days, int prices[products][days]){
int sol[1<<products][days];
memset(sol, 0, sizeof(sol));
for (int x = 0; x < products; x++) {
sol[1<<x][0] = prices[x][0];
}
for (int dayIndex = 1; dayIndex < days; dayIndex++) {
int allPossibleSetsCount = 1<<products;
for (int setIndex = 0; setIndex < allPossibleSetsCount; setIndex++) {
int currentMin = sol[setIndex][dayIndex-1];
for (int productIndex = 0; productIndex < products; productIndex++) {
if (setIndex&(1<<productIndex)) {
// this is the index of the set WITHOUT current product
int xorIndex = setIndex^(1<<productIndex);
if(__builtin_popcount(xorIndex) > dayIndex)
continue;
if (__builtin_popcount(setIndex ^ xorIndex) == 1){
// minimum for the prior day for the set excluding this product
int previousMin = sol[xorIndex][dayIndex-1];
// current price of the product
int currentPrice = prices[productIndex][dayIndex];
sol[setIndex][dayIndex] = currentMin == 0 ? previousMin + currentPrice : std::min(previousMin + currentPrice, currentMin);
currentMin = sol[setIndex][dayIndex];
}
}
}
}
}
return sol[(1<<products)-1][days-1];
}

The posted algorithm has a time and space complexity of n.k.2k which seems very expensive and likely to cause a stack overflow for moderately large sets.
Furthermore, the output is not very informative and the constraint at most one product per day does not seem enforceable.
Here is an alternative approach using recursion, with similar time complexity nk but a much smaller memory footprint:
#include <stdio.h>
enum { N = 8, K = 3 };
struct optim {
const int (*price)[N];
int bestsol[K];
int bestprice;
};
void test(struct optim *p, int i, int set, int price, int *sol) {
if (i >= K) {
if (p->bestprice > price) {
p->bestprice = price;
for (int j = 0; j < K; j++) {
p->bestsol[j] = sol[j];
}
}
} else {
for (int d = 0; d < N; d++) {
if (set & (1 << d)) {
continue; // constaint: only 1 product per day
}
sol[i] = d;
test(p, i + 1, set | (1 << d), price + p->price[i][d], sol);
}
}
}
int main() {
int price[K][N] = { { 6, 9, 5, 2, 8, 9, 1, 6 },
{ 8, 2, 6, 2, 7, 5, 7, 2 },
{ 5, 3, 9, 7, 3, 5, 1, 4 } };
struct optim data = { price, { 0, 1, 2 }, price[0][0] + price[1][1] + price[2][2] };
int sol[K];
test(&data, 0, 0, 0, sol);
printf("price: %d, days: [", data.bestprice);
for (int i = 0; i < K; i++) {
printf(" %d", data.bestsol[i]);
}
printf(" ]\n");
return 0;
}
Output: price: 5, days: [ 3 1 6 ]

Turns out the solution that was provided in the book was incomplete. For the program to return the correct result, all subsets of first day have to be populated but in the book only the subsets containing single element that were mapped to powers of two i.e., the indices 1,2,4,etc of total[][] were populated which left the other subsets to have value of 0. This made each of the subsequent day calculation to take minimum value which is 0.
code in line 14 to 16
for (int x = 0; x < k; x++) {
total[1<<x][0] = price[x][0];
}
must be replaced with:
for (int s = 0; s < (1 << k); s++) {
for (int x = 0; x < k; x++) {
if (s & (1 << x)) {
total[s][0] = price[x][0];
}
}
}
Minimum Total Sum for each day will be the set that contains all the elements i.e. total[(1<<k)-1][index of day].
With all the changes the working code is:
#include <stdio.h>
#ifndef min
#define min(a, b)((a) < (b) ? (a) : (b))
#endif
int main()
{
int price[3][8] = {
{ 6, 9, 5, 2, 8, 9, 1, 6 },
{ 8, 2, 6, 2, 7, 5, 7, 2 },
{ 5, 3, 9, 7, 3, 5, 1, 4 }
};
int n = 8, k = 3;
//Changed to scale with input
int total[1 << k][n];
//Buy all products on day 0
//Changes here
for (int s = 0; s < (1 << k); s++)
{
for (int x = 0; x < k; x++)
{
if (s &(1 << x))
{
total[s][0] = price[x][0];
}
}
}
for (int d = 1; d < n; d++)
{
for (int s = 0; s < (1 << k); s++)
{
total[s][d] = total[s][d - 1];
for (int x = 0; x < k; x++)
{
if (s &(1 << x))
{
total[s][d] = min(total[s][d], total[s ^ (1 << x)][d - 1] + price[x][d]);
break;
}
}
}
}
//Output
//Changes here
printf("%d", total[(1 << k) - 1][n - 1]);
}

Related

Loop through odd numbers and 2

Is it possible in C to have a fast for/while loop that loops through the odd numbers and 2? Without using arrays.
So I'd like it to loop through {1, 2, 3, 5, 7, 9, ..}
Of course. Here is a pretty straight forward way.
for(int i=1; i<N; i++) {
if(i>3) i++;
// Code
}
A bit more hackish variant:
for(int i=1; i<N; i+=1+(i>2)) {
// Code
}
But I think in this case that the most readable variant would be something like:
// Code for 1 and 2
// Then code for 3,5,7 ...
for(int i=3; i<N; i+=2) {
// Code
}
Another option
for(int i=1;;++i) // you didn't specify a limit
{
switch(i)
{
default:
if(!(i&1))continue;
case 1:
case 2:
DoSomething(i):
}
}
Another alternative which does use an array but only a small one that is a constant size of two elements no matter how many numbers in the sequence would be:
{
int i;
int iray[] = {1, 2};
int n = 15;
for (i = 1; i < n; i += iray[i > 2]) {
printf (" i = %d \n", i);
// code
}
}
which produces:
i = 1
i = 2
i = 3
i = 5
i = 7
i = 9
i = 11
i = 13
Extending this alternative to other sequences
And this alternative can be extended to other sequences where there is a change of a similar nature. For instance if the desired sequence was
1, 2, 3, 5, 8, 11, ..
Which involves several changes in the sequence. Beginning at 1 an increment of 1 is used followed by a first increment change beginning at 3 where an increment of 2 is used followed by a second change in the sequence beginning at 5 where an increment of 3 is used, you can make the following modification.
{
int i;
int iray[] = {1, 2, 3}; // increment changes
int n = 15;
// calculate the increment based on the current value of i
for (i = 1; i < n; i += iray[(i > 2) + (i > 3)]) {
printf (" i = %d \n", i);
// code
}
return 0;
}
which would produce:
i = 1
i = 2
i = 3
i = 5
i = 8
i = 11
i = 14
#include <stdio.h>
int main()
{
for(unsigned x = 0; x < 10; x++)
printf("%u%s element - %u\n",x + 1, !x ? "st" : x == 1 ? "nd" : x == 2 ? "rd" : "th", !x + x * 2 - (x >= 2));
return 0;
}
no jumps calculating in the !x + x * 2 - (x >= 2) so no pipeline flushes.

How to check if two arrays are mirror images of each other in C?

I am trying to see how to use C to check if two 2d arrays are symmetrical/mirror to each other.
So for example, if
array1 = { { 2, 5, 10 }, { 2, 1, 9 } };
array2 = { { 10, 5, 2 }, { 9, 1, 2 } };
The arrays are really 2d arrays.
How should I approach this? So far I tried to read both 2d arrays and use if/else statements and a bool to check if both arrays are equal to each other or not. But I'm not sure how to check if they are mirror matrices of each other or not.
2 5 10 | 10 5 2
2 1 9 | 9 1 2
The compiler is from 89.
You wanted to read values to both matrices the same way (hint 1: use functions). So they will both look like this:
First one:
{{m1[0][0], m1[0][1], m1[0][2],..., m1[0][99]},
{m1[1][0], m1[1][1], m1[1][2],..., m1[1][99]},
...
{m1[99][0], m1[99][1], ..., m1[99][99]}}
second one:
{{m2[0][0], m2[0][1], m2[0][2],..., m2[0][99]},
{m2[1][0], m2[1][1], m2[1][2],..., m2[1][100]},
...
{m2[99][0], m2[99][1], ..., m2[99][99]}}
But you have an error in first loop of reading m1 array:
for (a = 0; b < row; i++)
And then inside your comparison loop, you have :
m1[row][col] != m2[row][col]
Which compares values of both matrices with the same indices. So instead of comparing m1[0][0] with m2[0][99] you are comparing m1[0][0] with m2[0][0].
You can verify this property with 2 nested loops:
#include <stdio.h>
#define COLS 3
#define ROWS 2
int main(void) {
int array1[ROWS][COLS] = { { 2, 5, 10 }, { 2, 1, 9 } };
int array2[ROWS][COLS] = { { 10, 5, 2 }, { 9, 1, 2 } };
int xmirror = 1;
int ymirror = 1;
int xymirror = 1;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (array1[i][j] != array2[i][COLS - 1 - j])
xmirror = 0;
if (array1[i][j] != array2[ROWS - 1 - i][j])
ymirror = 0;
if (array1[i][j] != array2[ROWS - 1 - i][COLS - 1 - j])
xymirror = 0;
}
}
if (xymirror)
printf("Mirror image to each other rowwise and columnwise\n");
if (ymirror)
printf("Mirror image to each other rowwise\n");
if (xmirror)
printf("Mirror image to each other columnwise\n");
if (xmirror + ymirror + xymirror == 0)
printf("Not a mirror image of each other\n");
return 0;
}
Simple and short:
#include <stdio.h>
#define size 3
int main (void){
int i,j,k,flag=1;
int array1[][size] = { { 2, 5, 10},{ 2, 1, 9 } }, array2[][size] = { {10, 5, 2 }, { 9, 1, 2 } };
//Check mirror image or not
for(i=0;i<size-1;i++) {
for(j=0,k=size-1;j<size;j++,k--) {
if(array1[i][j]!=array2[i][k]) {
flag=0;
break;
}
}
}
if(flag)
printf("Mirror image to each other");
else
printf("Not a mirror image to each other");
return 0;
}

C best function to get split array on elements less, equals and greater than some value

I am programming in C. What is the best method (I mean in linear time) to spit array on elements less, equals and greater than some value x.
For example if I have array
{1, 4, 6, 7, 13, 1, 7, 3, 5, 11}
and x = 7 then it should be
{1, 4, 6, 1, 3, 5, 7, 7, 13, 11 }
I don't want to sort elements because I need more efficient way. Of course in this example in could be any permutation of {1, 4, 6, 1, 3, 5} and {13, 11}.
My thougt: less or grater than some element in array... In this example it is 7.
My function is:
int x = 7;
int u =0, z = 0;
for(int i=0; i<size-1; i++) // size - 1 because the last element will be choosen value
{
if(A[i] == x)
swap(A[i], A[u]);
else if(A[i] == x)
{
swap(A[i], A[n-(++z)]);
continue;
}
i++
}
for(int i = 0; i<z; i++)
swap(A[u+i],A[size-(++z)];
where u is number of current less elements, and z is the number of equals element
But if I have every elements in array equals there it doesn't work (size-(++z)) is going under 0
This is the so-called Dutch national flag problem, named after the three-striped Dutch flag. (It was named that by E.W. Dijkstra, who was Dutch.) It's similar to the partition function needed to implement quicksort, but in most explanations of quicksort a two-way partitioning algorithm is presented whereas here we are looking for a three-way partition. The classic quicksort partitioning algorithms divide the vector into two parts, one consisting of elements no greater than the pivot and the other consisting of elements strictly greater. [See note 1]
The wikipedia article gives pseudocode for Dijkstra's solution, which (unlike the classic partition algorithm usually presented in discussions of quicksort) moves left to right through the vector:
void dutchflag(int* v, size_t n, int x) {
for (size_t lo = 0, hi = n, j = 0; j < hi; ) {
if (v[j] < x) {
swap(v, lo, j); ++lo; ++j;
} else if (v[j] > x) {
--hi; swap(v, j, hi);
} else {
++j;
}
}
There is another algorithm, discovered in 1993 by Bentley and McIlroy and published in their paper "Engineering a Sort Function" which has some nice diagrams illustrating how various partitioning functions work, as well as some discussion about why partitioning algorithms matter. The Bentley & McIlroy algorithm is better in the case that the pivot element occurs infrequently in the list while Dijkstra's is better if it appears often, so you have to know something about your data in order to choose between them. I believe that most modern quicksort algorithms use Bentley & McIlroy, because the common case is that the array to be sorted has few duplicates.
Notes
The Hoare algorithm as presented in the Wikipedia Quicksort article, does not rearrange values equal to the pivot, so they can end up being present in both partitions. Consequently, it is not a true partitioning algorithm.
You can do this:
1) Loop through the array, if element is less than x then put in new array1.
2)If element is greater than x then put in new array2.
This is linear time O(n)
I tried something like this below which I think is O(n). Took me a little bit to work the kinks out but I think it's pretty similar to the dutchflag answer above.
My ouptput
a.exe
1 4 6 5 3 1 7 7 11 13
1 4 5 6 3 1 7 7 7 11 13
code:
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
void order(int * list, int size, int orderVal)
{
int firstIdx, lastIdx, currVal, tempVal;
firstIdx = 0;
lastIdx = size-1;
for ( ;lastIdx>firstIdx;firstIdx++)
{
currVal = list[firstIdx];
if (currVal >= orderVal)
{
tempVal = list[lastIdx];
list[lastIdx] = currVal;
lastIdx--;
list[firstIdx] = tempVal;
if (tempVal >= orderVal)
firstIdx--;
}
}
lastIdx = size-1;
for( ;lastIdx>firstIdx && middleNum>0;lastIdx--)
{
currVal = list[lastIdx];
if (currVal == orderVal)
{
tempVal = list[firstIdx];
list[firstIdx] = currVal;
firstIdx++;
list[lastIdx] = tempVal;
if (tempVal == orderVal)
lastIdx++;
}
}
}
int main(int argc, char * argv[])
{
int i;
int list[] = {1, 4, 6, 7, 13, 1, 7, 3, 5, 11};
int list2[] = {1, 4, 7, 6, 7, 13, 1, 7, 3, 5, 11};
order(list, ARRAY_SIZE(list), 7);
for (i=0; i<ARRAY_SIZE(list); i++)
printf("%d ", list[i]);
printf("\n");
order(list2, ARRAY_SIZE(list2), 7);
for (i=0; i<ARRAY_SIZE(list2); i++)
printf("%d ", list2[i]);
}
Here is an example using a bubble sort. Which type of sort algorithm is best, is up to you, this is just to demonstrate. Here, I treat values < x as -1, values == x as 0, values > x as 1.
Note that the elements < x and those > x are still in the same sequence.
#include <stdio.h>
int main(void)
{
int array[] = { 1, 4, 6, 7, 13, 1, 7, 3, 5, 11 };
int x = 7;
int len = sizeof array / sizeof array[0];
int i, j, m, n, tmp;
for (i=0; i<len-1; i++) {
m = array[i] < x ? -1 : array[i] == x ? 0 : 1;
for (j=i+1; j<len; j++) {
n = array[j] < x ? -1 : array[j] == x ? 0 : 1;
if (m > n) {
tmp = array[i]; // swap the array element
array[i] = array[j];
array[j] = tmp;
m = n; // and replace alias
}
}
}
for(i=0; i<len; i++)
printf("%d ", array[i]);
printf("\n");
return 0;
}
Program output:
1 4 6 1 3 5 7 7 13 11

How do I compute the number of valleys in a sequence of numbers?

Given a sequence of digits, a valley is defined as the region in the sequence that is surrounded (to the left and right) by higher values. The task is to find the number of valleys in the sequence.
For example,
{9,8,7,7,8,9} has one valley at {7,7}
{9,8,7,7,8,6,9} has two valleys at {7,7} and {6}
{7,8,9,8,7} has no valleys
The code I have to compute the number of valleys is as follows:
#include <stdio.h>
#define SIZE 40
int main()
{
int input;
int store[SIZE];
int i = 0;
int j;
int valley = 0;
int count = 0;
printf("Enter sequence: ");
scanf("%d", &input);
while(input != -1)
{
store[i] = input;
i++;
scanf("%d", &input);
}
count = count + i;
for(i = 1; i < count; i++)
{
for(j = i; j < i + 1; j++)
{
if((store[j-1] > store[j]) && (store[j] < store[j+1]))
{
valley = valley + 1;
break;
}
}
}
printf("Number of valleys: %d", valley);
return 0;
}
I am able to display the correct answer if the input is "3 2 1 2 3". However, if in between the number is equal to another and they are side by side (for example, "3 1 1 2"), the program will compute the wrong answer.
How do I go about writing the program so that I am able to display the correct number of valleys?
Look for slope changes from down to up.
Rather than a double nested for loop, march along looking for slope changes from down to up. Consider any slope of 0 to be the same as the previous slope.
size_t Valley(const int *store, size_t count) {
size_t valley = 0;
int slope = -1;
size_t i;
// Find first down slope
for (i = 1; i < count; i++) {
if (store[i] < store[i - 1]) {
break;
}
}
for (; i < count; i++) {
int newslope = (store[i] > store[i - 1]) - (store[i] < store[i - 1]);
// Loop for slope changes
if (newslope == -slope) {
if (newslope > 0)
valley++;
slope = newslope;
}
}
return valley;
}
Test code.
void Vtest(const int *store, size_t count) {
size_t n = Valley(store, count);
printf("%zu %zu\n", count, n);
}
void Vtests(void) {
int a1[] = { 9, 8, 7, 7, 8, 9 };
Vtest(a1, sizeof a1 / sizeof a1[0]);
int a2[] = { 9, 8, 7, 7, 8, 6, 9 };
Vtest(a2, sizeof a2 / sizeof a2[0]);
int a3[] = { 7, 8, 9, 8, 7 };
Vtest(a3, sizeof a3 / sizeof a3[0]);
int a4[] = { 3, 2, 1, 2, 3 };
Vtest(a4, sizeof a4 / sizeof a4[0]);
int a5[] = { 8, 7, 7, 8, 6 };
Vtest(a5, sizeof a5 / sizeof a5[0]);
}
int main(void) {
Vtests();
return 0;
}
Output
6 1
7 2
5 0
5 1
5 1
The problem is here:
if((store[j-1] > store[j] )&&(store[j] < store[j+1]))
In both comparations you are using index j, so this program finds only valleys with length 1. Try this modification:
if((store[i-1] > store[i] )&&(store[j] < store[j+1]))
Also I am not sure, that it is right to break; in this situation. But it is not clear now, which answer is correct in case 3 1 2 3 - one (1) or two (1 and 1 2). From your first example we can see, that right answer is one, but it is not obvious from the definition.
Depending on whether you define valley as a higher value to the IMMEDIATE left/right of a given point you may need to adjust the Valley function provided by chux as follows:
size_t Valley (const int *store, size_t count) {
...
i++;
for (; i < count; i++) {
int newslope = (store[i] > store[i - 1]) - (store[i] < store[i - 1]);
if (newslope == -slope) {
if (newslope > 0)
valley++;
}
slope = newslope;
}
...
}
output:
$ ./bin/valleyt
6 0
7 1
5 0
5 1
5 0
This is a supplement to the answer provided by chux, and the input data is as he provided in his answer. This code just limits the definition of a valley to being created by 3 adjacent points. (a special case of the general answer of a change from negative to positive slope with intervening equivalent points)

How can I average a subset of an array and store the result in another array?

I have a C array fftArray[64] that contains values that I want averaged and placed into another array frequencyBar[8]. Getting the average of the entire array would be easy enough using a for statement.
int average, sum = 0;
for (i = 0; i < 64; i++)
{
sum += fftArray[i];
}
average = sum/64;
But I just can't seem to figure out how to get the average from fftArray[0] through fftArray[8] and store this in frequencyBar[0], the average of fftArray[9] through fftArray[16] and store this in frequencyBar[1], etc. Can anyone help me out with this? Thanks
This looks like a homework assignment, so, rather than give you the outright answer, I'd rather just point you in the right direction...
use a nested loop (one inside the other). One loop cycles 0-7, the other one 0 - 63. Use the smaller one to populate your sliced averages.
or better yet use the % operator to see when you've gone through 8 elements and do an average of your total, then reset the total for the next set. Then you'll have learned how to use the % operator too! :)
[EDIT]
ok, if not homework then something like this... I haven't written C in 5 years, so treat this as pseudo code:
//assuming you have a fftArray[64] with data, as per your question
int i,sum,avCounter,total;
int averages[8];
for(i=0 , avCounter=0, total=0 ; i<64; ){
total += fftArray[i];
if(++i % 8 == 0){ //%gives you the remainder which will be 0 every 8th cycle
averages[avCounter++] = total / 8
total = 0; //reset for next cycle
}
}
I think this will work better than a nested loop... but I'm not sure since % is division which is more processor heavy than addition... however... I doubt anyone would notice :)
int i, j;
for (i = 0; i < 8; i++) {
int sum = 0;
for (j = 0; j < 8; j++) {
sum += fftArray[ 8*i + j ];
}
frequencyBar[i] = sum / 8;
}
Bonus exercise: Optimize this code for speed on your chosen platform.
TF,
DISCLAIMER: This code is just off the top of my head... it hasn't even been compiled, let alone tested.
// returns the average of array[first..last] inclusive.
int average(int[] array, int first, int last) {
int sum = 0;
for (i = first; i <= last; i++)
sum += array[i];
return sum / (last - first + 1); // not sure about the +1
}
Then what you'd do is loop through the indexes of your frequencyBar array [0..7], setting frequencyBar[i] = average(array, first, last);... the tricky bit is calculating the first and last indexes... try i*8 and (i+1)*8 respectively... that may not be exactly right, but it'll be close ;-)
Cheers. Keith.
EDIT: Bored... waiting for my test results to come back. No news is good news, right? ;-)
It turns out that passing the length is a fair bit simpler than passing the last index.
#include <stdio.h>
int sum(int array[], int first, int length) {
int sum = 0;
for (int i = first; i < first+length; i++)
sum += array[i];
return sum;
}
double average(int array[], int first, int length) {
double total = sum(array, first, length);
#ifdef DEBUG
printf("DEBUG: [%2d..%2d] %d", first, first+length-1, array[first]);
for (int i = first+1; i < first+length; i++)
printf(" + %d", array[i]);
printf(" = %d / %d = %f\n", (int)total, length, total/length);
#endif
return total / length;
}
int main(int argc, char* argv[]) {
int array[] = { // average
1, 2, 3, 4, 5, 1, 2, 3, // 2.625
4, 5, 1, 2, 3, 4, 5, 1, // 3.125
2, 3, 4, 5, 1, 2, 3, 4, // 3
5, 1, 2, 3, 4, 5, 1, 2, // 2.875
3, 4, 5, 1, 2, 3, 4, 5, // 3.375
1, 2, 3, 4, 5, 1, 2, 3, // 2.625
4, 5, 1, 2, 3, 4, 5, 1, // 3.125
2, 3, 4, 5, 1, 2, 3, 4 // 3
};
double frequency[8];
for (int i = 0; i < 8; i++)
frequency[i] = average(array, i*8, 8);
for (int i = 0; i < 8; i++)
printf("%f ", frequency[i]);
printf("\n");
}
Watch your sum doesn't wrap around if fftArray has large value in!

Resources