Search code examples
arrayscsortingstructswap

Small Triangles, Large Triangles code not working


So, I had been trying to write the code for the Small Triangles, Large Triangles problem of C in Hackerrank. Before, I state what problem I'm facing, I'll attach the question- enter image description here

I only wrote the sort_by_area, swap and area functions here. The rest of it was given and unchangeable. The code I've written is getting executed properly but the structures aren't getting sorted correctly. Here is the expected output & my output-

enter image description here

I just cannot figure out why it is getting such weirdly swapped. If anyone could help, would mean a lot.

My code is-

#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 i, j, swapped;
    for (i = 0; i < n-1; i++)
   {
     swapped = 0;
     for (j = 0; j < n-i-1; j++)
     {
        if (area(tr[j].a, tr[j].b, tr[j].c) > area(tr[j+1].a, tr[j+1].b, tr[j+1].c))
        {
           swap(&tr[j], &tr[j+1]);
           swapped = 1;
        }
     }
     if (swapped == 0)
        break;
    }
}
void swap(struct triangle **xp, struct triangle **yp)
{
    struct triangle *temp = *xp;
    *xp = *yp;
    *yp = temp;
}
int area(int a, int b, int c){
       int p=(a+b+c)/2;
       int q=p*(p-a)*(p-b)*(p-c);
       return sqrt(q);
   }
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;
}```


Solution

  • Enable all warnings

    This quickly led to swap() swapping pointers and not data.

    // Corrected - swap data
    void swap(struct triangle *xp, struct triangle *yp) {
      struct triangle temp = *xp;
      *xp = *yp;
      *yp = temp;
    }
    

    Function order

    Move area(), swap() definitions before calling them.


    Area

    (int) sqrt(q) may return the same value for different qs.

    Example: (int) sqrt(100), (int) sqrt(110), (int) sqrt(120)
    All return 10. Sorting will not certainly sort according to area.


    Simple return the square of the area. Mathematically, sorting by area squared same as area.

    int area_squared(int a, int b, int c){
       int p=(a+b+c)/2;
       int q=p*(p-a)*(p-b)*(p-c);
       // return sqrt(q);
       return q;
    }
    

    Although one could code using double, let us stay with integers.

    Watch out for a+b+c as odd as odd/2 forms a truncated quotient.

    Perhaps return the square of the area, scaled each side by 2?

    int area_squared2(int a, int b, int c){
       a *= 2; b *= 2; c *= 2;
       // a+b+c is certianly even
       int p=(a+b+c)/2;
       int q=p*(p-a)*(p-b)*(p-c);
       return q;
    }
    

    A remaining concern is int overflow. Consider long long math.

    long long area_squared2LL(int a, int b, int c){
       long long aa = a * 2LL;
       long long bb = b * 2LL;
       long long cc = c * 2LL;
       long long pp = (aa+bb+cc)/2;
       long long qq = pp*(pp-aa)*(pp-bb)*(pp-cc);
       return qq;
    }
    

    Tip: Allocate by referenced data, not type

    Easier to code right, review and maintain.

    // triangle *tr = malloc(n * sizeof(triangle));
    triangle *tr = malloc(sizeof *tr * n);
    if (tr == NULL) {
      // use tr 
      ...
      free(tr);
      tr = NULL;
    }