Unexpected output at a particular row for a dynamic 2D array - c

I was solving a programing question for displaying Pascal triangle. In the code, I have set the last element of every row equal to zero. Still, the 6th row produces the output as 50 for the last element. I'm unable to figure out the reason for this. Kindly help. The code is attached.
int ** generate(int A, int *number_of_rows) {
*number_of_rows = A;
int i,j,nc=0;
int **result = (int**)malloc(A * sizeof(int *));
for(i=0;i<A;i++)
{
nc=i+1;
result[i]=(int)malloc(nc*sizeof(int));
result[i][0]=nc;
result[i][1] = 1;
for(j=2;j<nc;j++)
{
result[i][j]=result[i-1][j]+result[i-1][j-1];
}
}
return result;
}
Edit:
The first element of every row displays the number of columns in that row.

#include <stdio.h>
#include <stdlib.h>
int ** generate(int A, int *number_of_cols) {
int **result = malloc(A * sizeof(int *));
int nc;//number of columns
for(int i = 0; i < A; ++i){
number_of_cols[i] = nc = i + 1;
result[i] = malloc(nc * sizeof(int));
result[i][0] = result[i][nc-1] = 1;
if(i > 1)
for(int j = 1; j < nc -1; ++j){
result[i][j] = result[i-1][j-1] + result[i-1][j];
}
}
return result;
}
int main(void){
int n;
scanf("%d", &n);
int *number_of_cols = malloc(n * sizeof(int));
int **pascal_triangle = generate(n, number_of_cols);
for(int i = 0; i < n; ++i){
printf("%*s", 2 * (n-i-1), "");
for(int j = 0; j < number_of_cols[i]; ++j){
printf("%4d", pascal_triangle[i][j]);
}
puts("");
free(pascal_triangle[i]);
}
free(pascal_triangle);
free(number_of_cols);
return 0;
}

I can't understand the purpose of passing the *number_of_row just to assign it the other parameter address. However, I'd split your main for loop in 2:
one to allocate all memory and another to fill it.
for(i=0;i<A;i++)
result[i]=(int)malloc((i+1)*sizeof(int));
result[0][0]=1; //in your code, result[i-1] was accessed with i=0
for(i=1;i<A;i++) {
result[i][0] = i+1;
result[i][1] = 1;
for(j=2;j<i;j++)
result[i][j] = result[i-1][j] + result[i-1][j-1]; //when j reaches the last value,
//[i-1][j] won't work! So put j<i instead.
result[i][j] = 1;
}
The rest of code was OK, check if this is what you wanted. The resulting triangle shoud be:
1
2 1
3 1 1
4 1 2 1
5 1 3 3 1
6 1 4 6 4 1 etc.

Related

Can't figure out what's wrong with my code for a HackerRank problem in C

I'm sorry to ask help for a HackerRank problem here, I know it's not really the right place but nobody is answering me on HackerRank. Also, I'm new in C, so don't be to rude please.
Problem's description:
You are given n triangles, specifically, their sides a, b and c. Print them in the same style but sorted by their areas from the smallest one to the largest one. It is guaranteed that all the areas are different.
Link to the problem : https://www.hackerrank.com/challenges/small-triangles-large-triangles/problem
We can only edit the sort_by_area function.
First of all, I didn't calculate the triangles' area, I've just calculated the perimeter of each triangle, because the formula is simpler to read and to execute. Normally, that doesn't change anything for the result since a bigger perimeter means a bigger area. Tell me if I'm wrong.
The problem is that I have unexpected results: there's numbers on a line from my output that I really don't know from where they come. See:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
int a;
int b;
int c;
} triangle;
void sort_by_area(triangle *tr, int n) {
// Array for storing the perimeter.
int *size = malloc(100 * sizeof(*size));
// Adding perimeters in size array.
for (int i = 0; i < n; i++) {
size[i] = tr[i].a + tr[i].b + tr[i].c;
}
// Sort.
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (size[j] > size[j + 1]) {
// Sort in size array.
int temp = size[j];
size[j] = size[j + 1];
size[j + 1] = temp;
// Sort in tr array.
temp = tr[j].a;
tr[j].a = tr[j + 1].a;
tr[j + 1].a = temp;
temp = tr[j].b;
tr[j].b = tr[j + 1].b;
tr[j + 1].b = temp;
temp = tr[j].c;
tr[j].c = tr[j + 1].c;
tr[j + 1].c = temp;
}
}
}
}
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;
}
Input:
3
7 24 25
5 12 13
3 4 5
Output:
0 417 0 // Unexpected results on this line.
3 4 5
5 12 13
Expected output:
3 4 5
5 12 13
7 24 25
It seems that an error occurs from the 7 24 25 triangle, but for me, my code seems to be good.... Can you help to find out what's wrong ? I really want to understand before going to another problem.
The assumption that a greater parameter implies a greater area is incorrect. Why? Imagine an isosceles triangle with a base of 1000 units and a height of 1e-9 units. The area is minuscule, compared to an equilateral triangle with unit length whereas the former has a huge perimeter (~2000 units) compared to the latter (3 units). That's just an (extreme) example to convey the flaw in your assumption.
I'd suggest you roll up your own area function. It's even mentioned on the problem page to use Heron's formula. Since it's just to be used in the comparison, then we don't need the exact area but an indicative area. So something like
double area(triangle const* tr) {
if(tr) {
double semiPerimeter = (tr->a + tr->b + tr->c)/2.0;
return semiPerimeter* (semiPerimeter - tr->a) * (semiPerimeter - tr->b) * (semiPerimeter - tr->c);
} else {
return 0;
}
}
Where we don't really need to calculate the square root since we just need to compare the areas across triangles and comparing the square of areas across triangles should be fine.
After this, it's just a matter of plugging this into whatever you did, after correcting the inner j loop to run only till n-1 (as the other answer has also explained)
void sort_by_area(triangle* tr, int n) {
/**
* Sort an array a of the length n
*/
double areaArr[n];
for(size_t i = 0; i < n; ++i) {
areaArr[i] = area(&tr[i]);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - 1; j++) {
if (areaArr[j] > areaArr[j + 1]) {
// Sort in area array.
int temp = areaArr[j];
areaArr[j] = areaArr[j + 1];
areaArr[j + 1] = temp;
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
}
}
}
}
You could directly use qsort too here since the problem doesn't prohibit using standard functions, something like:
int qsortCompare(void const* a, void const* b) {
triangle const* trA = a;
triangle const* trB = b;
if(trA && trB) {
double areaA = area(trA);
double areaB = area(trB);
return (areaA < areaB) ? -1 :
((areaA > areaB)? 1: 0);
}
return 0;
}
void sort_by_area(triangle* tr, int n) {
qsort(tr, n, sizeof(triangle), &qsortCompare);
}
Also, don't be restricted to add functions in the problem solution. The actual driver code only calls sort_by_area() but you can write other functions in the solution and call them from sort_by_area().
The inner loop does not need to run till n, only till n-1
for (int j = 0; j < n - 1; j++)
Because when j == n, then you are comparing with random junk outside of your respective arrays by accessing size[j+1] and tr[j+1].
Also, when swapping, you don't need to copy the structure members one-by-one. You can simply do:
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
Edit: As #CiaPan pointed out:
You have a memory leak. You need to call free() after you are done with using the malloc'd memory.
You are not allocating the right amount of memory. If you are passed more than 100 triangles, your code might behave weirdly or randomly crash.
int *size = malloc(n* sizeof(*size));
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
int a;
int b;
int c;
} triangle;
void sort_by_area(triangle *tr, int n) {
// Array for storing the perimeter.
int *size = malloc(n* sizeof(*size));
// Adding perimeters in size array.
for (int i = 0; i < n; i++) {
size[i] = tr[i].a + tr[i].b + tr[i].c;
}
// Sort.
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - 1; j++) {
if (size[j] > size[j + 1]) {
// Sort in size array.
int temp = size[j];
size[j] = size[j + 1];
size[j + 1] = temp;
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
}
}
}
}
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;
}

Printing unique values of the array in C

I wrote a function creating a dynamic array of random values and another function creating a new array consisting of unique values of the previous array. The algorithm used counts unique values correctly. However, I faced a problem in printing all values. In the example below the program printed 7 2 12714320 4 5 instead of 7 2 4 5 6 .
This is the program which can be tested:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int *delduplicate(int *v, int size_old, int *size_new);
main()
{
int n;
int *norepeat;
float *results;
int dim, size_norepeat, i;
int a[7] = {7,2,2,4,5,6,7};
norepeat = delduplicate(a, 7, &size_norepeat);
for (int i = 0; i < size_norepeat; i++)
printf("%d ", norepeat[i]);
}
// delduplicate function
int *delduplicate(int *v, int size_old, int *size_new)
{
int i, j, k = 1, uniques = 1, repeats, *new_v, temp;
// count the number of unique elements
for (i = 1; i < size_old; i++)
{
int is_unique = 1;
for (j = 0; is_unique && j < i; j++)
{
if (v[i] == v[j])
is_unique = 0;
}
if (is_unique)
uniques++;
}
*size_new = uniques;
// create new array of unique elements
new_v = (int*) malloc(*size_new * sizeof(int));
// fill new array with unique elements
new_v[0] = v[0];
for (i = 1; i < size_old; i++)
{
int is_unique = 1;
for (j = 0; j < i; j++)
{
if (v[i] == v[j])
is_unique = 0;
}
if (is_unique)
new_v[k] = v[i];
k++;
}
return new_v;
}
The problem should be happening here:
// fill new array with unique elements
new_v[0] = v[0];
for (i = 1; i < size_old; i++)
{
int is_unique = 1;
for (j = 0; j < i; j++)
{
if (v[i] == v[j])
is_unique = 0;
}
if (is_unique)
new_v[k] = v[i];
k++;
}
Your problem is probably occurring in the following section -
if (is_unique)
new_v[k] = v[i];
k++;
Here you are incrementing k at each iteration. However, you only want to increment it whenever you have found a unique element. if() without brackets only considers the first statement. So change it to this -
if (is_unique){
new_v[k] = v[i];
k++;
}
This change should make your program run fine.
Side Note : If you do not want to use brackets for an if() , for() , etc, you can separate the statements by commas and use without having the brackets. Like this -
if (is_unique)
new_v[k] = v[i],
k++;

How to print values down a column in a 2D array in C?

I have the following 2D array:
int censusData[4][3] = {{87290, 77787, 55632},
{83020, 78373, 62314},
{95588, 87934, 705421},
{112456, 97657, 809767}};
I want to print values column-wise in that, after 3 passes of a loop, it would print:
87290 83020 95588 112456
77787 78373 87934 97657
55632 62314 705421 809767
Notice how it's the first element from each sub-array, then the 2nd, then the third..etc
I can easily access each subarray when going row-wise using this:
int* averageCityIncome(int size, int size_2, int arr[][size_2]){
int* t_arr = malloc(4 * sizeof(int));
for (int i = 0; i < size; i++){
int avg = 0;
for (int j = 0; j < size_2; j++){
avg += arr[i][j];
}
avg /= size_2;
t_arr[i] = avg;
}
return t_arr;
}
But now I'm trying to read column-wise as stated above and I so far have this:
int* averageIncome(int size, int size_2, int arr[][size_2]){
int* t_arr = malloc(4 * sizeof(int));
for (int i = 0; i < size_2; i++){
for (int j = 0; j < size; j++){
printf("%d\n", arr[i][j]);
}
printf("-----\n");
}
return t_arr;
}
But it doesn't seem to be working. I'm still pretty new to C, and it's difficult to wrap my mind around 2D arrays still. Any help would be greatly appreciated.
You simply need to swap i and j for the dimensions when addressing a certain element of the array in the caller.
int* averageIncome(int size, int size_2, int arr[][size_2]) {
int* t_arr = calloc(4, sizeof(int)); // calloc to initialize the array elements to 0.
if ( t_arr == NULL )
{
fputs("Error at memory allocation for t_arr!", stderr);
exit(1);
}
int avg = 0; // definition of avg placed outside of the loop.
for (int i = 0; i < size_2; i++) {
for (int j = 0; j < size; j++) {
printf("%d\n", arr[j][i]); // j swapped with i.
avg += arr[j][i]; // same here too.
}
printf("-----\n");
t_arr[i] = avg / size;
avg = 0;
}
return t_arr;
}
Example (Online):
#include <stdio.h>
#include <stdlib.h>
#define ROWS 4
#define COLS 3
int* averageIncome(int size, int size_2, int arr[][size_2]) {
int* t_arr = calloc(4, sizeof(int)); // calloc to initialize the array elements to 0.
int avg = 0; // definition of avg placed outside of the loop.
for (int i = 0; i < size_2; i++) {
for (int j = 0; j < size; j++) {
printf("%d\n", arr[j][i]); // j swapped with i.
avg += arr[j][i]; // same here too.
}
printf("-----\n");
t_arr[i] = avg / size;
avg = 0;
}
return t_arr;
}
int main (void)
{
int censusData[ROWS][COLS] = {
{87290, 77787, 55632},
{83020, 78373, 62314},
{95588, 87934, 705421},
{112456, 97657, 809767}
};
int* p = averageIncome(ROWS, COLS, censusData);
for ( int i = 0; i < COLS; i++ )
{
printf("Average Income of %d. column is: %d\n", i + 1, p[i]);
}
return 0;
}
Output:
87290
83020
95588
112456
-----
77787
78373
87934
97657
-----
55632
62314
705421
809767
-----
Average Income of 1. column is: 94588
Average Income of 2. column is: 85437
Average Income of 3. column is: 408283
Side notes:
Always check the returned pointer from a memory-management for a null pointer if the allocation failed.
I used calloc() instead of malloc() to initialize all elements of the dynamically allocated array to 0.
The definition of avg should be placed before the nested loops, not within. Reset avg to 0 at the end of the outer loop.
avg /= size_2; t_arr[i] = avg; should be avg /= size; t_arr[i] = avg;. Note the replacement of size_2 with size.
avg /= size; t_arr[i] = avg; can be simplified by t_arr[i] = avg / size;.
#include <stdio.h>
int censusData[4][3] = {{87290, 77787, 55632},
{83020, 78373, 62314},
{95588, 87934, 705421},
{112456, 97657, 809767}};
int main() {
int* t_arr = malloc(3 * sizeof(int));
for(int i=0;i<3;i++){
int avg = 0;
for(int j=0;j<4;j++){
//Keep the I fixed here now J is varying and its position of column
//So you are reading all column values for ith row.
avg+=censusData[j][i];
}
avg/=4;
t_arr[i] = avg;
}
for(int i=0;i<3;i++){
printf("%d,",t_arr[i]);
}
return 0;
}
You can loop over the columns first and then print the corresponding element of each row:
for (int col = 0; col < 3; ++col)
{
for (int row = 0; row < 4; ++row)
{
printf("%d\n", censusData[row][col]);
// Do other stuff here
}
printf("-----\n");
}
For each row, the colth element is printed. So for col = 0, censusData[0][0], censusData[1][0], censusData[2][0], censusData[3][0] will be printed.
In your code, you can just swap the positions of the two for loops to iterate over the columns first.

How can I make a new array, by counting the no.of appearances of value and printing it next to that value?

I should make new array out of existing one (ex. 1 0 4 5 4 3 1) so that the new one contains digits already in existing array and the number of their appearances.
So, the new one would look like this: 1 2 0 1 4 2 5 1 3 1 (1 appears 2 times, 0 appears 1 time.... 3 appears 1 time; the order in which they appear in first array should be kept in new one also); I know how to count no. of times a value appears in an array, but how do I insert the no.of appearances? (C language)
#include <stdio.h>
#define max 100
int main() {
int b, n, s, i, a[max], j, k;
printf("Enter the number of array elements:\n");
scanf("%d", &n);
if ((n > max) || (n <= 0)) exit();
printf("Enter the array:\n");
for (i = 0; i < n; i++)
scanf("%d", a[i]);
for (i = 0; i < n; i++) {
for (j = i + 1; j < n;) {
if (a[j] == a[i]) {
for (k = j; k < n; k++) {
a[k] = a[k + 1];
}}}}
//in the last 5 rows i've tried to compare elements, and if they are same, to increment the counter, and I've stopped here since I realised I don't know how to do that for every digit/integer that appears in array//
If you know that the existing array consists of digits between 0 and 9, then you can use the index of the array to indicate the value that you are incrementing.
int in[12] = {1,5,2,5,6,5,3,2,1,5,6,3};
int out[10] = {0,0,0,0,0,0,0,0,0,0};
for (int i = 0; i < 12; ++i)
{
++out[ in[i] ];
}
If you provide any code snippet, its easy for the community to help you.
Try this, even you optimize the no.of loops :)
#include <stdio.h>
void func(int in[], int in_length, int *out[], int *out_length) {
int temp[10] = {0}, i = 0, j = 0, value;
//scan the input
for(i=0; i< in_length; ++i) {
value = in[i];
if(value >= 0 && value <= 9) { //hope all the values are single digits
temp[value]++;
}
}
// Find no.of unique digits
int unique_digits = 0;
for(i = 0; i < 10; ++i) {
if(temp[i] > 0)
unique_digits++;
}
// Allocate memory for output
*out_length = 2 * unique_digits ;
printf("digits: %d out_length: %d \n",unique_digits, *out_length );
*out = malloc(2 * unique_digits * sizeof(int));
//Fill the output
for(i = 0, j = 0; i<in_length && j < *out_length; ++i) {
//printf("\n i:%d, j:%d val:%d cout:%d ", i, j, in[i], temp[in[i]] );
if(temp[in[i]] > 0 ) {
(*out)[j] = in[i];
(*out)[j+1] = temp[in[i]];
temp[in[i]] = 0; //Reset the occurrences of this digit, as we already pushed this digit into output
j += 2;
}
}
}
int main(void) {
int input[100] = {1, 0, 4, 5, 4, 3, 1};
int *output = NULL, output_length = 0, i = 0;
func(input, 7, &output, &output_length );
for(i=0; i < output_length; i+=2) {
printf("\n %d : %d ", output[i], output[i+1]);
}
return 0;
}

C - Read matrix of unknown size from file

I have file that has 30 matrices and each matrix has unknown size of rows and columns(with a max size of 1000). For instance:
0 5 2
5 0 2
1 6 0
0 9 7 4
3 0 9 1
9 1 0 4
9 4 1 0
I need to read each matrix into a 2d array. What would be the most efficient way of doing this?
This is what I have so far:
int** mat=malloc(1000000*sizeof(int*));
for(i=0;i<1000000;++i)
mat[i]=malloc(4*sizeof(int));
while(!feof(file))
{
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++){
fscanf(file,"%d%*[^\n]%*c",&mat[i][j]);
printf("%d\n", mat[i][j]);
}
}
}
Well the most efficient way is definitely not that. First figure out how big an array you need, then allocate it.
Apparently some matrices are small, so there is no need to allocate the maximum size 1000x1000. One way is to put the matrix in a structure to make it easier to keep track of size:
struct s_matrix
{
int **matrix;
int N; //one side of the square matrix N x N
};
typedef struct s_matrix Matrix;
Then allocate and free the matrix
void allocate_matrix(Matrix *m, int N)
{
m->N = N;
m->matrix = (int**)malloc(N * sizeof(int*));
*m->matrix = (int*)malloc(N * N * sizeof(int));
for (int i = 0; i < N; i++)
m->matrix[i] = *m->matrix + i * N;
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
m->matrix[i][j] = 0;
}
void free_matrix(Matrix *m)
{
if (!m) return;
if (!m->matrix) return;
free(*m->matrix);
free(m->matrix);
}
Now we can declare how many matrices we need. It looks like this number is fixed at 30, so I don't think we need dynamic allocation.
int main()
{
const int max_count = 30;
Matrix list[max_count];
for (int i = 0; i < max_count; i++)
list[i].matrix = NULL;
allocate_matrix(&list[0], 3);//allocate 3x3 matrix
allocate_matrix(&list[1], 1000);//1000x1000
allocate_matrix(&list[2], 4000);//4000x4000
int **m;
m = list[0].matrix;
m[0][0] = 0;
m[0][1] = 1;
m[0][2] = 2;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
printf("%02d %s", m[i][j], (j == 2) ? "\n" : "");
//...
for (int i = 0; i < max_count; i++)
free_matrix(&list[i]);
printf("hey it worked, or maybe it didn't, or it did but there is memory leak\n");
return 0;
}

Resources