How can I make my Code work on Larger Inputs - c

I'm trying to solve the hacker rank question "Small triangle, Large triangle"
I have to arrange triangle by increasing order of area
the code I wrote is working fine on smaller input given by me but fails on the larger inputs, after taking inputs I just get terminated
eg,
working on input
3
7 24 25
5 12 13
3 4 5
not working when
10
67 67 19
3 57 55
33 33 49
61 58 59
23 43 35
48 42 45
23 12 27
41 34 22
26 49 35
63 46 45
unable to understand why!! Thank YOU!! in advance
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct triangle
{
int a;
int b;
int c;
};
typedef struct triangle triangle;
void sort_by_area(triangle *tr, int n)
{
int *p = (int*)malloc(n * sizeof(int));
int *middle = (int*)malloc((3*n)*sizeof(int));
// doing sum of side of triangle
for (int i = 0; i < n; i++)
{
p[i] = tr[i].a + tr[i].b + tr[i].c;
}
// arranging sum in increasing order
// as more the sum of a+b+c more its area in herons formula
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (p[i] < p[j])
{
int temp;
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
int num = 0;
// storing sides in increasing order in middle
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (p[i] == tr[j].a + tr[j].b + tr[j].c)
{
middle[num] = tr[j].a;
num++;
middle[num] = tr[j].b;
num++;
middle[num] = tr[j].c;
num++;
}
}
}
num=0;
// copying increassed order in tr poiinter in question
for (int i = 0; i < n; i++)
{
tr[i].a = middle[num];
num++;
tr[i].b = middle[num];
num++;
tr[i].c = middle[num];
num++;
}
}
int main()
{
int n;
scanf("%d", &n);
triangle *tr = malloc(n * sizeof(triangle));
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for (int i = 0; i < n; i++) {
printf("%d %d %d\n", tr[i].a, tr[i].b, tr[i].c);
}
return 0;
}

It's kind of strange that your function is called sort_by_area but it doesn't seem to calculate any area. Instead it seems to calculate the perimeter of the triangles.
Anyway... there is a bug here. (note: There may be other bugs but to start with you need to fix this)
int *middle = (int*)malloc((3*n)*sizeof(int));
...
...
int num = 0;
// storing sides in increasing order in middle
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (p[i] == tr[j].a + tr[j].b + tr[j].c)
{
middle[num] = tr[j].a;
num++;
middle[num] = tr[j].b;
num++;
middle[num] = tr[j].c;
num++;
}
}
}
You have two nested loops going from 0 to n. When the if statement is true, you increment num 3 times.
So in case p[i] == tr[j].a + tr[j].b + tr[j].c is always true (which is possible), you end up with num being equal to 3*n*n.
And you use num as index into middle but middle is only allocated to hold 3*n integers.
So you are writing outside the allocated area. That's undefined behavior.
BTW
When sorting arrays in C you should nearly always use qsort

Related

I have written a C code for a pattern but there is a small mistake which I've done which I'm not able to identify

My output of the code is:
1
1 2
3 5 8
13 21 34 55
89 144 233 377 610
My desired output is:
1
1 2
3 5 8
13 21 34 55
89 144 233 377 610
Can you please let me know where do I have to change the code.
#include <stdio.h>
int fib(int);
int main() {
int i, j, k = 1;
for (i = 1; i <= 5; i++) {
for (j = 1; j <= i; j++) {
printf("%d ", fib(k++));
}
printf("\n");
}
return 0;
}
int fib(int n) {
if (n <= 1)
return n;
return (fib(n - 1) + fib(n - 2));
}
The space between each number is the same in my output, but in the desired output all the elements are properly sorted which makes them appear in the same columns.
Use the following call of printf
printf("%-8d", fib(k++));
^^^^
instead of
printf("%d ", fib(k++));
There are 2 ways to achieve the desired appearance:
you can use TAB as a separator, which will make the numbers aligned on tab stops, usually 8 characters apart on most terminals, but as you can see from how your question appears on stackoverflow, can be 4 characters apart in other places.
you can use the "%-7d " format which pads the number with spaces to its right if it has less than 7 digits, and an extra space to separate it from the next in all cases.
Here is a modified version using printf to align the columns:
#include <stdio.h>
int fib(int);
int main() {
int i, j, k = 1;
for (i = 1; i <= 5; i++) {
for (j = 1; j <= i; j++) {
printf("%7d ", fib(k++));
}
printf("\n");
}
return 0;
}
int fib(int n) {
if (n <= 1)
return n;
return fib(n - 1) + fib(n - 2);
}
Here is a different version using TABs, that produces the expected output:
#include <stdio.h>
int fib(int);
int main() {
int i, j, k = 1;
for (i = 1; i <= 5; i++) {
for (j = 1; j <= i; j++) {
printf("%d", fib(k++));
if (j < i)
printf("\t");
else
printf("\n");
}
}
return 0;
}
int fib(int n) {
if (n <= 1)
return n;
return fib(n - 1) + fib(n - 2);
}

Sorting array C program

I need to make a program which sorts out a given array in such a way that the numbers with the same digits will be in front. The order must remain the same. It would be a big problem but I'm not allowed to use any addiodional arrays, functions etc. I really don't know how to sort out the numbers so that the order remains the same. And also the array is max 100 elements.
Example:
Input:
1 22 43 444 51 16 7 8888 90 11
Output:
1,22,444,7,8888,11,43,51,16,90.
I've written this so far:
#include <stdio.h>
int main()
{
int a = 0, i = 0, niz[100], temp, N, j, logika, cifra1, cifra2, brojac = 0, brojac2 = 1;
printf("Unesite brojeve: \n");
do {
scanf("%d", &niz[i]);
if (niz[i] == -1) {
i--;
break;
}
i++;
} while (i < 100);
N = i;
for (i = 0; i < N; i++) {
a = niz[i];
logika = 1;
cifra1 = a % 10;
cifra2 = niz[i] / 10;
while (cifra2) {
if (cifra2 % 10 != cifra1) {
logika = 0;
break;
}
cifra2 = cifra2 / 10;
}
if (a / 10 == 0) logika = 1;
if (logika == 1) {
niz[brojac++] = niz[i];
}
if (logika == 0) {
niz[i] = temp;
niz[N - 1] = niz[i];
niz[N - i] = temp;
}
}
printf("Nakon preslaganja niz glasi: \n");
for (i = 0; i <= N; i++) {
if (i < N)
printf("%d,", niz[i]);
else {
printf("%d.", niz[i]);
}
}
return 0;
}
#include <stdio.h>
enum { MAX_NUMBERS = 100 };
int main(void)
{
int numbers[MAX_NUMBERS];
int numbers_count = 0;
int input;
puts("Please enter your numbers, end input with -1:");
while (numbers_count < MAX_NUMBERS && scanf(" %d", &input) == 1 && input != -1)
numbers[numbers_count++] = input;
int current_insertion_point = 0; // where to insert
for (int i = 0; i < numbers_count; ++i) {
int all_digits_the_same = 1;
// check if number only contains one probably repeated digit:
int current_number = numbers[i];
int last_digit = -1;
while (current_number && all_digits_the_same) {
int current_digit = current_number % 10;
current_number /= 10;
if (last_digit != -1 && current_digit != last_digit)
all_digits_the_same = 0;
last_digit = current_digit;
}
// insert the number:
if (all_digits_the_same) {
int temp = numbers[i];
// nove the range current_insertion_point ... i to the right
for (int k = i; k > current_insertion_point; --k)
numbers[k] = numbers[k - 1];
// so there is space to insert the number previously numbers[i]
numbers[current_insertion_point++] = temp;
}
}
for (int i = 0; i < numbers_count; ++i)
printf("%d ", numbers[i]);
putchar('\n');
}
Output:
Please enter your numbers, end input with -1:
1 22 43 444 51 16 7 8888 90 11 -1
1 22 444 7 8888 11 43 51 16 90
I have done selection sort.It's not giving output as you expecting exactly.
#include<iostream>
using namespace std;
int main(){
int x;
cout<<"Enter Size Of Array";
cin>>x;
const int SIZE=x;
int a[SIZE];
int copy[SIZE];
cout<<"Enter "<<SIZE<<" Value";
for(int i=0;i<SIZE;i++){
cin>>a[i];
}
for(int i=0;i<SIZE;i++){
copy[i]=a[i];
}
for(int i=0;i<SIZE;i++){
int n=a[i];
int temp;
int rem=n%10;
bool isAllDigitSame=false;
while(n!=0){
if(rem==n%10){
isAllDigitSame=true;
}
else{
isAllDigitSame=false;
break;
}
n=n/10;
}
if(isAllDigitSame){
temp=a[i];
a[i] = a[i]%10;
}
}
cout<<"A="<<endl;
for(int i=0;i<SIZE;i++){
cout<<a[i]<<endl;
}
cout<<endl;
for(int i=0;i<SIZE;i++){
int min=i;
for(int j=i;j<SIZE;j++){
if(a[j]<a[min]){
min=j;
}
}
int temp;
temp=copy[i];
copy[i]=copy[min];
copy[min]=temp;
temp=a[i];
a[i]=a[min];
a[min]=temp;
}
cout<<"Copy="<<endl;
for(int i=0;i<SIZE;i++){
cout<<copy[i]<<endl;
}
return 0;
}
It is sorting other element also.
Input :1 22 43 444 51 16 7 8888 90 11
Output: 1 11 22 444 7 8888 16 43 51 90

Compute how many possibilities of summing numbers from a matrix that are equal with another number

I have this problem where I need to compute the number of ways in which elements that are consecutive in a matrix can be summed in order to obtain a certain number. Let me give you an example :
Searched number = 42
Matrix :
00 03 07 09 10
09 13 20 05 20
12 11 33 00 12
17 39 22 03 18
12 15 31 01 17
There are 4 possibilities to obtain 42 : 42 = 10+20+12 =
9 + 13 + 20 = 9 + 11 + 22 = 20 + 0 + 22.
I don't succeed in checking the sum diagonally .I succeeded in transversing the matrix diagonally but my algorithm is not doing the correct sum:
int getNumbers(int **arr,int length,int number){
int count=0;
//check sum each row / horizontally
for(int i=0;i<length;i++){
for(int j=0;j<length;j++){
int sum=0;
int k=j;
do{
if(arr[k][j]!=number){
sum=sum+arr[i][k];
}
k++;
}while(sum<number && k<length);
if(sum==number){
count++;
}
}
}
//check sum each column/ vertically
for(int j=0;j<length;j++){
for(int i=0;i<length;i++){
int sum=0;
int k=i;
do{
if(arr[k][j]!=number){
sum=sum+arr[k][j];
}
k++;
}while(sum<number && k<length);
if(sum==number){
count++;
}
}
}
//check sum each diagonally
for (int j = 0; j < 2 * length - 1; j++) {
for (int i = 0; i < length; i++) {
int row = i;
int col = j - i;
int sum=0;
if (col >= 0 && col <= length - 1) {
do{
if(arr[row][col]!=number){
sum=sum+arr[row][col];
}
}while(sum<number && row<length && col<length);
if(sum==number){
count++;
}
}
}
}
for (int j = 0; j < 2 * length - 1; j++) {
int z = (j < length) ? 0 : j - length + 1;
int len = j + 1 - 2 * z;
for (int i = 0; i < len; i++) {
int sum=0;
int row = length - 1 - i - z;
int col = j - i - z;
do{
if(arr[row][col]!=number){
sum=sum+arr[row][col];
}
}while(sum<number && row<length && col<length);
if(sum==number){
count++;
}
}
}
return count;
}
For a working solution it is enough to replicate the stretegy that you used for the horizontal and vertical cases, that is:
Consider each cell as a possible starting point, except the ones at the borders
Traverse in the desired direction
A solution for left-right and top-bottom diagonals would be:
for(int j=0; j < length-1; j++)
{
for(int i=0; i < length-1; i++)
{
if(arr[i][j] == number)
continue;
int sum=0;
int localColumn = i;
int localRow = j;
do{
sum += arr[localRow][localColumn];
localColumn++;
localRow++;
}
while( sum < number && localRow < length && localColumn < length);
if(sum==number){
count++;
}
}
}
Note that I moved the check for the single 42 cell out of the do while loop: your code just skips it during the sum, making a sequence like 20 42 22 valid.

Sieve of Eratosthenes C implementation error

So I am making next homework with input numbers to be dissolved to primes multiplication in output. I was confused when it showed up only prime number 2, so I did a proper control dump of the allocated primes array using this function:
long* eratosthen(long max) {
bool grid[max + 1];
for(long i = 0; i < max + 1; ++i) {
grid[i] = true;
}
for(long i = 2; i < max + 1; ++i) {
if(grid[i]) {
for(long j = i * 2; j < max + 1; ++j) {
grid[j] = false;
}
}
}
long *primes;
primes = (long*)malloc((max + 1) * sizeof(long));
long index = 0;
for(long i = 2; i < max + 1; ++i) {
if(grid[i]) {
primes[index++] = i;
}
}
return primes;
}
For some unknown reason, the dump says 2 only and ends. Calling for dump is made up by following code:
int main(void) {
// Prime numbers get calculated first
long *primes;
primes = eratosthen(1000000);
// Control code
fprintf(stdout, "Control dump of primes array:\n");
for(long i = 0; i < sizeof(primes) / sizeof(long); ++i) {
fprintf(stdout, "%li\n", primes[i]);
}
int ret = 0;
/// ...
return ret;
}
//EDIT: So after all your answers I'll update my question to current state. Main program:
int main(void) {
// Prime numbers get calculated first
long *primes;
primes = eratosthen(1000000);
// Control code
fprintf(stdout, "Control dump of primes array:\n");
for( ; *primes != 0 ; primes++) {
fprintf(stdout, "%li\n", *primes);
}
int ret = 0;
}
Generation of primes function:
long* eratosthen(long max) {
bool *grid;
grid = (bool*)malloc((max + 1) * sizeof(bool));
index = 0;
for(long i = 0; i < max + 1; ++i) {
*(grid + index) = true;
index++;
}
index = 2;
index_2 = 2;
for(long i = 2; i < max + 1; ++i) {
if(*(grid + index)) {
for(long j = i * 2; j < max + 1; j += i) {
*(grid + 2 * index_2) = false;
index_2++;
}
index++;
}
}
long *primes;
primes = (long *)malloc((max + 1) * sizeof(long));
index = 0;
for(long i = 0; i < max + 1; ++i) {
*(primes + index) = 0;
index++;
}
index = 0;
index_2 = 2;
for(long i = 2; i < max + 1; ++i) {
if(*(grid + index_2)) {
*(primes + index) = i;
index++;
index_2++;
}
}
// free the grid
free(grid);
return primes;
}
Like said before, the Ubuntu terminal displays following line:
Neoprávněný přístup do paměti (SIGSEGV) (core dumped [obraz paměti uložen])
translated like this:
Forbidden access to memory (SIGSEGV) (core dumped [memory image saved])
What does it mean and how to get rid of that? :(
The simplest fix to your code is probably to add a sentinel value of 0 to the end of the array of primes, and to rewrite the check condition in main(). As explained extensively in the comments, your current test:
for(long i = 0; i < sizeof(primes) / sizeof(long); ++i) {
is irremediably wrong. You must not attempt to use sizeof because it simply doesn't do what you want it to do.
This code works:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
static
long *eratosthen(long max)
{
bool grid[max + 1];
for (long i = 0; i < max + 1; ++i)
grid[i] = true;
for (long i = 2; i < max + 1; ++i)
{
if (grid[i])
{
for (long j = i * 2; j < max + 1; j += i) // Key fix
grid[j] = false;
}
}
long *primes;
primes = (long *)malloc((max + 1) * sizeof(long));
long index = 0;
for (long i = 2; i < max + 1; ++i)
{
if (grid[i])
primes[index++] = i;
}
primes[index] = 0; // Sentinel
return primes;
}
int main(void)
{
// Prime numbers get calculated first
long *primes = eratosthen(1000000);
fprintf(stdout, "Control dump of primes array:\n");
for (long i = 0; primes[i] != 0; ++i)
{
printf("%7li", primes[i]);
if (i % 10 == 9)
putchar('\n');
}
putchar('\n');
return 0;
}
I revised the code to print 10 numbers per line. I changed the condition in the loop in main(). And I made two key changes in the function — one to calculate multiples of primes correctly, and the other to add the sentinel at the end of the list of primes.
It produces a list of 78,498 primes starting with
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
and ending with:
999563 999599 999611 999613 999623 999631 999653 999667 999671 999683
999721 999727 999749 999763 999769 999773 999809 999853 999863 999883
999907 999917 999931 999953 999959 999961 999979 999983
You might note that the code does not release primes — it arguably should. You might note that the space allocated for the primes greatly exceeds the space needed (one million vs less than eighty thousand); you could use realloc() to shrink the space allocated, or use a less conservative (or do I mean less profligate?) estimate on the number of entries needed.

Input to Multi-Array in C

I am trying to assign user input into an array; however, the program below only picks up on the first element in each line of input. The ultimate goal of this program is to find the diagonal sums of integers and return the absolute value of their difference.
Example input (note that the first number gives the number of rows and columns (square array):
Input:
3
11 2 4
4 5 6
10 8 -12
Output:
Expected = 15
Actual = 10
I realize that the issue lies in the way that the array is setup. If I print the array out I get: 111555999
Any hints/help would be very appreciated.
int main() {
int n, i, c, multi_array[200][200], sum1 = 0, sum2 = 0;
scanf("%i", &n); //N = number of rows and number of columns (square 2D array)
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
scanf("%d ", &multi_array[c][i]); //enter integers to store in array
}
}
for (i = 0; i != n; i++) {
sum1 += multi_array[i][i]; //add up top left to bottom right diagonal
}
for (i = 0; i != n; i++) {
sum2 += multi_array[i][n-i]; //add up top right to bottom left diagonal
}
printf("%i", abs(sum1 - sum2)); //print absolute value of the difference between diagonals
return 0;
}
Your major problem is here, where you go out of bounds:
for (i = 0; i != n; i++) {
sum2 += multi_array[i][n - i]; // when i is 0, th
}
When i = 0, you are accessing multi_array[0][3], which is out of bounds when N = 3.
So change it to this:
multi_array[i][n - i - 1]
You should read your array like this:
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
scanf(" %d ", &multi_array[i][c]);
}
}
since C stored its arrays in row-major order. What you have stores the array in column-major order. It's not wrong, but it's something you do only if you really have to.
Finally, change again the input part of your code to this:
scanf("%d", &n);
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
scanf("%d", &multi_array[i][c]);
}
}
so that you have to input exactly what you need to. With your initial code I have to type an extra random number when I had completed the input process.
Last but not least, I am posting the whole code, where I have wrote some extra printf()'s, which are actually for the programmer, so that he can see step-by-step if his code is acting as expected or not.
#include <stdio.h>
#include <stdlib.h> /* abs */
int main() {
int n, i, c, multi_array[200][200], sum1 = 0, sum2 = 0;
scanf("%d", &n);
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
scanf("%d", &multi_array[i][c]);
}
}
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
printf("|%d|", multi_array[i][c]);
}
printf("\n");
}
for (i = 0; i != n; i++) {
sum1 += multi_array[i][i];
}
printf("sum1 is %d\n", sum1);
for (i = 0; i != n; i++) {
sum2 += multi_array[i][n - i - 1];
}
printf("sum2 is %d\n", sum2);
printf("%i", abs(sum1 - sum2));
return 0;
}
Output:
3
11 2 4
4 5 6
10 8 -12
|11||2||4|
|4||5||6|
|10||8||-12|
sum1 is 4
sum2 is 19
15
You are clearly going out of bounds here:
for (i = 0; i != n; i++) {
sum2 += multi_array[i][n-i]; //add up top right to bottom left diagonal
}
When i is equal to 0 the expression n-i will be equal to n, but the range of the array is from 0 to n-1. The code will read uninitialized values and cause undefined behavior.
The second array index should be 1 less.

Resources