Sample Solutions to Diagnostic Test

« Back to Getting Started

The following are sample solutions to problems 8, 9, and 10 of the diagnostic test.

 

 /* Notes: as we will be doing in the class, diagnostic.c should be  compiled with  * "gcc -std=c99 -m64 -Wall -Wextra -Wshadow -Werror -pedantic"  * (in particular: we are coding by the C99 standard)  */   #include <stdio.h> #include <stdbool.h> #include <stdlib.h> #include <assert.h>   /************ PROBLEM 8 ************/   bool is_prime( int n ) {   if( n <= 2 || n % 2 == 0 ) {     return ( n == 2 );   }     for( int i = 3; i * i <= n; i += 2 ) {     if( n % i == 0 ) {       return false;     }   }     return true; }   /************ PROBLEM 9 ************/   void swap( int *a, int *b ) {   int t = *a;   *a = *b;   *b = t; }   void permute( int *digits, int n, int p ) {   if( p == n ) {     for( int i = 0; i < n; ++i ) {       printf( "%d ", digits[i] );     }     printf( "\n" );   } else {     for( int i = p; i < n; ++i ) {       swap( &digits[p], &digits[i] );       permute( digits, n, p + 1 );       swap( &digits[p], &digits[i] );     }   } }   void print_permutations( int n ) {   int *digits = malloc( n * sizeof( int ) );   for( int i = 0; i < n; ++i ) {     digits[i] = i + 1;   }   permute( digits, n, 0 );   free( digits ); }   /************ PROBLEM 10 ************/   size_t search( int *data, size_t N, int value ) {   for( size_t i = 0; i < N; ++i ) {     if( data[i] == value ) {       return i;     }   }   return N; }   size_t binary_search( int *data, size_t N, int value ) {   size_t lo = 0, hi = N - 1;     while( lo < hi ) {     size_t mid = lo + ( hi - lo ) / 2;       if( data[mid] < value ) {       lo = mid + 1;     } else {       hi = mid;     }   }     return ( hi == lo && data[lo] == value ) ? lo : N; }   /************ TESTING ************/   void test_is_prime(void) {   int N_prime = 10, N_composite = 20;   int prime[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };   int composite[] = { 1, 4, 6, 8, 9, 10, 12, 14, 15, 16,                       18, 20, 21, 22, 24, 25, 26, 27, 28 };                          for( int i = 0; i < N_prime; ++i ) {     assert( is_prime( prime[i] ) );   }     for( int i = 0; i < N_composite; ++i ) {     assert( !is_prime( composite[i] ) );   } }   void test_print_permutations(void) {   print_permutations( 3 ); }   void test_search(void) {   size_t N = 7;   int data[] = { 1, 2, 3, 5, 9, 11, 101 };     assert( search( data, N, 0 ) == 7 );   assert( search( data, N, 10 ) == 7 );   assert( search( data, N, 11 ) == 5 );   assert( search( data, N, 102 ) == 7 );     assert( binary_search( data, N, 0 ) == 7 );   assert( binary_search( data, N, 10 ) == 7 );   assert( binary_search( data, N, 11 ) == 5 );   assert( binary_search( data, N, 102 ) == 7 ); }   void run_all_tests(void) {   test_is_prime();   test_print_permutations();   test_search(); }   int main(void) {   run_all_tests();   return 0; } 

 

Practices Illustrated

  • Functions with no parameters are declared with parameter void.
  • We use size_t for all array index types that could potentially be large.
  • Judicious horizontal spacing and minimal (but readable) vertical spacing.
  • Curly braces used always (even when optional).
  • Use of the bool type from C99's stdbool.h.
  • Variable names are descriptive, but not more verbose than necessary.
  • Each solution to a problem has a piece of code to test it.

 

« Back to Getting Started