Simplifying Fractions – Solution

This month’s Exercise both terrified and enticed me. Yes, I code these solutions myself after I think up the challenges. No cheating here! This particular puzzle was more fun than I imagined, but also required a lot of mental work.

The first thing I did was to look up the three steps to simplify a fraction: Discover the common factors, obtain the greatest common denominator (GCD), and then divide the numerator and denominator by the GCD. This approach required a lot of code.

Here is the main() function from my first solution, which you can find on Github:

int main()
{
    const int size = 7;
    int numerator[size] = { 28, 13, 14, 1, 9, 276, 4 };
    int denominator[size] = { 42, 52, 91, 50, 15, 23, 100 };
    int numerator_factors[BUFFER_LIMIT];
    int denominator_factors[BUFFER_LIMIT];
    int x,m;

    for( x=0; x<size; x++ )
    {
        /* output the original fraction */
        printf("%d/%d ",numerator[x],denominator[x]);

        /* obtain factors for the numerator and denominator */
        factors(numerator_factors,numerator[x]);
        factors(denominator_factors,denominator[x]);

        /* obtain the maximum common factor */
        m = maxfactor(numerator_factors,denominator_factors);

        if( m )
        {
            /* reduce the fraction */
            printf("is simplified to %d/%d\n",
                    numerator[x]/m,
                    denominator[x]/m
                  );
        }
        else
        {
            /* the fraction cannot be reduced */
            puts("cannot be simplified");
        }
    }

    return(0);
}

The defined constant BUFFER_LIMIT equals 100, which is a guess of how many factors are possible for a given value. This is the kludgiest part of this solution; a number could have more factors than 100, but I didn’t want to manipulate a dynamic array to store them.

A for loop processes each of the fractions, which are output as was done in the skeleton code. Within the loop, the factors() function obtains the factors for numerator[x] and denominator[x]. The results are stored in the numerator_factors[] and denominator_factors[] arrays. See this Lesson for more details on finding factors.

The maxfactor() (heh) function returns the maximum shared factor value between the two arrays, numerator_factors[] and denominator_factors[]. I use a bubble sort to compare the values and find the maximum, which is returned in variable m.

If variable m isn’t zero, its value divides both numerator[x] and denominator[x] to output the simplified fraction. Otherwise, the fraction cannot be simplified.

Here’s a sample run:

28/42 is simplified to 2/3
13/52 is simplified to 1/4
14/91 is simplified to 2/13
1/50 cannot be simplified
9/15 is simplified to 3/5
276/23 is simplified to 12/1
4/100 is simplified to 1/25

My second solution uses Euclid’s algorithm to reduce the numerator and denominator values by their differences. The algorithm is quite clever, and I need not repeat the details or fancy graphics from the Wikipedia page. Here is the entirety of my second solution:

2022_03-Exercise-b.c

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

int main()
{
    const int size = 7;
    int numerator[size] = { 28, 13, 14, 1, 9, 276, 4 };
    int denominator[size] = { 42, 52, 91, 50, 15, 23, 100 };
    int x,diff,larger,smaller;

    for( x=0; x<size; x++ )
    {
        /* output the original fraction */
        printf("%d/%d ",numerator[x],denominator[x]);

        /* calculate differences between the larger and smaller values */
        larger = numerator[x]>denominator[x] ? numerator[x] : denominator[x];
        smaller = numerator[x]<denominator[x] ? numerator[x] : denominator[x];
        diff = larger-smaller;
        /* keep calculating until the common denominator is found */
        while( diff!=larger )
        {
            larger = smaller>diff ? smaller : diff;
            smaller = smaller==larger ? diff : smaller;
            diff = larger-smaller;
        }

        /* if the difference is more than 1, the fraction can be reduced */
        if( diff>1 )
        {
            printf("is simplified to %d/%d\n",
                    numerator[x]/diff,
                    denominator[x]/diff
                  );
        }
        else
        {
            /* the fraction cannot be reduced */
            puts("cannot be simplified");
        }
    }

    return(0);
}

Not being Euclid, I would have never thought of this approach. Yet it works beautifully: The algorithm starts at Lines 17 through 19, then repeats in a while loop until the GCD is found. The output is the same, but I admire this code far better than my first, plodding solution.

Whether you tried one solution or both, I hope you met with success. And I further hope I never have to type the word denominator so many times again in my life.

3 thoughts on “Simplifying Fractions – Solution

  1. A few years ago I did something similar for an article I was writing. It’s not an exact implementation of the exercise but you know, whatever.

    Usually when I post code in comments I mess it up and it looks like an explosion in an Alphabetti Spaghetti factory but I’ll try anyway. Here goes.

    #include<stdio.h>
    #include<stdlib.h>
    
    int EuclideanHCF(int a, int b);
    
    int main(int argc, char* argv[])
    {
        int avalues[] = {55, 27, 3, 14, 500, 30};
        int bvalues[] = {5, 45, 15, 49, 12, 18};
    
        for(int i = 0; i < 6; i++)
        {
            int hcf = EuclideanHCF(avalues[i], bvalues[i]);
    
            printf("HCF of %d and %d = %d\n", avalues[i], bvalues[i], hcf);
    
            printf("%d / %d = %d\n", avalues[i], hcf, avalues[i] / hcf);
    
            printf("%d / %d = %d\n\n", bvalues[i], hcf, bvalues[i] / hcf);
        }
    
        return EXIT_SUCCESS;
    }
    
    int EuclideanHCF(int a, int b)
    {
        int temp;
    
        while(b != 0)
        {
            temp = b;
    
            b = a % b;
    
            a = temp;
        }
    
        return a;
    }

    This is the output:

    HCF of 55 and 5 = 5
    55 / 5 = 11
    5 / 5 = 1

    HCF of 27 and 45 = 9
    27 / 9 = 3
    45 / 9 = 5

    HCF of 3 and 15 = 3
    3 / 3 = 1
    15 / 3 = 5

    HCF of 14 and 49 = 7
    14 / 7 = 2
    49 / 7 = 7

    HCF of 500 and 12 = 4
    500 / 4 = 125
    12 / 4 = 3

    HCF of 30 and 18 = 6
    30 / 6 = 5
    18 / 6 = 3

  2. I fixed your indentation. Next time use the <pre> tags.

    Nice solution! Very clever. Wish I would have done it that simply.

Leave a Reply