Saturday, April 1, 2017

Programming Challenge 9.8 - Mode Function

/* Mode Function - In statistics, the mode of a set of values is the
   value that occurs most often or with the greatest frequency. This
   program contains a function that accepts the following arguments:
  
      * An array of integers
      * An integer that indicates the number of elements in the array
  
   The function determines the mode of the array. That is, it determines
   which value in the array occurs most often. The mode is the value the
   function returns. If the array has no mode (none of the values occur
   more than once), the function returns -1. (The assumption is that the
   array will always contain nonnegative values.)

   Pointer prowess is demonstrated by using pointer notation instead of
   array notation in this function. */

#include "Utility.h"

void getNumbers(int *, int);
void sortNumbers(int *, int);
void getFrequency(int *, int *, int);
void dualSort(int *, int *, int);
int  getMode(int *, int *, int *, int);
void displayMode(int *, int);
void displayHistogram(int *, int *, int);
void freeMem(int *, int *, int *);

int main()
{
   /* Dynamically allocated arrays to hold a list of numbers */
   int *numList = nullptr;
   int *frequency = nullptr;
   int *modes = nullptr;

   int numels = 0,
       count = 0,
       mode = 0;

   cout << "\n\tMODE DISCOVERY PROGRAM\n\n"
        << "\tHow many elements should your set of numbers contain? ";
   cin >> numels;

   numList = new int[numels];
   frequency = new int[numels]();
   modes = new int[numels]();
     
   /* Gets a set of (pseudo)random numbers and stores them in numList */
   getNumbers(numList, numels);

   /* Sorts the numbers with an selection-sort algorithm */
   sortNumbers(numList, numels);

   /* Determines and stores the frequency of numbers found in numList */
   getFrequency(numList, frequency, numels);

   /* Sorts the elements in numList and frequency in descending order
      using an dual-selection-sort algorithm */
   dualSort(numList, frequency, numels);

   /* Determines and returns the mode(s) or -1 if there is no mode */
   mode = getMode(numList, frequency, modes, numels);

   /* If the mode returned is not -1, the mode or modes are displayed */
   if (mode != -1)
   {
      displayMode(modes, numels);
   }
   else
   {
      cout << "\n\tThis set of numbers does not contain any modes!";
   }
  
   /* Displays a histogram */
   displayHistogram(numList, frequency, numels);

   /* Frees the memory before the program exits */
   freeMem(numList, frequency, modes);

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: getNumbers

   This function accepts numList and numels as its arguments.
   It creates a random list of numbers in the range from 1 to
   15 and stores these in the numList.
   ********************************************************** */

void getNumbers(int *numList, int numels)
{
   const int MIN_NUM = 1,
             MAX_NUM = 15;

   srand((unsigned int) time(NULL));

   for (int index = 0; index < numels; index++)
   {
      *(numList + index) = (rand() % (MAX_NUM - MIN_NUM + 1) + MIN_NUM);
   }
}

/* **********************************************************
   Definition: sortNumbers

   This function accepts numList and numels as its arguments.
   It uses a selection-sort algorithm to sort the number in
   ascending order.
   ********************************************************** */

void sortNumbers(int *numList, int numels)
{
   int startScan = 0,
       index = 0,
       minIndex = 0,
       minEl = 0;

   for (startScan = 0; startScan < numels; startScan++)
   {
      minIndex = startScan;
      minEl = *(numList + startScan);

      for (index = startScan + 1; index < numels; index++)
      {
         if (*(numList + index) < minEl)
         {
            minEl = *(numList + index);
            minIndex = index;
         }
      }

      *(numList + minIndex) = *(numList + startScan);
      *(numList + startScan) = minEl;
   }
}

/* **********************************************************
   Definition: getFrequency

   This function accepts numList, frequency and numels as its
   arguments. It counts the numbers stored in numList, totals
   these numbers, and stores the sum-total in frequency.
   ********************************************************** */

void getFrequency(int *numList, int *frequency, int numels)
{
   int total = 0,
       count = 0;

   /* Find numbers that are equal, and count these */
   for (int index = 0; index < numels; index++)
   {
      total = 0;
      count = 1;

      while (*(numList + index) == *(numList + index + 1))
      {
         count++;
         index++;
      }

      total = count;
      *(frequency + index) = total;
   }
}

/* **********************************************************
   Definition: sortFrequency

   This function accepts numList, frequency and numels as
   arguments. It uses a dual-sort selection-sort algorithm to
   sort numberList and frequency in descending order.
   ********************************************************** */

void dualSort(int *numList, int *frequency, int numels)
{
   int startScan = 0,
       index = 0,
       maxIndex = 0,
       tempList = 0,
       maxEl = 0;

   for (startScan = 0; startScan < numels; startScan++)
   {
      maxIndex = startScan;
      maxEl = *(frequency + startScan);
      tempList = *(numList + startScan);

      for (index = startScan + 1; index < numels; index++)
      {
         if (*(frequency + index) > maxEl)
         {
            maxEl = *(frequency + index);
            tempList = *(numList + index);
            maxIndex = index;
         }
      }

      *(frequency + maxIndex) = *(frequency + startScan);
      *(numList + maxIndex) = *(numList + startScan);

      *(frequency + startScan) = maxEl;
      *(numList + startScan) = tempList;
   }
}

/* **********************************************************
   Definition: getMode

   This function accepts numList, frequency, modes, and
   numels as arguments. First the function determines whether
   there are numbers more frequent than any other, modes gets
   this number. If there is no mode, -1 is returned.
   ********************************************************** */

int getMode(int *numList, int *frequency, int *modes, int numels)
{
   int index = 0,
       frHigh = 0,
       mode = 0;

   /* If all numbers in numList are the same, 3, 3, 3, or if
      frequency equals 1, meaning that no number has a higher
      occurence than any others, mode gets -1. */
   if (*(numList + index) == *(numList + index + 1) ||
       *(frequency + index) == 1)
   {
      mode = -1;
   }

   for (int index = 0; index < numels; index++)
   {
      if (*(frequency + index) > frHigh)
      {
         frHigh = *(frequency + index);
      }

      if (frHigh == *(frequency + index))
      {
         *(modes + index) = *(numList + index);
      }
   }

   return mode;
}

/* **********************************************************
   Definition: displayMode

   This function accepts modes, mode and numels as arguments.
   It displays the mode or modes found in the numList array.
   If no mode has been found, a message is displayed.
   ********************************************************** */

void displayMode(int *modes, int numels)
{
   cout << "\n\n\tMODES\n\n"
        << "\tThese mode(s) have been discovered: \n\n";

   for (int index = 0; index < numels; index++)
   {
      if (*(modes + index) > 0)
      {
         cout << "\tMode #" << (index + 1) << setw(14) << right
              << *(modes + index) << " \n";
      }
   }
}

/* **********************************************************
   Definition: displayHistogram

   This function accepts numList, frequency and numels as
   arguments. It displays all numbers in numList, sorted in
   order from highest to lowest, the frequency, and of occurence.
   ********************************************************** */

void displayHistogram(int *numList, int *frequency, int numels)
{
   int index = 0,
       total = 0,
       count = 0;

   cout << "\n\t\n\tHISTOGRAM\n\n"
        << "\tNUMBERS: " << setw(17) << right
        << "FREQUENCY:" << setw(17) << right
        << "HISTOGRAM:\n";

   cout << "\t-------" << setw(18) << right
        << "---------" << setw(17) << right
        << "---------\n";

   for (index = 0; index < numels; index++)
   {
      total = 0;

      if (*(frequency + index) > 0)
      {
         total = *(frequency + index);

         cout << setw(11) << right << *(numList + index)
              << setw(15) << right << *(frequency + index)
              << setw(15) << right;

         for (count = 1; count <= total; ++count)
         {
            cout << "*";
         }
         cout << "\n";
      }
   }
}

/* **********************************************************
   Definition: freeMem

   This function accepts numList, frequencies and multiMode
   as its arguments. It frees the memory before the program
   exits.
   ********************************************************** */

void freeMem(int *numList, int *frequency, int *modes)
{
   delete[] numList;
   delete[] frequency;
   delete[] modes;

   numList = nullptr;
   frequency = nullptr;
   modes = nullptr;
}

Example Output:





No comments:

Post a Comment