Fat to Fit Club (FFC) (C)

My friend and I are members of the "Fat to Fit Club (FFC)".
My friend is worried because each month a list with the weights of members is published,
and each month he is the last on the list which means he is the heaviest.

I am the one who establishes the list so I told him:
"Don't worry any more, I will modify the order of the list".
It was decided to attribute a "weight" to numbers.
The weight of a number will be from now on the sum of its digits.

For example:
99 will have "weight" 18, 100 will have "weight" 1,
so in the list 100 will come before 99
because the sum of the digits of 100 = 1 <  the sum of the digits of 99 = 18 


🎯Task/Program🎯
Given a string with the weights of FFC members in normal order.
Can you give this string ordered by "weights"(sum of the digits of this string)?


Examples 

  • "56 65 74 100 99 68 86 180 90"         --->  "100 180 90 56 65 74 68 86 99"
  • "103 123 4444 99 2000"                         --->  "2000 103 123 4444 99"
  • "2000 10003 1234000 44444444 9999 11 11 22 123" ---> "11 11 2000 10003 22 123 1234000 44444444 9999"
  • "10003 1234000 44444444 9999 2000 123456789"    ---> "2000 10003 1234000 44444444 9999 123456789"


📝Notes 📝

  • If two numbers have the same "weight", order them as if they were strings (alphabetical ordering) e.g 180 comes before 90, since both have the same "weight" (9),
    but "180" is alphabetically smaller than "90"
  • Don't modify the input
  • The allocated space should be freed


📢RecommendedPlease try to implement  the program on your own first, before looking at the code down below.



____________________________________________________

🎁Code:



/**
 * AUTHOR: KHALED BADRAN*
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

// #############################################
#define IS_DIGIT(c) c >= '0' && c <= '9' ? 1 : 0
#define IS_SPACE(c) c == ' ' ? 1 : 0

// Check whether the actual String (first argument) is equal to the expected String (second argument).
bool base_test_equal_s(const char* fileint line,  char* a,  char* e);
#define test_equal_s(aebase_test_equal_s(__FILE____LINE__, a, e)


typedef struct Weight{
    char *val_str; //value as string
    int val_int;   //value as int //actually not required in this qeuestion  
    int sum_int;   //sum of the digits of a number as int 
Weight;
// #############################################


//gets one number in form of string and returns the sum of its digits as int
int str_sum(char *str){
    int sum = 0;
    for(int i = 0str[i]; i++if(IS_DIGIT(str[i])) sum += str[i] - '0';
    return sum;
}

//gets one number in form of string and returns the same number inform of int
int str_to_int(const char* s){
    int as_int = 1;
    for(int i = 0, factor = 10s[i] != '\0'; i++){
        if( i == 0) as_int = s[i] - '0';
        else as_int =  (as_int * factor) + (s[i] - '0');
    }
    return as_int;
}

void free_arr_of_weights(Weight *arrint length){
    for(int i = 0; i < length; i++){
        free(arr[i].val_str);
    }
    free(arr);
}

char* order_weight(const char* s){ 
    //counting how many spaces are there in the input string because number of weights to order = number of spaces + 1
    int spaces = 0;
    for(int i = 0s[i]; i++if(IS_SPACE(s[i])) spaces++

    //getting number of digits of the biggest number in the input string.
    int digits = 0;
    for(int i = 0, temp_digits = 0s[i]; i++) {
        if(IS_DIGIT(s[i])) temp_digits++;
        else if(IS_SPACE(s[i])) temp_digits = 0;
        if(temp_digits > digits) digits = temp_digits;
    }

    //creating an array of Weights
    int length_arr_weights = spaces+1;
    Weight* arr_weights = (Weight*calloc(length_arr_weights, sizeof(Weight));
    for (size_t i = 0, input_i = 0/*index of the input array*/; i < length_arr_weights; i++){
        //getting the number as str for a Weight variable.
        arr_weights[i].val_str = (char*calloc(digits+1sizeof(char));//allocating memory for every single str of a Weight variable
        int single_str_sz = 0//size of single string of the array of Weights 
        for(size_t j = 0; j < digits+1; j++, input_i++){
            if(s[input_i] == '\0'break
            if(s[input_i] == ' ') { input_i ++;  break; }
            arr_weights[i].val_str[j] = s[input_i];
            single_str_sz++;
        }
        arr_weights[i].val_str[single_str_sz+1= '\0'

        //getting the number as int for a Weight variable.
        arr_weights[i].val_int = str_to_int(arr_weights[i].val_str);

        //getting the sum of digits as int for a Weight variable.
        arr_weights[i].sum_int = str_sum(arr_weights[i].val_str);
    }
    
    char *modified = (char*calloc(strlen(s)+1sizeof(char));
    for(int i = 0; i < (length_arr_weights - 1); i++){
        for(int j = i + 1; j < length_arr_weights; j++){
            Weight save_i = arr_weights[i];
            if(arr_weights[j].sum_int < arr_weights[i].sum_int) { arr_weights[i] = arr_weights[j]; arr_weights[j] = save_i; } 

            else if(arr_weights[j].sum_int == arr_weights[i].sum_int){
                if(strcmp(arr_weights[j].val_str, arr_weights[i].val_str) < 0) { arr_weights[i] = arr_weights[j]; arr_weights[j] = save_i; }
            }
        }
        i != (length_arr_weights - 1- 1 ? ( strcat(modified, arr_weights[i].val_str), strcat(modified," ") ) : ( strcat(modified, arr_weights[i].val_str), strcat(modified," "),  strcat(modified, arr_weights[i+1].val_str) );
    }  
    modified[strlen(s)] = '\0';

    free_arr_of_weights(arr_weights, length_arr_weights);

    return modified;
}

bool base_test_equal_s(const char* fileint line,  char* a,  char* e) {
    if (strcmp(ae== 0) {
        printf("Actual value:   \"%s\"\n"a);
        printf("Expected value: \"%s\"\n"e);
        printf("%s, line %d: check passed\n\n"fileline);
        return true;
    } else {
        printf("%s, line %d: Actual value \"%s\" differs from expected value \"%s\".\n\n"filelineae);
        return false;
    }
}

void test_order_weight() { 
    char* result;

    result = order_weight("56 65 74 100 99 68 86 180 90");
    test_equal_s(result, "100 180 90 56 65 74 68 86 99");
    free(result); 

    result = order_weight("103 123 4444 99 2000 4 31");
    test_equal_s(result, "2000 103 31 4 123 4444 99");
    free(result);

    result = order_weight("2000 10003 1234000 44444444 9999 11 11 22 123");
    test_equal_s(result, "11 11 2000 10003 22 123 1234000 44444444 9999");
    free(result); 

    result = order_weight("10003 1234000 44444444 9999 2000 123456789");
    test_equal_s(result, "2000 10003 1234000 44444444 9999 123456789");
    free(result);  

    result = order_weight("5562 2632 11341 3492 15335 5893 1916 13302 3349 18038 5628");
    test_equal_s(result, "13302 11341 2632 15335 1916 3492 5562 3349 18038 5628 5893");
    free(result);

    result = order_weight("1752 1298 13680 17088 15020 16674 1872 11114 8662 17618 2957 17467 11762 18299 2874");
    test_equal_s(result, "11114 15020 1752 11762 13680 1872 1298 2874 8662 17618 2957 16674 17088 17467 18299");
    free(result);
}

int main(){
    test_order_weight();
    return 0;
}


____________________________________________________

Output:

Actual value: "100 180 90 56 65 74 68 86 99" Expected value: "100 180 90 56 65 74 68 86 99" fat_to_fit_club.c, line 122: check passed Actual value: "2000 103 31 4 123 4444 99" Expected value: "2000 103 31 4 123 4444 99" fat_to_fit_club.c, line 126: check passed Actual value: "11 11 2000 10003 22 123 1234000 44444444 9999" Expected value: "11 11 2000 10003 22 123 1234000 44444444 9999" fat_to_fit_club.c, line 130: check passed Actual value: "2000 10003 1234000 44444444 9999 123456789" Expected value: "2000 10003 1234000 44444444 9999 123456789" fat_to_fit_club.c, line 134: check passed Actual value: "13302 11341 2632 15335 1916 3492 5562 3349 18038 5628 5893" Expected value: "13302 11341 2632 15335 1916 3492 5562 3349 18038 5628 5893" fat_to_fit_club.c, line 138: check passed Actual value: "11114 15020 1752 11762 13680 1872 1298 2874 8662 17618 2957 16674 17088 17467 18299" Expected value: "11114 15020 1752 11762 13680 1872 1298 2874 8662 17618 2957 16674 17088 17467 18299" fat_to_fit_club.c, line 142: check passed


____________________________________________________



Comments