revised: 01/13/2008


Puzzles D01 ... D10

Part D — 2D Arrays

These puzzles involve 2D arrays. The dimensions of an array are given as row followed by column. A 3x5 array has 3 rows and 5 columns. Arrays are stored in main memory in row-major order, which means that the elements of a row are stored in sequence in memory. Conceptually a 3x5 array looks like this:

  Column
row 01234
001234
156789
21011121314

If an array has R rows, the rows are indexed 0 ... R-1. And if it has C columns, the columns are indexed 0 ... C-1. Of course, in main memory, the row and column numbers are not explicit. The elements of the array are stored in a contiguous block of memory, as follows (assume that memory addresses increase to the right):

01234 56789 1011121314

Because of this, code that accesses every element of a 2D array should be written, as follows, so that elements are accessed in sequence through memory:

  for ( r=0; r<Number_Of_Rows; r++ )
  {
    for ( c=0; c<Number_Of_Columns; c++ )
    {  
       ... do something with element[r][c] ...
    }
  }

Puzzle D01 — fill an N by M integer array with 0, 1, 2, ... and print it out.

[E-6] Write a main() that declares an N by M integer array and fills it with ascending integers starting with 0. After filling the array, print it to the terminal. Print one row of the array per output line. Let wrap-around take care of long lines.

Here is a skeleton of the program. Your job is to finish it. If you have a programming environment running (such as Bloodshed Dev-c++) use copy-and-paste to copy this code into a source file.

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

/* Puzzle D01 — fill an N by M integer array with ascending integers and print it out. */

int main(int argc, char *argv[])
{
  const int Nrows = 3, Mcols = 5 ;
  int x[Nrows][Mcols] ;
  
  int count = 0; /* value to copy to the array */
  
  int r, c;  /* row and column indexes for the array */
  
  /* Fill the array with ascending integers */

    
  /* Print out the array */

  
  printf("\n");
  system("PAUSE");	
  return 0;
}

As an alternate to copy-and=paste, click here for a Testing Framework


Two-D Arrays as Function Parameters

With old C compilers, if a function took a 2D array as a parameter, the function definition was required to explicitly show the number of columns (but not rows) in the array:

void function ( int x[][15], int nrows )
{
    . . .
}

The number of rows of the array could be a variable (as above). Often the preprocessor was used for this:

#define NUMCOLS 15

void function ( int x[][NUMCOLS], int nrows )
{
    . . .
}

If a program contained functions dealing with 2D arrays of different dimensions, each function had to be hard-coded for arrays with a particular number of columns. It did not work to have a function like the following:

void print2DArray ( int x[][], int nrows, int ncols )
{
    . . .
}

The reason for this strange requirement was that C compilers needed to know the number of elements in each row in order to output machine code that found the correct element in the block of memory used for the array. The number of elements in each row is the number of columns in the array.

Modern C compilers that conform to the current ANSI Standard allow both the number of rows and number of columns in array parameters to be variables. The following is legal for modern compilers:

void print2DArray ( int nrows, int ncols, int x[nrows][ncols] )
{
    . . .
}

In the above, the number of rows and number of columns must appear before the array so that they are defined before they are used. Arrays that have dimensions that are determined dynamically at run time are called flex arrays. The most recent Bloodshed Dev-C++ uses flex arrays.

However, in the following puzzles, the older style of array parameters are used. This is because a vast amount of C has been written using the older style of arrays, so you should learn to use it. Even with a modern compiler, most of the libraries you need use the older style arrays. You might be forced to use this style, even for development of new code.


Puzzle D02 — Function to print a 2D integer array

[E-6] Write a function that prints the elements of a 2D integer array. Write one row the the array per line on the screen. Copy and paste the following:

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

/* Puzzle D02 -- print a 2D integer array */
#define NUMCOLS 15
#define NUMROWS 5

void print2DArray ( int x[][NUMCOLS], int nrows )
{
}

int main(int argc, char *argv[])
{
  int x[NUMROWS][NUMCOLS] ;
  int count = 0;
  
  int r, c;  /* row and column indexes */
  
  /* Fill the array with ascending integers */
  for ( r=0; r<NUMROWS; r++ )
    for ( c=0; c<NUMCOLS; c++ )
      x[r][c] = count++ ;
    
  /* Print the array using your function */
  print2DArray( x, NUMROWS  );
  
  printf("\n");
  system("pause");	
  return 0;
}

Or, click here for a Testing Framework


Puzzle D03 — print a 2D integer array

[E-6] (Skip this puzzle if you have not yet seen pointer arithmetic.)

Write a function that prints the elements of a 2D integer array. Write one row of the the array per output line on the monitor. The function prototype shows a parameter that is a pointer to the first element of the array:

void print2DArray ( int *x, int nrows, int ncols );

Inside the function body use an expression like this to access the array elements:

*(x+ncols*r+c)

Here is a program skeleton. Notice how the array is initialized in main():

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

/* Puzzle D03 -- print a 2D integer array */
void print2DArray ( int *x, int nrows, int ncols )
{
}

int main(int argc, char *argv[])
{
  int x[3][7] = { { 0,  1,  2,  3,  4,  5,  6},
                  { 7,  8,  9, 10, 11, 12, 13},
                  {14, 15, 16, 17, 18, 19, 20} };
     
  /* Print the array using our function */
  print2DArray( x, 3, 7 );
  
  printf("\n");
  system("pause");	
  return 0;
}

Although main() declares the array as a two-dimensional array, in implementation it is a sequential block of ints in main memory which may be accessed through a pointer.

Click here for a Testing Framework


Puzzle D04 — write a function to fill an array with integers in ascending order

[E-4] Write a function that fills an array with integers in ascending order. Unlike puzzle D01, do the work in a function, not in main().

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

/* Puzzle D04 -- fill  an array with integers in ascending order */
#define NUMCOLS 5
#define NUMROWS 3

void print2DArray ( int x[][NUMCOLS], int nrows )
{
}

void fill2DArray ( int x[][NUMCOLS], int nrows )
{
}

int main(int argc, char *argv[])
{
  int x[NUMROWS][NUMCOLS] ;
  
  /* Fill the array with ascending integers */
  fill2DArray( x, NUMROWS );
      
  /* Print the array using our function */
  print2DArray( x, NUMROWS );
  
  printf("\n");
  system("pause");	
  return 0;
}

Click here for a Testing Framework


Puzzle D05 — Fill an integer array with random integers

[E-6] Write a function that fills an array with random integers in the range Low .. High

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

/* Puzzle D05 -- Fill an integer array with random integers */
#define NUMCOLS 15
#define NUMROWS 10

/* Generate a random integer  min <= r <= max */
int randInt( int min, int max )
{
  return (rand()*(max-min+1))/(RAND_MAX+1) + min ;
}

void print2DArray ( int x[][NUMCOLS], int nrows )
{
}

void randomFill2DArray ( int x[][NUMCOLS], int nrows, int low, int high )
{
}

int main(int argc, char *argv[])
{
  const int low = 10, high = 25;
  int x[NUMROWS][NUMCOLS] ;
  
  /* Fill the array with random integers */
  srand( time(NULL) );
  randomFill2DArray( x, NUMROWS, low, high );
      
  /* Print the array using our function */
  print2DArray( x, NUMROWS );
  
  printf("\n");
  system("pause");	
  return 0;
}

Click here for a Testing Framework


Puzzle D06 — add up the elements in a 2D integer array

[E-6] Write a function that adds up the elements in a 2D array. Here is the function prototype:

long add2DArray( int x[][NUMCOLS], int nrows )

Click here for a Testing Framework


Puzzle D07 — add up the elements in a 2D integer array

[M-6] Find a function from section C (1D arrays) of these puzzles that can be used to add up the elements in a 2D array. To do this, think about how a 2D array of integers is implemented as a sequence of integers in main memory, laid out in row major order.

Replace someFunction() with a 1D function, already written, from the previous section of puzzles. You will need to use a type cast to get this to work.

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

/* Puzzle D07 -- Fool a 1D function into adding the integers in a 2D array */
#define NUMCOLS 15
#define NUMROWS 10

/* Generate a random integer  min <= r <= max */
int randInt( int min, int max );
void print2DArray ( int x[][NUMCOLS], int nrows );
void randomFill2DArray ( int x[][NUMCOLS], int nrows, int low, int high );

long someFunction ()
{
   . . .
}

int main(int argc, char *argv[])
{
  const int low = 10, high = 25;
  
  int x[NUMROWS][NUMCOLS] ;
  long sum;
  
  /* Fill the array with random integers */
  srand( time(NULL) );
  randomFill2DArray( x, NUMROWS, low, high );
      
  /* Print the array using our function */
  print2DArray( x, NUMROWS );
      
  /* Fool the 1D function into computing the sum */
  sum =  someFunction ( . . . ) ;
  
  printf("\nThe sum is: %ld %ld\n", sum );
  
  printf("\n");
  system("pause");	
  return 0;
}

Click here for a Testing Framework


Puzzle D08 — Find the maximum element in a 2D array of integers

[E-6] Write a function that finds the maximum element in a 2D array of integers.

int findMax( int x[][NumColumns], int nrows )

Click here for a Testing Framework


Puzzle C09 — find the element in a 2D int array that is most distant from the average

[E-6] Write a function that does the following: Compute the average of the elements in a 2D array. Then find the element x in the array such that |x-avg| is maximized. You will need the function int abs( int ) from the standard libarary.

Click here for a Testing Framework


Puzzle D10 — set each element of a 2D array to row*10 + column

[E-5] Write a function that initializes an array so that an element at [row, col] has the value row*10 + column. This will be useful for debugging. An example of such an initialized array is:

 0  1  2  3  4
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34

Click here for a Testing Framework


— Return to the main contents page