Code fails to find the maximum sum - c

Link to CodeChef problem MAXSC
Attempted solution:
#include<stdio.h>
int main()
{
long long int n, t, k, i, j, max[701], a[701][701], sum, flag;
scanf( "%lld", &t );
for( k = 0 ; k < t ; k++ )
{
scanf( "%lld", &n );
for( i = 1 ; i <= n ; i++ )
{
for( j = 1 ; j <= n ; j++ )
{
scanf( "%lld", &a[i][j] );
if( j == 1)
max[i] = a[i][1];
if( a[i][j] > max[i] )
max[i] = a[i][j];
}
}
sum = 0, flag = 0;
for( i = 1 ; i <= n-1 ; i++ )
{
if( max[i] < max[i+1])
sum = sum + max[i];
else
{
flag = 1;
break;
}
}
if(flag == 1)
printf("-1\n");
else
{
sum = sum + max[n-1];
printf("%lld\n", sum );
}
}
}
Compute the maximum possible value of E1 + E2 + ... + EN. If it's impossible to pick the elements E1, E2, ..., EN, print -1 instead.
Constraint:
Code should pick N elements, one from each sequence; let's denote the element picked from sequence Ai by Ei. For each i (2 ≤ i ≤ N), Ei should be strictly greater than Ei-1.
Does this constraint mean we have to choose max element from each line?
If you look at example given:
Example Input:
1
3
1 2 3
4 5 6
7 8 9
Output:
18
Explanation
Example case 1: To maximize the score, pick 3 from the first row, 6 from the second row and 9 from the third row. The resulting sum is E1+E2+E3 = 3+6+9 = 18.
If you notice they have mentioned "maximize".
Though my code finds the max, it isn't being accepted.

why is this code not being accepted?
Code's logic is flawed. When max[i] < max[i+1] is false, it sets flag = 1; instead of considering other elements from a[i].
Does this constraint mean we have to choose max element from each line?
No. The goal is a maximal sum, not a sum of maximums.
// if( max[i] < max[i+1])
if(max[i] < max[i+1])
sum = sum + max[i];
else {
flag = 1;
break;
}
The solution lies in tying other elements. Even if that fails, perhaps a prior selection should be changed. Recursion may be employed or other analysis. I think it would make sense to first sort each row of data to avoid this code taking n*n run-time. It should be trivial to code a n*n solution (trying every combination).
As this is homework, leave to OP to develop the solution.

1
3
6 10 12
4 5 7
8 9 10
-1
but output should be 6+7+10=23.
question is given Ei should be strictly greater than Ei-1

1
3
1 2 3
4 5 6
7 8 9
Output is 3+6+9=18 means 3<6 and 6<9 which satisfy the above problem
3
6 10 12
4 5 7
8 9 10
Output is 6+7+10=23 means 12<7 which is false and 6<7 which is true and 7<10 also true so sum=23.
3
8 9 10
11 12 13
10 5 9
Output is -1 because 10<13 is true but 13 is not less than 10 or 5 or 9 which is false hence output is -1.

Related

I want to get the inverse of an array while the user input the value

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];
}

Loop through a nested loop two-by two in C

I would like to loop through two arrays in a semi-zipped fashion, such that for as many entries as possible, the following pattern is observed:
arr1[i] arr2[j]
arr1[i] arr2[j+1]
arr1[i+1] arr2[j+2]
arr1[i+1] arr2[j+3]
....
For example, if len arr1 is 96 and len arr2 is 3, I would like to see
0 0
0 1
1 2
1 0
2 1
2 2
3 0
3 1
4 2
4 0
5 1
5 2
I'm having a little trouble getting the logic exactly right; any help would be greatly appreciated
Pseudocode:
i = 0;
for (x = 0; i < arr1.len; ++x) {
i = x / 2; // integer division
j = x % arr2.len;
// use arr1[i] and arr2[j]
}
Use integer division to repeat a value multiple times before moving on to the next value (e.g. 0 0 1 1 2 2 3 3 ...), where the number of times you want to repeat a value is equal to the denominator.
Use modulo division to repeat a sequence of values indefinitely (e.g. 0 1 2 0 1 2 0 1 2 ...), where the number of items in the sequence is equal to the denominator.
If I have understood you correctly you need a loop like the one shown in the demonstrative program below.
#include <stdio.h>
#define N 10
#define M 3
int main( void )
{
int a[N];
int b[N];
for ( int i = 0; i < N; i++ ) a[i] = i;
for ( int i = 0; i < M; i++ ) b[i] = i;
for (int i = 0, j = 0, k = 1; i < N; i += k ^= 1, j = ( j + 1 ) % M)
{
printf( "%d %d\n", a[i] , b[j] );
}
}
The program output is
0 0
0 1
1 2
1 0
2 1
2 2
3 0
3 1
4 2
4 0
5 1
5 2
6 0
6 1
7 2
7 0
8 1
8 2
9 0
9 1

What should I do for sort array?

I tried to sort arr by excluding those who were already selected as the largest numbers but it didn't work.
The result is this:
As I intended, at first cycle, the store is {9, 0, 0, 0, 0 ... } and when arr[i] becomes 9, the rest of process should be skipped. I have to sort it without additional functions and it's too difficult to me. What is the problem?
int i = 0;
int j = 0;
int num = 0;
int sign = 0;
int arr[10] = { 1,5,3,4,8,7,5,9,8,0 };
int max = arr[0];
int store[10] = { 0 };
int k = 0;
for (j = 0; j < 10; j++) {
printf("store: ");
for (int n = 0; n < 10; on++)
printf("%d ", store[n]);
printf("\n");
for (i = 0; i < 10; i++) {
sign = 0;
k = 0;
while (k < 10) {
if (arr[i] == store[k]) {
sign = 1;
break;
}
k++;
}
if (sign == 1) {
continue;
}
if (arr[i] > max) {
max = arr[i];
}
}
store[j] = max;
}
You have several errors here:
The array store has a size of 10, but in the jth pass through the outer loop, only j values have been filled in; the rest is still zero. So whenever you iterate over store, you should use j as upper limit.
You are looking for the max in each iteration. Therefore, it is not enough to initialise max once outside the outer loop. You do that, and it will stay 9 ever after. You should reset max for every j.
Finally, your idea to go through the array to see whether you have already processed a certain value does not work. Your array has duplicates, two 8's and two 5's. You will only place one eight and one five with your strategy and re-use the last value of max for the last two elements. (Plus, that idea lead to O(n³) code, which is very wasteful.
You can work around that by keeping an extra array where you store whether (1) or not (0) you have already processed a value at a certain index or by setting processed entries in the array to a very low value.
What you want to implement is selection sort: Find the maximum value in the whole list and move it to the front. Then find the maximum in the whole list except the first item and move it to the second slot and so on:
* 1 5 3 4 8 7 5 9 8 0
9 * 5 3 4 8 7 5 1 8 0
9 8 * 3 4 5 7 5 1 8 0
9 8 8 * 4 5 7 5 1 3 0
9 8 8 7 * 5 4 5 1 3 0
9 8 8 7 5 * 4 5 1 3 0
9 8 8 7 5 5 * 4 1 3 0
9 8 8 7 5 5 4 * 1 3 0
9 8 8 7 5 5 4 3 * 1 0
9 8 8 7 5 5 4 3 1 * 0
9 8 8 7 5 5 4 3 1 0 *
Here, all items to the left of the asterisk have been sorted and everything to the right of the asterisk is still unsorted. When the * (at position j) has moved to the right, the whole array is sorted.
This sort is in-place: It destroys the original order of the array. That is useful, because the position of an element tells us whether it has been processed or not. In the third iteration, the algorithm can distinguish between the 8 that has been sorted and the 8 that hasn't been sorted yet. (This sort is often described as sorting a hand of cards: Look fo the lowest, put it to the left and so on. If you must sort into a second array, copy the original array and sort the copy in place.)
Here's the code that sorts your array and prints out the diagram above:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int arr[10] = {1, 5, 3, 4, 8, 7, 5, 9, 8, 0};
int i = 0;
int j = 0;
for (j = 0; j < 10; j++) {
int imax = j;
int swap = arr[j];
// print array
for (i = 0; i < 10; i++) {
if (i == j) printf("* ");
printf("%d ", arr[i]);
}
printf("\n");
// find index of maximum item
for (i = j + 1; i < 10; i++) {
if (arr[i] > arr[imax]) {
imax = i;
}
}
// swap first unsorted item and maximum item
arr[j] = arr[imax];
arr[imax] = swap;
}
// print fully sorted array
for (i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("*\n");
return 0;
}
Use i and j.
N is 10 and the data consists of shuffled numbers 0 to N-1.
j goes from 0 to N-1. At each step, you want to fill it with
the maximum of the unprocessed input.
So i goes from j+1 to N-1, in the inner loop. If arr[j] < arr[i],
swap arr[i] and arr[j].
It speeds up considerably as you get towards the end.

Creating a 2D array board

I am trying to create a 2d matrix board which side is determined by the user input. I created the two D array but it is not printing the right numbers. For example if the user enters 3, it is suppose to create a 3 * 3 board with the number 8, 7, 6, 5, 4, 3, 2, 1, 0.
However it keeps printing the same numbers in each row eg 876, 876, 876
I know it is doing what I have written but I cant figure out how to correct it...I am thinking that I need a counter that resets to zero and perhaps the [i][j] = counter's value.
Anyway here is the code that is giving the trouble.
for (i =0; i< row; i++)
{
for (j =0; j < col; j++)
{
game [i][j] = ((row * row)-1) - j;
printf( "%i", game[i][j] );
}
How can I populate the board so it prints from (row * col) - 1 to zero. Thanks a million.
for ((i=0, k=0); i< row; i++)
{
for (j =0; j < col; j++)
{
game [i][j] = ((row * col)-1) - (k++);
printf( "%i", game[i][j] );
}
}
The basic mistake in the code is that, in each iteration, the value getting subtracted from the game[i][j] gets re-initialized to 0. Since, the value of (row * col) is constant for a given value of both, subtracting (0, 1, 2) each time from the sum results in the reproduction of the same numbers.
As given in the example, row=3, col=3, so 3*3 = 9 (Indexed from 0 to 8).
So, we do :
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
again j gets re-init to 0, so again we have,
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
.
The solution is, the value getting subtracted should get uniformly reduced, such that it doesn't get re-init inside the loop.
Result :
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
8 - 3 = 5
.
.
.
.
8 - 8 = 0.
Hope this clears the problem.
As suggested by "self", using a third variable is the easiest way (and actually the most efficient : only one decrement per iteration)
int count = row * col - 1;
for (size_t i =0; i< row; i++)
{
for (size_t j =0; j < col; j++)
{
game [i][j] = count--;
printf( "%i", game[i][j] );
}
}
Output:
24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Optimize a summing of array (subset problem)

In the hottest part of my program (90% of time according to gprof), I need to sum one array A into another B. Both arrays are 2^n (n is 18..24) sized and holds an integer (for simplicity, actually the element stored is mpz_t or small int array). The rule of summing: for each i in 0..2^n-1, set B[i] = sum (A[j]), where j is bit vector, and j & ~ i == 0 (in other words, k-th bit of any j can't be set to 1 if k-th bit of i is not 1).
My current code (this is a body of innermost loop) does this in the time of 2^(1.5 * n) sums, because I will iterate for each i on (in average) 2^(n/2) elements of A.
int A[1<<n]; // have some data
int B[1<<n]; // empty
for (int i = 0; i < (1<<n); i++ ) {
/* Iterate over subsets */
for (int j = i; ; j=(j-1) & i ) {
B[i] += A[j]; /* it is an `sum`, actually it can be a mpz_add here */
if(j==0) break;
}
}
My I mentioned, that almost any sum is recomputed from the values, summed earlier. I suggest, there can be code, doing the same task in the time of n* 2^n sums.
My first idea is that B[i] = B[i_without_the_most_significant_bit] + A[j_new]; where j_new is only j's having the most_significant bit from i in '1' state. This halves my time, but this is not enough (still hours and days on real problem size):
int A[1<<n];
int B[1<<n];
B[0] = A[0]; // the i==0 will not work with my idea and clz()
for (int i = 1; i < (1<<n); i++ ) {
int msb_of_i = 1<< ((sizeof(int)*8)-__builtin_clz(i)-1);
int i_wo_msb = i & ~ msb;
B[i] = B[i_wo_msb];
/* Iterate over subsets */
for (int j_new = i; ; j_new=(j_new-1) & i ) {
B[i] += A[j_new];
if(j_new==msb) break; // stop, when we will try to unset msb
}
}
Can you suggest better algorithm?
Additional image, list of i and j summed for each i for n=4:
i j`s summed
0 0
1 0 1
2 0 2
3 0 1 2 3
4 0 4
5 0 1 4 5
6 0 2 4 6
7 0 1 2 3 4 5 6 7
8 0 8
9 0 1 8 9
a 0 2 8 a
b 0 1 2 3 8 9 a b
c 0 4 8 c
d 0 1 4 5 8 9 c d
e 0 2 4 6 8 a c e
f 0 1 2 3 4 5 6 7 8 9 a b c d e f
Note the similarity of figures
PS the msb magic is from here: Unset the most significant bit in a word (int32) [C]
Divide and conquer anyone? Now not in-place.
void sums(int *a, int n, int *b) {
if (n <= 0) {
*b = *a;
return;
}
int m = 1 << (n - 1);
sums(a, n - 1, b);
sums(a + m, n - 1, b + m);
for (int i = 0; i < m; i++) {
b[m + i] += b[i];
}
}

Resources