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.
Related
I'm making a program in C that factors any number using primes and saves these primes, multiplying them you find all the divisors of a number.
But I can't make an array that multiplies the previous columns and saves the results. follow the example
60 / 2
30 / 2
15 / 3
5 / 5
divisors = 2, 2, 3, 5
now i need`add 1 to array array {1, 2, 2, 3, 5}
i need this now start colune 2 {1, 2} 2 * 1 = 2 save.
next colune 3 {1, 2, 2} 2 * 1 = 2 but we already have 2 so don't save it.
continue 2 * 2 = 4 save.
colune 4 {1, 2, 2, 3} 3 * 1 = 3 save, 3 * 2 = 6 save, 3 * 4 = 12 save.
colune 5 {1, 2, 2, 3, 5} 5 * 1 = 5 save, 5* 2 = 10, 5 * 4 = 20 save, 5 * 3= 15 save, 5 * 6 = 30 save, 5 * 12 = 60 save.
now we found all divisors of 60 = 1, 2, 3, 4, 5, 6, 10 ,12 , 15,20, 30, 60.
It is important to mention that I need the program to be like this, I know there are other ways... but I only need this one, I have been unable to complete it for 1 week
video to help https://www.youtube.com/watch?v=p0v5FpONddU&t=1s&ab_channel=MATEM%C3%81TICAFORALLLUISCARLOS
my program so far
#include <stdlib.h>
#include <stdio.h>
int N = 1;
int verificarPrimo(int numero);
int main()
{
int num = 60, i, primo = 1, resultados[N], j = 1;
for (i = 0; i < 60; i++)
{
if (primo == 1)
{
resultados[N - 1] = primo;
i = 2;
primo = i;
}
if (verificarPrimo(i))
{
while (num % i == 0)
{
num = num / i;
resultados[N] = i;
N++;
}
}
}
for (i = 1; i < N; i++)
{
printf("%d \n", resultados[i]);
}
}
int verificarPrimo(int primo)
{
int i;
if (primo <= 1)
return 0;
for (i = 2; i <= primo / 2; i++)
{
if (primo % i == 0)
return 0;
}
return 1;
}
I tried out your code and ran into some issues with how the results were being stored. First off, the results array is being initially defined as an array with a size of "1", and that it not what you probably want.
int num = 60, i, primo = 1, resultados[N], j = 1;
With that in mind and determining the spirit of this project, following is tweaked version of the code to test for one or more values and their factors.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int verificarPrimo(int primo)
{
int sq = sqrt(primo) + 1; /* Usual checking for a prime number is from '2' to the square root of the number being evaluated */
if (primo <= 1)
return 0;
for (int i = 2; i < sq; i++)
{
if (primo % i == 0)
return 0;
}
return 1;
}
int main()
{
int N = 0;
int num = 0, entry = 0, resultados[100]; /* The results array needs to be defined with some value large enough to contain the assorted factors a number might have */
printf("Enter a number to evaluate for factors: "); /* Using a prompt to allow various values to be tested */
scanf("%d", &entry);
num = entry;
if (verificarPrimo(num)) /* Catchall in case the entered number is a prime number */
{
printf("This number is a prime number and has no factors other than one and itself\n");
return 0;
}
resultados[0] = 1; /* Normally the value '1' is implied in a list of factors, so these lines could be omitted */
N = 1;
for (int i = 2; i < entry; i++)
{
if (verificarPrimo(i))
{
while (num % i == 0)
{
num = num / i;
resultados[N] = i;
N++;
}
}
}
printf("Factors for %d\n", entry);
for (int i = 0; i < N; i++)
{
printf("%d ", resultados[i]);
}
printf("\n");
return 0;
}
Some items to point out in this tweaked code.
In the prime number verification function, it is usually customary to set up a for loop in testing for prime numbers to go from the value of "2" to the square root of the number being tested. There usually is no need travel to one half of the number being tested. For that, the #include <math.h> statement was added (FYI, "-lm" would need to be added to link in the math library).
Instead of defining the results array with a value of one element, an arbitrary value of "60" was chosen for the holding the possible number of results when evaluating factors for a given value. Your original code had the potential of storing data past the end of the array and causing a "smashing" error.
The value of "1" is usually left out of the list of factors for a number, but was left in as the initial result value. This might be left out of the completed code.
An additional entry field was added to allow for user entry to be tested to give the code some flexibility in testing numbers.
A test was also added to see if the entered number is itself a prime number, which would only have factors of "1" and itself.
Following is some sample terminal output testing out your original value of "60" along with some other values.
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 60
Factors for 60
1 2 2 3 5
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 63
Factors for 63
1 3 3 7
#Dev:~/C_Programs/Console/Factors/bin/Release$ ./Factors
Enter a number to evaluate for factors: 29
This number is a prime number and has no factors other than one and itself
Give that a try to see if it meets the spirit of your project.
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]);
}
I create a program that get the input of array element size of 10. Everything getting will with the sum of even and odd number. but when it comes to the inverse it didn't work.
i created two arrays where the first getting the value from the user and second copying the element starting from end of the first array..
#include <stdio.h>
int main (){
int array[10] , i , odd =0 , even =0;
int array1[10],b;
for (i=0 ; i < 10 ; i ++){
printf("Insert number %d: ",i);
scanf("%d",&array[i]);
}
for (i=0; i < 10 ; i++){
if ( array[i] % 2 == 0){
even = even + array[i];
}
else
odd = odd + array[i];
}
printf("\n The Sum of Even Numbers in this Array = %d ", even);
printf("\n The Sum of Odd Numbers in this Array = %d ", odd);
for ( i = 10 , b =0; i>0; i-- , b++)
{
array1[b] = array[i];
}
printf("\nReverse Order:\n");
for ( b = 0 ; b< 10;b++ )
{
printf(" %d",array[b]);
}
return 0;
}
The input will be: 2 3 5 4 6 12 3 7 4 9
What I expect the out put for the reverse is: 9 4 7 3 12 6 4 5 3 2
But it gave me same value as : 2 3 5 4 6 12 3 7 4 9 .
Any Idea for how doing this reverse.?
In addition to the answer by #Yunnosch that identifies the problems in your current implementation, you can refactor (rearrange) your code to sum even and odd and reverse array into array1 in a single loop. The only other loop you need is the loop to iterate over array1 outputting the reversed array.
With a bit of re-arranging, you could do something similar to:
#include <stdio.h>
int main (void) {
int array[] = { 2, 3, 5, 4, 6, 12, 3, 7, 4, 9 }, /* array */
array1[sizeof array/sizeof *array], /* array1 */
even = 0, odd = 0; /* even/odd */
size_t n = sizeof array/sizeof *array; /* no. elem in array */
for (size_t i = 0; i < n; i++) { /* loop over each element in array */
array1[i] = array[n - i - 1]; /* reverse into array1 */
if (array[i] & 1) /* check if odd (bit-0 == 1) */
odd += array[i]; /* add value to odd */
else /* even */
even += array[i]; /* add value to even */
}
/* output results */
printf ("even sum: %d\nodd sum : %d\n\nreversed: ", even, odd);
for (size_t i = 0; i < n; i++)
printf (" %d", array1[i]);
putchar ('\n');
}
(note: you can either use if (array[i] % 2) or if (array[i] & 1) to test whether the element is odd or even. Anding with 1 simply checks whether bit-0 is 1, if it is, it's an odd number. Modern compilers will optimize to remove the division inherent to modulo, so whichever you prefer should pose no penalty)
Example Use/Output
$ ./bin/revarr
even sum: 28
odd sum : 27
reversed: 9 4 7 3 12 6 4 5 3 2
Look things over and let me know if you have questions.
You are outputting the array which you never tried to inverse.
printf(" %d",array[b]);
should be
printf(" %d",array1[b]);
Aside, the input by David C. Rankin:
Also for ( i = 10 ... and array1[b] = array[i]; assigns from beyond the end of array. It should e.g. better be
for ( i = 10 , b =0; i>0; i-- , b++)
{
array1[b] = array[i-1];
}
So I have been trying to do a variant of the subset sum problem, which I want to do using dynamic programming. So what I am aiming for is for example, to have an input of
m = 25 // Target value
n = 7 // Size of input set
and the input set to be for example {1, 3, 4, 6, 7, 10, 25}. So the wanted output would be something like
{1, 3, 4, 7, 10} and {25}.
Here is the code
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Get input sequence
int n = 7; // Size of input set
int m = 25; // Target value
int *S; // Input set
int **C; // Cost table
int i,j,potentialSum,leftover;
S=(int*) malloc((n+1)*sizeof(int));
C=malloc((m+1)*sizeof(int*));
for (int rows = 0; rows<=m; rows++) {
C[rows] = malloc((m+1)*sizeof(int));
}
if (!S || !C)
{
printf(" FAILED %d\n",__LINE__);
exit(0);
}
S[0] = 0;
S[1] = 1;
S[2] = 3;
S[3] = 4;
S[4] = 6;
S[5] = 7;
S[6] = 10;
S[7] = 25;
// Initialize table for DP
C[0][0]=0; // DP base case
// For each potential sum, determine the smallest index such
// that its input value is in a subset to achieve that sum.
for (potentialSum=1; potentialSum<=m; potentialSum ++)
{
for (j=1;j<=n;j++)
{
leftover=potentialSum-S[j]; // To be achieved with other values
if (leftover<0) // Too much thrown away
continue;
if (C[leftover][0] == (-1)) // No way to achieve leftover
continue;
if (C[leftover][0]<j) // Indices are included in
break; // ascending order.
}
C[potentialSum][0]=(j<=n) ? j : (-1);
}
// Output the input set
printf(" i S\n");
printf("-------\n");
for (i=0;i<=n;i++)
printf("%3d %3d\n",i,S[i]);
// Output the DP table
printf("\n\n i C\n");
printf("-------\n");
for (i=0;i<=m;i++)
printf("%3d %3d\n",i,C[i][0]);
if (C[m][m]==(-1))
printf("No solution\n");
else
{
printf("\n\nSolution\n\n");
printf("(Position) i S\n");
printf("------------------\n");
for (i=m;i>0;i-=S[C[i][0]])
printf(" %3d %3d\n",C[i][0],S[C[i][0]]);
}
}
This will output the following
i S
-------
0 0
1 1
2 3
3 4
4 6
5 7
6 10
7 25
i C
-------
0 0
1 1
2 -1
3 2
4 2
5 3
6 4
7 3
8 3
9 4
10 4
11 4
12 5
13 4
14 4
15 5
16 5
17 5
18 5
19 6
20 5
21 5
22 6
23 6
24 6
25 6
Solution
(Position) i S
------------------
6 10
5 7
3 4
2 3
1 1
Program ended with exit code: 0
My problem is that I can only output one solution, and that is the solution that needs the smaller values and goes up to 25, so when 25 is used it isn't in the solution. The C array in the code is a 2-D array, since I thought I could maybe do another backtrace while computing the first one? I couldn't figure out how to do so, so I left C[i][0] fixed to the first column, just to demonstrate a single solution. Any tips in the right direction would be greatly appreciated. I found a solution using Python, but the problem is solved recursively, which I don't think helps me, but that code is here.
Thanks for all the help in advance.
I did not fully understand your code. But here is a C code which finds all the subsets that sum to target.
#include <stdio.h>
int a[] = { 0, 1, 3, 4, 6, 7, 10, 25 }; //-- notice that the input array is zero indexed
int n = 7;
int target = 25;
int dp[8][26];
int solutions[1 << 7][8]; //-- notice that the number of subsets could be exponential in the length of the input array a.
int sz[1 << 7]; //-- sz[i] is the length of subset solutions[i]
int cnt = 0; //-- number of subsets
void copy(int srcIdx, int dstIdx){
int i;
for (i = 0; i < sz[srcIdx]; i++)
solutions[dstIdx][i] = solutions[srcIdx][i];
sz[dstIdx] = sz[srcIdx];
}
//-- i, and j are indices of dp array
//-- idx is the index of the current subset in the solution array
void buildSolutions(int i, int j, int idx){
if (i == 0 || j == 0) return; // no more elements to add to the current subset
if (dp[i - 1][j] && dp[i - 1][j - a[i]]){ // we have two branches
cnt++; // increase the number of total subsets
copy(idx, cnt); // copy the current subset to the new subset. The new subset does not include a[i]
buildSolutions(i - 1, j, cnt); //find the remaining elements of the new subset
solutions[idx][sz[idx]] = a[i]; // include a[i] in the current subset
sz[idx]++; // increase the size of the current subset
buildSolutions(i - 1, j - a[i], idx); // calculate the remaining of the current subset
}
else if (dp[i - 1][j - a[i]]){ // we only have one branch
solutions[idx][sz[idx]] = a[i]; // add a[i] to the current subset
sz[idx]++;
buildSolutions(i - 1, j - a[i], idx); // calculate the remaining of the current subset
}
else buildSolutions(i - 1, j, idx); // a[i] is not part of the current subset
}
int main(){
int i, j;
// initialize dp array to 0
for (i = 0; i <= n; i++)
for (j = 0; j <= target; j++) dp[i][j] = 0;
//-- filling the dp array
for (i = 0; i <= n; i++)
dp[i][0] = 1;
for (i = 1; i <= n; i++){
for (j = 1; j <= target; j++){
if (j < a[i])
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - a[i]];
}
}
//-- building all the solutions
for (i = 0; i < sizeof(sz); i++) sz[i] = 0; //-- initializing the sz array to 0
buildSolutions(n, target, 0);
//-- printing all the subsets
for (i = 0; i <= cnt; i++){
for (j = 0; j < sz[i]; j++){
printf("%d ", solutions[i][j]);
}
printf("\n");
}
}
If you have any questions about the code, do not hesitate to ask.
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)