Brilliant Sheep
9Apr/12

Finding the Smallest Value Out of Three Integers via a Ternary Operator

Due to the title being too descriptive, I'm left with not much to say in this post. So, here's the one-line implementation along with a test function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
 
/** Returns the minimum of three values */
int min( int a, int b, int c )
{
    return ( a < b ? ( a < c ? a : c ) : ( b < c ? b : c ) );
}
 
/** Test Function */
int main( )
{
    int a = 1, b = 2, c = 3;
 
    // Test all combinations of a, b, c
    printf( "{ %d, %d, %d } => min = %d\n", a, b, c, min( a, b, c ) );
    printf( "{ %d, %d, %d } => min = %d\n", a, c, b, min( a, c, b ) );
    printf( "{ %d, %d, %d } => min = %d\n", b, a, c, min( b, a, c ) );
    printf( "{ %d, %d, %d } => min = %d\n", b, c, a, min( b, c, a ) );
    printf( "{ %d, %d, %d } => min = %d\n", c, a, b, min( c, a, b ) );
    printf( "{ %d, %d, %d } => min = %d\n", c, b, a, min( c, b, a ) );
 
    return 0;
}

Whereas the output from the test function is as follows:

gdoko@mars:~$ ./min
{ 1, 2, 3 } => min = 1
{ 1, 3, 2 } => min = 1
{ 2, 1, 3 } => min = 1
{ 2, 3, 1 } => min = 1
{ 3, 1, 2 } => min = 1
{ 3, 2, 1 } => min = 1

HTH :)

Tagged as: No Comments
7Apr/12

Calculating the Sum of All Proper Divisors in C

Hi there! Now that I have your attention, I'd like to tell you that I'm happy to share my very first post in Number Theory. I know, I know. It's elementary. However, I'm hoping to continue publishing similar posts as I study more; and this post is the very first one.

That said, this post is about a simple algorithm which calculates the sum of all proper divisors of a number. The meaning of a proper divisor here is that of a positive divisor of a number, excluding that number. So, if f(n) represents the function for calculating the sum of all proper divisors, we'll have the following for n = 10:

f( 10 ) = 1 + 2 + 5 = 8

With that in mind, the C implementation of the algorithm that carries the calculation of the sum of all proper divisors of a number, is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <math.h>
 
/** Get the sum of all proper divisors of a positive number */
long long sum_proper_divisors( int number ) 
{
    int i;
    long long sum = 0;
 
    if( number == 1 )
    {
        return sum;
    }
 
    // Set sum to 1, as we start iteration from 2
    sum = 1;
 
    // Iterate from 2 to sqrt( number )
    int j = sqrt( number );
    for( i = 2; i <= j; i++ ) 
    {
        // If a number is a proper divisor, add it to the sum
        if( number % i == 0 ) 
        {
            sum = sum + i;
 
            // If there's a multiple of a proper divisor, that is not equal to the 
            // current proper divisor, then add it to the sum as well.
            if( i != number / i )
            {
                sum = sum + ( number / i );
            }
        }
    }
 
    return sum;
}
 
/** Test Function */
int main( )
{
    printf( "%d\t%lld\n", 1, sum_proper_divisors( 1 ) );
    printf( "%d\t%lld\n", 20, sum_proper_divisors( 20 ) );
    printf( "%d\t%lld\n", 25, sum_proper_divisors( 25 ) );
 
    return 0;
}

Assuming the specified number is 20; then we'll get the following:

number = 20 => sqrt( 20 ) = 4 (integer flooring)
sum = 1; iterate from 2 to 4 (inclusive)
 
    first iteration: 
        20 % 2 == 0 => sum = 3
        20 / 2 == 10 => 2 != 10 => sum = 13
 
    second iteration:
        20 % 3 != 0
 
    third iteration:
        20 % 4 == 0 => sum = 17
        20 / 4 == 5 => 5 != 4 => sum = 22

Thus, the sum of all proper divisors for 20, is 22. On the other han, if specified the number as 25, then we'll get the following:

number = 25 => sqrt( 25 ) = 5
sum = 1; iterate from 2 to 5 (inclusive)
 
    first iteration:
        25 % 2 != 0
 
    second iteration:
        25 % 3 != 0
 
    third iteration:
        25 % 4 != 0
 
    fourth iteration:
        25 % 5 == 0 => sum = 6
        25 / 5 == 5 => 5 == 5 (sum stays the same)

Thus, the sum of all proper divisors for 25, is 6. On the other hand, the execution of the test function will yield the following results:

gdoko@mars:~$ ./sum_proper_divisors 
1	0
20	22
25	6

HTH :)

6Apr/12

Sorting 3-Numbers in Ascending Order in C

Recently, while tackling a programming challenge, I had to sort 3-numbers in ascending order (no; that wasn't the challenge, but one of the steps). However, I wanted to do this in a very lightweight and straightforward manner. So, the end result was a code containing 3-if conditions and a pointer manipulation function for swapping, as seen below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
 
/** Swaps two numbers via pointer manipulation */
void swap( int* a, int* b )
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
 
/** Test Function */
int main( )
{
    int a, b, c;
    scanf( "%d %d %d", &a, &b, &c );
 
    // Order numbers in ascending order
    if( b < a ) swap( &a, &b );
    if( c < b ) swap( &b, &c );
    if( b < a ) swap( &a, &b );
 
    printf( "%d %d %d\n", a, b, c );
    return 0;
}

As expected, the outcome of this endeavor worked as follows:

gdoko@mars:~$ ./min
1 2 3
1 2 3
gdoko@mars:~$ ./min
1 3 2
1 2 3
gdoko@mars:~$ ./min
3 1 2
1 2 3

HTH :)

4Apr/12

Handling Big Numbers in C

Today I was looking at various C implementations for handling very large numbers. Although I've noticed that there were several libraries, such as The GNU Multiple Precision Arithmetic Library; I was more interested in a very lightweight, straightforward, single-file implementation. With that in mind, I finally came accross Professor's Skiena bignum.c implementation.

One of the first things I've noticed with this implementation is the missing string_to_bignum( char* s, bignum* n ) function. So, with some effort I went ahead and wrote that function. In addition, as I was studying the code, I also changed the formatting here and there, and added some additional comments for the sake of improved legibility. Thus, thinking that someone else might benefit from these tweaks as well, I'm going ahead with posting the complete [tweaked] source code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
/**
 * Copyright 2003 by Steven S. Skiena; all rights reserved. 
 *
 * Permission is granted for use in non-commerical applications provided this 
 * copyright notice remains intact and unchanged.
 * 
 * This file contains the structure for representing big numbers. In addition, 
 * this file contains functions for adding, subtracting, multiplying, and
 * dividing very large numbers.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXDIGITS 101    // Maximum Length Bignum 
 
#define PLUS        1    // Positive Sign Bit
#define MINUS      -1    // Negative Sign Bit
 
/** Struct for big numbers */
typedef struct {
    char digits[ MAXDIGITS ];  // Represent the number
    int signbit;               // 1 if positive, -1 if negative 
    int lastdigit;             // Index of high-order digit
} bignum;
 
/** Function headers declarations */
void print_bignum( bignum* n );
void string_to_bignum( char* s, bignum* n );
void int_to_bignum( int s, bignum* n );
void initialize_bignum( bignum* n );
void zero_justify( bignum* n );
void add_bignum( bignum* a, bignum* b, bignum* c );
void subtract_bignum( bignum* a, bignum* b, bignum* c );
void digit_shift( bignum* n, int d );
void multiply_bignum( bignum* a, bignum* b, bignum* c );
void divide_bignum(bignum *a, bignum *b, bignum *c);
int max( int a, int b );
int compare_bignum( bignum* a, bignum* b );
 
/** Prints big number */
void print_bignum( bignum* n )
{
    int i;
 
    if( n->signbit == MINUS ) printf( "-" );
 
    for( i = n->lastdigit; i >= 0; i-- )
    {
        printf( "%c", '0' + n->digits[ i ] );
    }
 
    printf("\n");
}
 
/** Converts a string to a big number */
void string_to_bignum( char* s, bignum* n )
{
    int i, j; 
 
    for( i = 0; i < MAXDIGITS; i++ )
    {
        n->digits[ i ] = ( char ) 0;
    }
 
    n->lastdigit = -1;
 
    for( j = strlen( s ) - 1; j > 0; j-- )
    {
        n->lastdigit++;
        n->digits[ n->lastdigit ] = s[ j ] - '0';
    }
 
    // Check if the last character is a minus sign or a digit
    if( s[ 0 ] == '-' )
    {
        n->signbit = MINUS;
    }
    else
    {
        n->lastdigit++;
        n->digits[ n->lastdigit ] = s[ 0 ] - '0';
 
        n->signbit = PLUS;
    }
}
 
/** Converts an integer to a big number */
void int_to_bignum( int s, bignum* n )
{
    int i, t;
 
    n->signbit = s >= 0 ? PLUS : MINUS;
 
    for( i = 0; i < MAXDIGITS; i++ )
    {
        n->digits[ i ] = ( char ) 0;
    }
 
    n->lastdigit = -1;
 
    t = abs( s );
 
    while( t > 0 ) 
    {
        n->lastdigit++;
        n->digits[ n->lastdigit ] = (t % 10);
        t = t / 10;
    }
 
    if( s == 0 )
    {
        n->lastdigit = 0;
    }
}
 
/** Initializes a big number */
void initialize_bignum( bignum* n )
{
    int_to_bignum( 0, n );
}
 
/** Returns the greatest of two integers */
int max( int a, int b )
{
    return a > b ? a : b;
}
 
/** Zero justifies a big number */
void zero_justify( bignum* n )
{
    while( ( n->lastdigit > 0 ) && ( n->digits[ n->lastdigit ] == 0 ) )
    {
        n->lastdigit--;
    }
 
    if( ( n->lastdigit == 0 ) && ( n->digits[ 0 ] == 0 ) )
    {
        n->signbit = PLUS;    /* hack to avoid -0 */
    }
}
 
/** Adds big numbers; i.e. c = a + b */
void add_bignum( bignum* a, bignum* b, bignum* c )
{
    int carry;            /* carry digit */
    int i;                /* counter */
 
    initialize_bignum( c );
 
    if( a->signbit == b->signbit )
    {
        c->signbit = a->signbit;
    }
    else 
    {
        if( a->signbit == MINUS ) 
        {
            a->signbit = PLUS;
            subtract_bignum( b, a, c );
            a->signbit = MINUS;
        } 
        else 
        {
            b->signbit = PLUS;
            subtract_bignum( a, b, c );
            b->signbit = MINUS;
        }
 
        return;
    }
 
    c->lastdigit = max( a->lastdigit, b->lastdigit ) + 1;
    carry = 0;
 
    for( i = 0; i <= ( c->lastdigit ); i++ ) 
    {
        c->digits[ i ] = ( char ) ( carry + a->digits[ i ] + b->digits[ i ] ) % 10;
        carry = ( carry + a->digits[ i ] + b->digits[ i ] ) / 10;
    }
 
    zero_justify( c );
}
 
/** Subtracts big numbers; i.e. c = a - b */
void subtract_bignum( bignum* a, bignum* b, bignum* c )
{
    int borrow;           /* has anything been borrowed? */
    int v;                /* placeholder digit */
    int i;                /* counter */
 
    initialize_bignum( c );
 
    if( ( a->signbit == MINUS ) || ( b->signbit == MINUS ) ) 
    {
        b->signbit = -1 * b->signbit;
        add_bignum( a, b, c );
        b->signbit = -1 * b->signbit;
        return;
    }
 
    if( compare_bignum( a, b ) == PLUS ) 
    {
        subtract_bignum( b, a, c );
        c->signbit = MINUS;
        return;
    }
 
    c->lastdigit = max( a->lastdigit, b->lastdigit );
    borrow = 0;
 
    for( i = 0; i <= ( c->lastdigit ); i++ ) 
    {
        v = ( a->digits[ i ] - borrow - b->digits[ i ] );
 
        if( a->digits[ i ] > 0)
        {
            borrow = 0;
        }
 
        if( v < 0 ) 
        {
            v = v + 10;
            borrow = 1;
        }
 
        c->digits[ i ] = ( char ) v % 10;
    }
 
    zero_justify( c );
}
 
/** Compares big numbers */
int compare_bignum( bignum* a, bignum* b )
{
    int i;                /* counter */
 
    if( ( a->signbit == MINUS ) && ( b->signbit == PLUS ) ) return( PLUS );
    if( ( a->signbit == PLUS ) && ( b->signbit == MINUS ) ) return( MINUS );
 
    if( b->lastdigit > a->lastdigit ) return( PLUS * a->signbit );
    if( a->lastdigit > b->lastdigit ) return( MINUS * a->signbit );
 
    for( i = a->lastdigit; i >= 0; i-- )
    {
        if( a->digits[ i ] > b->digits[ i ] ) return( MINUS * a->signbit );
        if( b->digits[ i ] > a->digits[ i ] ) return( PLUS * a->signbit );
    }
 
    return( 0 );
}
 
/** Multiplies a big number by 10^d */
void digit_shift( bignum* n, int d )
{
    int i;                /* counter */
 
    if( ( n->lastdigit == 0 ) && ( n->digits[ 0 ] == 0 ) ) return;
 
    for( i = n->lastdigit; i >= 0; i-- )
    {
        n->digits[ i + d ] = n->digits[ i ];
    }
 
    for( i = 0; i < d; i++ )
    {
        n->digits[ i ] = 0;
    }
 
    n->lastdigit = n->lastdigit + d;
}
 
/** Multiplies big numbers; i.e. c = a * b */
void multiply_bignum( bignum* a, bignum* b, bignum* c )
{
    bignum row;            /* represent shifted row */
    bignum tmp;            /* placeholder bignum */
    int i, j;              /* counters */
 
    initialize_bignum( c );
    row = *a;
 
    for( i = 0; i <= b->lastdigit; i++ ) 
    {
        for( j = 1; j <= b->digits[ i ]; j++ ) 
        {
            add_bignum( c, &row, &tmp );
            *c = tmp;
        }
        digit_shift( &row, 1 );
    }
 
    c->signbit = a->signbit * b->signbit;
    zero_justify( c );
}
 
/** Divides big numbers; i.e. c = a / b */
void divide_bignum(bignum *a, bignum *b, bignum *c)
{
    bignum row;              /* represent shifted row */
    bignum tmp;              /* placeholder bignum */
    int asign, bsign;        /* temporary signs */
    int i;                   /* counters */
 
    initialize_bignum( c );
    c->signbit = a->signbit * b->signbit;
 
    asign = a->signbit;
    bsign = b->signbit;
 
    a->signbit = PLUS;
    b->signbit = PLUS;
 
    initialize_bignum( &row );
    initialize_bignum( &tmp );
 
    c->lastdigit = a->lastdigit;
 
    for( i = a->lastdigit; i >= 0; i-- ) 
    {
        digit_shift( &row, 1 );
        row.digits[ 0 ] = a->digits[ i ];
        c->digits[ i ] = 0;
        while( compare_bignum( &row, b ) != PLUS ) 
        {
            c->digits[ i ]++;
            subtract_bignum( &row, b, &tmp );
            row = tmp;
        }
    }
 
    zero_justify( c );
 
    a->signbit = asign;
    b->signbit = bsign;
}
 
/** Test Function */
int main( )
{
    bignum n1, n2, n3, zero;
 
    // Instantiate string buffers for big numbers a and b
    char* a = calloc( MAXDIGITS, sizeof( char ) );
    char* b = calloc( MAXDIGITS, sizeof( char ) );
 
    // Get big numbers a and b as strings
    printf( "a = " );
    fgets( a, MAXDIGITS, stdin );
 
    printf( "b = " );
    fgets( b, MAXDIGITS, stdin );
 
    // Remove the newline character (if present) from string buffers
    char* nl;
    if( ( nl = strchr( a, '\n' ) ) != NULL ) *nl = '\0';
    if( ( nl = strchr( b, '\n' ) ) != NULL ) *nl = '\0';
 
    // Create a and b big number instances via the string buffers
    string_to_bignum( a, &n1 );
    string_to_bignum( b, &n2 );
 
    // Test addition
    add_bignum( &n1, &n2, &n3 );
    printf( "a + b = " );
    print_bignum( &n3 );
 
    // Test comparison
    int comparison = compare_bignum( &n1, &n2 );
    printf( "a %s b\n", comparison == 0 ? "==" : ( comparison < 0 ? ">" : "<" ) );
 
    // Test subtraction
    subtract_bignum( &n1, &n2, &n3 );
    printf( "a - b = " );    
    print_bignum( &n3 );
 
    // Test multiplication
    multiply_bignum( &n1, &n2, &n3 );
    printf( "a * b = " );
    print_bignum( &n3 );
 
    // Test division
    int_to_bignum( 0, &zero );
    if( compare_bignum( &zero, &n2 ) == 0 )
    {
        printf( "a / b = NaN\n" );
    }
    else 
    {
        divide_bignum( &n1, &n2, &n3 );
        printf( "a / b = " );
        print_bignum( &n3 );
    }
 
    return 0;
}
29Feb/12

Quicksort Implementation in C

Since I've started teaching various computer science courses last August, I've had a chance to dive deeper and deeper in the world of C programming. However, having to program in Java for a living, I'm far from being converted :)

That said, this is my second post only that bears the tag of C. What you'll find below is a C implementation of the Quicksort algorithm. This implementation has been adapted from my previous post: Quicksort Implementation in Java. To those of you who had a chance to delve in C, you'll notice that I don't make a lot of use of C-specific features. However, this was done on purpose as the goal of this implementation was to translate the code from Java to C with the least amount of modifications.

Needless to say, I hope you'll find both implementations beneficial, and do not hesitate to provide any feedback you might have.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <stdio.h>
 
#define ARRAY_SIZE 9
 
/** Sorts the specified array recursively */
void sort( int array[ ], int left, int right ) 
{
    if( left < right ) 
    {
        int pivot = partition( array, left, right );
        sort( array, left, pivot - 1 );
        sort( array, pivot + 1, right );
    }
}
 
/** Swaps the values at the specified array indexes */
void swap( int array[ ], int a, int b ) 
{
    int temp = array[ a ];
    array[ a ] = array[ b ];
    array[ b ] = temp;
}
 
/** 
 * Partitions the specified array based on the pivot element it 
 * selects. Afterwards by relying on a comparison sort, it places 
 * all the elements less than or equal to the pivot before it, 
 * and the elements greater than the pivot, after it. Finally, the
 * pivot index is returned.
 */
int partition( int array[ ], int left, int right ) 
{
    // Select pivot element
    int pivot = array[ right ];
 
    int j, i = left - 1;
 
    for( j = left; j < right; j++ ) 
    {
        if( array[ j ] <= pivot ) 
        {
            i++;
            swap( array, i, j );
        }
    }
 
    // Move the pivot element in the middle of the array
    swap( array, i + 1, right );
 
    // Return the pivot element index
    return i + 1;
} 
 
/** Test Method */
int main( ) 
{
    // Initialize input array
    int input[ ] = { 3, 7, 8, 5, 2, 1, 9, 5, 4 };
 
    // Sort the input array via quicksort
    sort( input, 0, ARRAY_SIZE - 1 );
 
    // Output the sorted input array
    int i;
    for( i = 0; i < ARRAY_SIZE; i++ )
    {
        printf( "%d%s", input[ i ], ( i < ARRAY_SIZE - 1 ) ? ", " : "\n" );
    }
 
    return 0;
}

P.S. Happy Leap Day! -- February 28, 2012 :)