I just started to learn C language. By now I have very basic knowledge. At the moment I am coding some very simple programs from given exercises by my University.
Current exercise I have is: Write a program that finds two largest elements in n element array (2 ≤ n ≤ 10) and outputs sum of those two elements.
The problem is that my written code works only with positive array numbers and doesn't work with negative numbers.
Current code:
#include <stdio.h>
int main() {
int seka[] = {0,0,0,0,0,0,0,0,0,0}; //array in lithuanian = seka
int k; //variable to determine array size
int m = seka[0];
int n = seka[0];
int y = 0;
scanf ("%d",&k);
for(int i = 0; i < k; ++i){
scanf ("%d",&seka[i]);
}
for(int j = 0; j < k; ++j){
if (seka[j] > m)
m = seka[j];
}
for(int o = 0; o < k; ++o){
if (seka[o] == m)
y = y + 1;
}
if(y >= 2){
n = m;
}
else
{
for(int l = 0; l < k; ++l){
if(seka[l] != m)
if (seka[l] > n)
n = seka[l];
}
}
printf ("%d", m + n);
return 0;
}
Input used:
5
4 9 5 6 3
Output got:
15
But if input has negative numbers:
6
-5 -8 -6 -2 -5 -8
Output is:
0
I know that this is not the most efficient approach for given problem, but I am still learning and I hope that you will help me finding the root of the issue.
Fixed my code with your help, now works like it should.
Fixed code:
#include <stdio.h>
int main() {
int seka[] = {0,0,0,0,0,0,0,0,0,0}; //array in lithuanian = seka
int k; //variable to determine array size
int y = 0;
scanf ("%d",&k);
for(int i = 0; i < k; ++i){
scanf ("%d",&seka[i]);
}
int m = seka[0];
for(int j = 1; j < k; ++j){
if (seka[j] > m)
m = seka[j];
}
for(int o = 0; o < k; ++o){
if (seka[o] == m)
y = y + 1;
}
int n;
for(int l = 0; l < k; ++l){
if(seka[l] != m)
if (seka[l] < n)
n = seka[l];
}
if(y >= 2){
n = m;
}
else
{
for(int l = 0; l < k; ++l){
if(seka[l] != m)
if (seka[l] > n)
n = seka[l];
}
}
printf ("%d", m + n);
return 0;
}
You update the max value with
for(int j = 0; j < k; ++j){
if (seka[j] > m)
m = seka[j];
}
but you initialize it with
m = seka[0];
The problem is that seka[0] has not been set by the user, yet, so its value is 0. That's Why the maximum value cannot be less than 0.
In order to fix it, just initialize the maximum with the first element of the array, but after the user input. Then loop starting from index 1:
m = seka[0];
for(int j = 1; j < k; ++j){
if (seka[j] > m)
m = seka[j];
}
Related
How do I make my code more efficient (in time) pertaining to a competitive coding question (source: codechef starters 73 div 4):
(Problem) Chef has an array A of length N. Chef wants to append a non-negative integer X to the array A such that the bitwise OR of the entire array becomes = Y .
Determine the minimum possible value of X. If no possible value of X exists, output -1.
Input Format
The first line contains a single integer T — the number of test cases. Then the test cases follow.
The first line of each test case contains two integers N and Y — the size of the array A and final bitwise OR of the array A.
The second line of each test case contains N space-separated integers A_1, A_2, ..., A_N denoting the array A.
Please don't judge me for my choice of language .
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int* binary_number(int n) // returns pointer to a array of length 20(based on given constrains) representing binary
{
int* ptc;
ptc = (int*) malloc(20*sizeof(int));
for(int i = 0; i < 20; i++)
{
if((n / (int) pow(2,19-i)) > 0){*(ptc + i) = 1;}
else {*(ptc + i) = 0;}
n = n % (int) pow(2,19-i) ;
}
return ptc;
}
int or_value(int* ptc, int n) // Takes in pointers containing 1 or zero and gives the logical OR
{
for(int k = 0; k < n; n++)
{
if(*ptc == *(ptc + 20*k)){continue;} // pointers are 20 units apart
else{return 1;break;}
}
return *ptc;
}
int main(void) {
int t; scanf("%d", &t);
for (int i = 0; i < t; i++)
{
int n, y;
scanf("%d %d", &n, &y);
int a[n];
for(int j = 0; j < n ; j++)
{
scanf("%d", &a[j]);
}
int b[20*n];
for (int j = 0; j < n; j++)
{
for (int k = 0; k < 20; k++)
{
b[20*j + k] = *(binary_number(a[n])+k);
}
}
int c = 0;
int p = 0;
for (int j = 0; j < 20; j++)
{
if ((*(binary_number(y) + j) == 1) && (or_value((&b[0] + j),n) == 0)){c = c + pow(2,19 - j);}
else if ((*(binary_number(y) + j) == 0) && (or_value((&b[0] + j),n) == 1)){p = 1; break;}
}
if (p==1){printf("-1");}
else {printf("%d\n", c);}
}
return 0;
}
This is a C program to find the next greater number with the same digits. This program is working for all given test cases except one. When the input is 472, the expected output is 724. But my output is 247. Can anyone please help me to find the error?
logic I tried to solve this is :
Traverse the given number from rightmost digit, keep traversing till you find a digit which is smaller than the previously traversed digit. For example, if the input number is 534976, we stop at 4 because 4 is smaller than next digit 9. If we do not find such a digit, then output is Not Possible.
Now search the right side of above found digit ‘d’ for the smallest digit greater than ‘d’. For 534976, the right side of 4 contains 976. The smallest digit greater than 4 is 6.
Swap the above found two digits, we get 536974 in above example.
Now sort all digits from position next to ‘d’ to the end of number. The number that we get after sorting is the output. For above example, we sort digits in bold 536974. We get 536479 which is the next greater number for input 534976.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main() {
int N, dig[100], i = 0,j, temp, t, s, k, l, min, temp1;
scanf("%d", &N);
while (N > 0) {
dig[i] = N % 10;
i++;
N = N / 10;
}
for (j = 0; j <= i; j++) {
if (dig[j] > dig[j + 1]) {
s = j;
break;
}
}
min = dig[s];
//printf("%d ", min);
for (k = s; k >= 0; k--) {
if (dig[k] <= min) {
min = dig[k];
t = k;
}
}
//printf("%d ", t);
temp = dig[t];
dig[t] = dig[s + 1];
dig[s + 1] = temp;
for (k = 0; k <= s; k++) {
for (l = k + 1; l <= s; l++) {
if (dig[k] < dig[l]) {
temp1 = dig[k];
dig[k] = dig[l];
dig[l] = temp1;
}
}
}
for (k = i - 1; k >= 0; k--) {
printf("%d", dig[k]);
}
}
Your algorithm seems correct, but the loops are incorrect. Some index boundaries are off by one and the comparisons with <= are incorrect. Storing the digits by increasing powers of 10, while more practical is counter-intuitive and complicates the translation of the algorithm into code.
Here is a corrected version, that outputs all greater numbers. You can easily check the output by piping through sort -c to verify order and wc -l to verify that all combinations have been found (there should be at most n! - 1 greater numbers for a number with n digits).
#include <stdio.h>
int main() {
int N, dig[100], i, j, s, t, k, l, temp;
if (scanf("%d", &N) != 1 || N < 0)
return 1;
for (;;) {
for (i = j = 100; N > 0;) {
dig[--i] = N % 10;
N = N / 10;
}
for (s = j - 2; s >= i; s--) {
if (dig[s] < dig[s + 1]) {
break;
}
}
if (s < i) {
/* no greater number with the same digits */
break;
}
t = s + 1;
for (k = t + 1; k < j; k++) {
if (dig[k] < dig[t] && dig[k] > dig[s]) {
t = k;
}
}
temp = dig[t];
dig[t] = dig[s];
dig[s] = temp;
for (k = s + 1; k < j; k++) {
for (l = k + 1; l < j; l++) {
if (dig[k] > dig[l]) {
temp = dig[k];
dig[k] = dig[l];
dig[l] = temp;
}
}
}
N = 0;
for (k = i; k < j; k++) {
N = N * 10 + dig[k];
printf("%d", dig[k]);
}
printf("\n");
}
return 0;
}
Input: 472
Output:
724
742
I have a binary matrix (zeros and ones) D[][] of dimension nxn where n is large (approximately around 1500 - 2000). I want to find the inverse of this matrix in C.
Since I'm new to C, I started with a 3 x 3 matrix and working around to generalize it to N x N. This works for int values, however since I'm working with binary 1's and 0's. In this implementation, I need unsigned int values.
I could find many solutions for int values but I didn't come across any solution for unsigned int. I'd like to find the inverse of a N x N binary matrix without using any external libraries like blas/lapack. It'd be great if anyone could provide a lead on M x N matrix.
Please note that I need inverse of a matrix, not the pseudo-inverse.
/* To find the inverse of a matrix using LU decomposition */
/* standard Headers */
#include<math.h>
#include<stdio.h>
int main() {
/* Variable declarations */
int i,j;
unsigned int n,m;
unsigned int rows,cols;
unsigned int D[3][3], d[3], C[3][3];
unsigned int x, s[3][3];
unsigned int y[3];
void LU();
n = 2;
rows=3;cols=3;
/* the matrix to be inverted */
D[0][0] = 1;
D[0][1] = 1;
D[0][2] = 0;
D[1][0] = 0;
D[1][1] = 1;
D[1][2] = 0;
D[2][0] = 1;
D[2][1] = 1;
D[2][2] = 1;
/* Store the matrix value for camparison later.
this is just to check the results, we don't need this
array for the program to work */
for (m = 0; m <= rows-1; m++) {
for (j = 0; j <= cols-1; j++) {
C[m][j] = D[m][j];
}
}
/* Call a sub-function to calculate the LU decomposed matrix. Note that
we pass the two dimensional array [D] to the function and get it back */
LU(D, n);
printf(" \n");
printf("The matrix LU decomposed \n");
for (m = 0; m <= rows-1; m++) {
for (j = 0; j <= cols-1; j++){
printf(" %d \t", D[m][j]);
}
printf("\n");
}
/* TO FIND THE INVERSE */
/* to find the inverse we solve [D][y]=[d] with only one element in
the [d] array put equal to one at a time */
for (m = 0; m <= rows-1; m++) {
d[0] = 0;
d[1] = 0;
d[2] = 0;
d[m] = 1;
for (i = 0; i <= n; i++) {
x = 0;
for (j = 0; j <= i - 1; j++){
x = x + D[i][j] * y[j];
}
y[i] = (d[i] - x);
}
for (i = n; i >= 0; i--) {
x = 0;
for (j = i + 1; j <= n; j++) {
x = x + D[i][j] * s[j][m];
}
s[i][m] = (y[i] - x) / D[i][i];
}
}
/* Print the inverse matrix */
printf("The Inverse Matrix\n");
for (m = 0; m <= rows-1; m++) {
for (j = 0; j <= cols-1; j++){
printf(" %d \t", s[m][j]);
}
printf("\n");
}
/* check that the product of the matrix with its iverse results
is indeed a unit matrix */
printf("The product\n");
for (m = 0; m <= rows-1; m++) {
for (j = 0; j <= cols-1; j++){
x = 0;
for (i = 0; i <= 2; i++) {
x = x + C[m][i] * s[i][j];
}
//printf(" %d %d %f \n", m, j, x);
printf("%d \t",x);
}
printf("\n");
}
return 0;
}
/* The function that calcualtes the LU deomposed matrix.
Note that it receives the matrix as a two dimensional array
of pointers. Any change made to [D] here will also change its
value in the main function. So there is no need of an explicit
"return" statement and the function is of type "void". */
void LU(int (*D)[3][3], int n) {
int i, j, k;
int x;
printf("The matrix \n");
for (j = 0; j <= 2; j++) {
printf(" %d %d %d \n", (*D)[j][0], (*D)[j][1], (*D)[j][2]);
}
for (k = 0; k <= n - 1; k++) {
for (j = k + 1; j <= n; j++) {
x = (*D)[j][k] / (*D)[k][k];
for (i = k; i <= n; i++) {
(*D)[j][i] = (*D)[j][i] - x * (*D)[k][i];
}
(*D)[j][k] = x;
}
}
}
This is just a sample example that I tried and I have -1 values in the inverse matrix which is my main concern. I have 1000 x 1000 matrix of binary values and the inverse should also be in binary.
The matrix:
1 1 0
0 1 0
1 1 1
The matrix LU decomposed:
1 1 0
0 1 0
1 0 1
The Inverse Matrix:
1 -1 0
0 1 0
-1 0 1
The product:
1 0 0
0 1 0
0 0 1
#include <stdio.h>
int main() {
int N = 133;
int a, b, c, d;
int flag = 0;
for ( int j = 1; j < (N/2); j++)
{
a = j;
for ( int k = 1; k < (N/2); k++)
{
b = k;
for ( int l = 1; l < (N/2); l++)
{
c = l;
for ( int m = 1; m < (N/2); m++)
{
d = m;
if ( a+b+c+d == N && (a != 0 && b!= 0 && c != 0 && d!= 0))
{
printf("\n %d + %d + %d + %d = %d" , a, b, c, d, N);
flag = 1;
break;
}
}
if(flag)
break;
}
if(flag)
break;
}
if(flag)
break;
}
return 0;
}
The code currently outputs
1 + 2 + 65 + 65 = 133
As you can see, I am getting the sum using 4 numbers to form N (133) in this case. Is there a way to improve the code to 'k' numbers without using nested 'k' for loops?
Desired Output: ( a + b + c + d + e + f + ...... + k = N )
say for a given value of N represented using sum of k terms, where k is an input parameter.
Notes:
None of the 'k' terms is zero.
Original question had loops starting from 0; updated to start from 1.
Specific Requirement, I want the terms (a to k) to have the lowest possible standard deviation among all the sums. So breaking out at the first sum is not ideal for that scenario, but this is the baseline code I have reached. Once I figure out reducing number of loops, I know how to modify for lowest S.D.
Also pretty obvious but k < N in all cases.
Much simpler code that does the same thing as yours:
#include <stdio.h>
int main()
{
int N = 133;
for ( int j = 1; j < (N/2); j++)
for ( int k = 1; k < (N/2); k++)
for ( int l = 1; l < (N/2); l++)
for ( int m = 1; m < (N/2); m++)
if ( j+k+l+m == N) {
printf("\n %d + %d + %d + %d = %d" , j, k, l , m, N);
return 0;
}
}
And to your problem, which is a bit vague, but seems to be finding k numbers a_1, a_2 ... a_k such that 1 < a_n < N/2 for all n and a_1+a_2+...+a_k=N. Here is very simple code to do that, using your algorithm but extended for arbitrary k:
#define N 133
#define k 8
int main()
{
int arr[k];
for(int i=0; i<k; i++)
arr[i]=1;
for(int i=0,c=k; c<N; c++) {
arr[i]++;
if(arr[i]>=N/2) {
c--;
i++;
}
}
for(int i=0; i<k-2; i++)
printf("%d + ", arr[i]);
printf("%d = %d\n", arr[k-1], N);
}
It has no error checking. The problem is not solvable for k=1 and k>N. And because integer division is rounded down, it is not solvable for k=2 if N is odd.
But here is some MUCH more efficient code. The problem is very simple, so it's not about finding the numbers a_1, a_2, a_3 ... a_k. It's really only about finding a_1 and a_2. The rest are one.
#define N 19
#define k 5
int main()
{
for(int i=0; i<k-2; i++)
printf("1 + ");
int c=N/2-(k-2);
if (c<1)
c=1;
printf("%d + ", c);
printf("%d = %d\n", N-(k-2)-c, N);
}
Again, no error check is made.
I need to know how to find the biggest sum of a given scope in a 2D array, preferably in C to improve the efficiency of the code give below and solve the problem.
To understand this better, read the problem I need to solve below.
Problem
The great city X is a grid of N rows and M columns. There are given
number of people living in each cell. You are asked to position the
telecommunication tower so that as many as people are satisfied. The
cellular tower can cover a rectangular area of Y rows and X columns.
Find the maximum number of people you can satisfy.
Constrains
1 <= N, M <= 1000
1 <= Y <= N, 1 <= X <= M
1 <= number of people in a cell <= 1000
Rectangular area covered by the celluar tower should not cover any cell partially.
Input
First line of the input will contain 4 digits N, M, Y and X respectively separated by spaces. Each of next N lines with contains integers of row 1 to N. Each row will M integers giving the number of people living in each cell separated by spaces.
Output
Output should contain only one integer, the maximum number of people you can satisfy.
Sample Input
4 5 2 3
3 1 1 1 2
2 5 6 7 1
1 2 9 9 1
1 1 1 1 1
Sample Output
38
Explanation
Maximum number of people can be satisfied by placing the tower covering 2x3 area that consists of 5, 6, 7, 2, 9 and 9 cells.
5 + 6 + 7 + 2 + 9 + 9 = 38
My code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int N, M, Y, X;
scanf("%d %d %d %d", &N, &M, &Y, &X);
int max = 0;
int total = 0;
int data[N][M];
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++)
scanf("%d",&(data[i][j]));
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
total = 0;
for(int l = 0; (l < Y) && (i + Y) <= N; l++)
{
for(int k = 0; (k < X) && (j + X <= M); k++)
{
total += data[i+l][j+k];
}
if(total > max)
max = total;
}
}
}
printf("%d",max);
return 0;
}
This code fails because it's too linear and takes a lot of time when a larger input is used.
You can try out the problem yourself, here
I suppose the main problem in your solution of Number Grid problem is nested for loops. The simplest optimization is to minimaze number of recalculations for each move of the scope.
I tryed the following changes in the original code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
int N, M, Y, X;
scanf("%d %d %d %d", &N, &M, &Y, &X);
int max = 0;
int total = 0;
int data[N][M];
for(int i = 0; i < N; i++)
for(int j = 0; j < M; j++)
scanf("%d",&(data[i][j]));
////////////////////////////////////////////////////////////
// calculation of the first total and initial max
int startTotal = 0;
int r, c;
for(r = 0; r < Y-1; r++)
{
for(c = 0; c < X-1; c++)
{
startTotal += data[r][c];
}
}
max = startTotal;
for(int i = 0; i+Y <= N; i++)
{
// add next line
for(int c = 0; c < X-1; c++)
{
startTotal += data[i+Y-1][c];
}
total = startTotal;
for(int j = 0; j+X <= M; j++)
{
// add next column
for(int r = i; r < i+Y; r++)
total += data[r][j+X-1];
// compare
if(total > max)
{
max = total;
}
// subtract the first column
for(int r = i; r < i+Y; r++)
total -= data[r][j];
}
// subtract the first line
for(int c = 0; c < X-1; c++)
{
startTotal -= data[i][c];
}
}
////////////////////////////////////////////////////////
printf("%d",max);
return 0;
}
I have tryed to run the program at hackerrank.com, and received