Jump to: navigation, search

The C Programming Language, 2nd Edition, by Kernighan and Ritchie
Exercise 1.13 on page 24

Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging.



Solution by Liron Abutbul (Vertical Edition)

/* Write a program to print a histogram of the lengths of words in its input.
It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging. */

#include <stdio.h>

#define MAX_WORD_LENGTH 4 // maximum length of the word
#define MAX_FREQUENCY 4 // maximum frequency of the word length

#define MIN(a, b) ((a) < (b) ? (a) : (b)) // get the minimum value of a and b

int main(void) {
    int i, j, c, cnt;
    int wlen[MAX_WORD_LENGTH + 1]; // index 0 is not used, index 1 is for the word of length 2, index MAX_WORD_LENGTH + 1 is for the word of length bigger than MAX_WORD_LENGTH

    for(i = 0; i <= MAX_WORD_LENGTH; wlen[i++] = 0); // initialize the array
    
    /**
     * Count the length of the words in the input
    */
    while((c = getchar()) != EOF) {
        if(c == ' ' || c == '\n' || c == '\t') {
            wlen[MIN(cnt, MAX_WORD_LENGTH)]++;
            cnt = 0;
        } else {
            cnt++;
        }
    }

    printf("Histogram of the length of words in its input:\n");
    /**
     * Print the y-axis of the histogram with the frequency of the words
    */
    for(i = MAX_FREQUENCY; i >= 1; i--) {
        printf("\n");
        printf("%02d | ", i);
        for(j = 1; j <= MAX_WORD_LENGTH; j++) 
            printf(wlen[j] >= i ? "\u25A0  " : "   ");
    }

    /**
     * Print the x-axis of the histogram with the length of the words
    */
    printf("\n   +");
    for(i = 1; i <= MAX_WORD_LENGTH; i++) // print the horizontal line
        printf("———");

    printf("\nF/L "); // print the label of the x-axis (Frequency/Length)

    for(i = 1; i <= MAX_WORD_LENGTH; i++)
        printf("%02d ", i);

    return 0;
}
04 | ■  ■  ■        ■
03 | ■  ■  ■        ■     ■
02 | ■  ■  ■  ■     ■     ■
01 | ■  ■  ■  ■  ■  ■     ■  ■  ■
   +——————————————————————————————
F/L 01 02 03 04 05 06 07 08 09 10

Solution by Liron Abutbul (Horizontal Edition)

/* Write a program to print a histogram of the lengths of words in its input.
It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging. */

#include <stdio.h>

#define MAX_WORD_LENGTH 10 // maximum length of the word
#define MAX_FREQUENCY 4 // maximum frequency of the word length

#define MIN(a, b) ((a) < (b) ? (a) : (b)) // get the minimum value of a and b

int main(void) {
    int i, j, c, cnt;
    int wlen[MAX_WORD_LENGTH + 2]; // index 0 is not used, index 1 is for the word of length 2, index MAX_WORD_LENGTH + 1 is for the word of length bigger than MAX_WORD_LENGTH

    for(i = 0; i <= MAX_WORD_LENGTH; wlen[i++] = 0); // initialize the array
    
    /**
     * Count the length of the words in the input
    */
    while((c = getchar()) != EOF) {
        if(c == ' ' || c == '\n' || c == '\t') {
            wlen[MIN(cnt, MAX_WORD_LENGTH + 1)]++;
            cnt = 0;
        } else {
            cnt++;
        }
    }

    printf("Histogram of the length of words in its input:\n\n");
    /**
     * Print the y-axis of the histogram with the length of the words
    */
    for(i = 0; i <= MAX_WORD_LENGTH; i++) {
        printf("%02d | ", i);
        for(j = 0; j < wlen[i] && j < MAX_FREQUENCY + 1; j++) {
            printf("\u25A0  ");
        }
        printf("\n");
    }

    /**
     * Print the x-axis of the histogram with the frequency of the words
    */
    printf("   +");
    for(i = 0; i <= MAX_FREQUENCY; i++) // print the horizontal line
        printf("———");
    
    printf("\nL/F "); // print the label of the x-axis (Length/Frequency)

    for(i = 1; i <= MAX_FREQUENCY; i++)  // print the frequency of the words
        printf("%02d ", i);

    printf(">%02d\n", MAX_FREQUENCY + 1); // print the frequency of the words bigger than MAX_FREQUENCY

    return 0;
}
00 |
01 |
02 | ■  ■
03 | ■  ■  ■  ■  ■
04 | ■
05 |
06 | ■  ■  ■
07 | ■
08 |
09 |
10 |
   +———————————————
L/F 01 02 03 04 >05

Solution by Vidhan Gupta

/* Write a program to print a histogram of the lengths of words in its input.
It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging. */

#include <stdio.h>

#define IN 1
#define OUT 0

int main()
{
    int i, j, c, state = OUT, count = 0, white = 0;
    int wordLength[10];
    for (i = 0; i < 10; ++i)
        wordLength[i] = 0;

    while ((c = getchar()) != EOF)
    {
        if (c == ' ' || c == '\n' || c == '\t')
        {
            ++white;
            ++wordLength[count];
            count = 0;
            state = OUT;
        }
        else if (state == OUT)
        {
            state = IN;
        }
        else if (state == IN)
            ++count;
    }

    for (i = 0; i < 10; ++i)
        printf("%d, ", wordLength[i]);

    printf("\nword length 0 = ");
    for (i = 0; i < white; ++i)
        putchar('*');
    putchar('\n');

    for (i = 0; i < 10; i++)
    {
        printf("word lenght %d = ", i + 1);
        for (j = 0; j < wordLength[i]; j++)
        {
            putchar('*');
        }
        putchar('\n');
    }

    return 0;
}
OUTPUT:
What the hell   is this
0, 1, 1, 3, 0, 0, 0, 0, 0, 0, 
word length 0 = *****
word lenght 1 = 
word lenght 2 = *
word lenght 3 = *
word lenght 4 = ***
word lenght 5 = 
word lenght 6 = 
word lenght 7 = 
word lenght 8 = 
word lenght 9 = 
word lenght 10 = 

Solution by Vidhan Gupta (Vertical Edition)

/* Write a program to print a histogram of the lengths of words in its input.
It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging. */

// This is for a vertical orientation:
#include <stdio.h>

#define IN 1
#define OUT 0

int main()
{
    int i, j, c, state = OUT, count = 0, white = 0;
    int wordLength[10];
    for (i = 0; i < 10; ++i)
        wordLength[i] = 0;

    while ((c = getchar()) != EOF)
    {
        if (c == ' ' || c == '\n' || c == '\t')
        {
            ++white;
            ++wordLength[count];
            count = 0;
            state = OUT;
        }
        else if (state == OUT)
        {
            state = IN;
        }
        else if (state == IN)
            ++count;
    }

    for (i = 0; i < 10; ++i)
        printf("%d, ", wordLength[i]);

    int maximum = wordLength[0];

    for (i = 0; i < 10; ++i)
    {
        if (wordLength[i] > maximum)
            maximum = wordLength[i];
    }
    putchar('\n');
    printf("%d\n", maximum);

    for (i = maximum; i > 0; --i)
    {
        printf("%d|", i);
        for (j = 0; j < 10; ++j)
        {
            if (wordLength[j] == i)
            {
                putchar('*');
                --wordLength[j];
            }
            else
                putchar(' ');
        }
        putchar('\n');
    }
    printf("  ");
    for (i = 1; i <= 10; ++i)
        printf("%d", i);
    putchar('\n');

    return 0;
}
OUTPUT:
What the hell you are doing here? 
Are you sure that you are a human ?
2, 0, 7, 4, 3, 0, 0, 0, 0, 0, 
7
7|  *       
6|  *       
5|  *       
4|  **      
3|  ***     
2|* ***     
1|* ***     
  12345678910

Solution by Richard Heathfield (Category 0)

/* This program was the subject of a thread in comp.lang.c, because of the way it handled EOF.
 * The complaint was that, in the event of a text file's last line not ending with a newline,
 * this program would not count the last word. I objected somewhat to this complaint, on the
 * grounds that "if it hasn't got a newline at the end of each line, it isn't a text file".
 *
 * These grounds turned out to be incorrect. Whether such a file is a text file turns out to
 * be implementation-defined. I'd had a go at checking my facts, and had - as it turns out -
 * checked the wrong facts! (sigh)
 *
 * It cost Richard Heathfield an extra variable. It turned out that the least disturbing way to modify the
 * program (I always look for the least disturbing way) was to replace the traditional
 * while((c = getchar()) != EOF) with an EOF test actually inside the loop body. This meant
 * adding an extra variable, but is undoubtedly worth the cost, because it means the program
 * can now handle other people's text files as well as my own. As Ben Pfaff said at the
 * time, "Be liberal in what you accept, strict in what you produce". Sound advice.
 *
 * The new version has, of course, been tested, and does now accept text files not ending in
 * newlines.
 *
 * I have, of course, regenerated the sample output from this program. Actually, there's no
 * "of course" about it - I nearly forgot.
 */

#include <stdio.h>

#define MAXWORDLEN 10

int main(void)
{
  int c;
  int inspace = 0;
  long lengtharr[MAXWORDLEN + 1];
  int wordlen = 0;

  int firstletter = 1;
  long thisval = 0;
  long maxval = 0;
  int thisidx = 0;
  int done = 0;

  for(thisidx = 0; thisidx <= MAXWORDLEN; thisidx++)
  {
    lengtharr[thisidx] = 0;
  }

  while(done == 0)
  {
    c = getchar();

    if(c == ' ' || c == '\t' || c == '\n' || c == EOF)
    {
      if(inspace == 0)
      {
        firstletter = 0;
        inspace = 1;

        if(wordlen <= MAXWORDLEN)
        {
          if(wordlen > 0)
          {
            thisval = ++lengtharr[wordlen - 1];
            if(thisval > maxval)
            {
              maxval = thisval;
            }
          }
        }
        else
        {
          thisval = ++lengtharr[MAXWORDLEN];
          if(thisval > maxval)
          {
            maxval = thisval;
          }
        }
      }
      if(c == EOF)
      {
        done = 1;
      }
    }
    else
    {
      if(inspace == 1 || firstletter == 1)
      {
        wordlen = 0;
        firstletter = 0;
        inspace = 0;
      }
      ++wordlen;
    }
  }

  for(thisval = maxval; thisval > 0; thisval--)
  {
    printf("%4d  | ", thisval);
    for(thisidx = 0; thisidx <= MAXWORDLEN; thisidx++)
    {
      if(lengtharr[thisidx] >= thisval)
      {
        printf("*  ");
      }
      else
      {
        printf("   ");
      }
    }
    printf("\n");
  }
  printf("      +");
  for(thisidx = 0; thisidx <= MAXWORDLEN; thisidx++)
  {
    printf("---");
  }
  printf("\n       ");
  for(thisidx = 0; thisidx < MAXWORDLEN; thisidx++)
  {
    printf("%2d ", thisidx + 1);
  }
  printf(">%d\n", MAXWORDLEN);

  return 0;
}


Here's the output of the program when given its own source as input:

 113  | *                                
 112  | *                                
 111  | *                                
 110  | *                                
 109  | *                                
 108  | *                                
 107  | *                                
 106  | *                                
 105  | *                                
 104  | *                                
 103  | *                                
 102  | *                                
 101  | *                                
 100  | *                                
  99  | *                                
  98  | *                                
  97  | *                                
  96  | *                                
  95  | *                                
  94  | *  *                             
  93  | *  *                             
  92  | *  *                             
  91  | *  *                             
  90  | *  *                             
  89  | *  *                             
  88  | *  *                             
  87  | *  *                             
  86  | *  *                             
  85  | *  *                             
  84  | *  *                             
  83  | *  *                             
  82  | *  *                             
  81  | *  *                             
  80  | *  *                             
  79  | *  *                             
  78  | *  *                             
  77  | *  *                             
  76  | *  *                             
  75  | *  *                             
  74  | *  *                             
  73  | *  *                             
  72  | *  *                             
  71  | *  *                             
  70  | *  *                             
  69  | *  *                             
  68  | *  *                             
  67  | *  *                             
  66  | *  *                             
  65  | *  *                             
  64  | *  *                             
  63  | *  *  *                          
  62  | *  *  *                          
  61  | *  *  *                          
  60  | *  *  *                          
  59  | *  *  *                          
  58  | *  *  *                          
  57  | *  *  *                          
  56  | *  *  *                          
  55  | *  *  *                          
  54  | *  *  *                          
  53  | *  *  *                          
  52  | *  *  *  *                       
  51  | *  *  *  *                       
  50  | *  *  *  *                       
  49  | *  *  *  *                       
  48  | *  *  *  *                       
  47  | *  *  *  *                       
  46  | *  *  *  *                       
  45  | *  *  *  *                       
  44  | *  *  *  *                       
  43  | *  *  *  *        *              
  42  | *  *  *  *        *              
  41  | *  *  *  *        *              
  40  | *  *  *  *        *              
  39  | *  *  *  *        *              
  38  | *  *  *  *        *              
  37  | *  *  *  *        *              
  36  | *  *  *  *        *              
  35  | *  *  *  *        *              
  34  | *  *  *  *        *              
  33  | *  *  *  *        *              
  32  | *  *  *  *        *              
  31  | *  *  *  *        *              
  30  | *  *  *  *        *           *  
  29  | *  *  *  *        *           *  
  28  | *  *  *  *  *     *           *  
  27  | *  *  *  *  *     *           *  
  26  | *  *  *  *  *     *           *  
  25  | *  *  *  *  *  *  *           *  
  24  | *  *  *  *  *  *  *           *  
  23  | *  *  *  *  *  *  *           *  
  22  | *  *  *  *  *  *  *        *  *  
  21  | *  *  *  *  *  *  *        *  *  
  20  | *  *  *  *  *  *  *        *  *  
  19  | *  *  *  *  *  *  *        *  *  
  18  | *  *  *  *  *  *  *        *  *  
  17  | *  *  *  *  *  *  *        *  *  
  16  | *  *  *  *  *  *  *        *  *  
  15  | *  *  *  *  *  *  *        *  *  
  14  | *  *  *  *  *  *  *  *     *  *  
  13  | *  *  *  *  *  *  *  *     *  *  
  12  | *  *  *  *  *  *  *  *     *  *  
  11  | *  *  *  *  *  *  *  *     *  *  
  10  | *  *  *  *  *  *  *  *     *  *  
   9  | *  *  *  *  *  *  *  *  *  *  *  
   8  | *  *  *  *  *  *  *  *  *  *  *  
   7  | *  *  *  *  *  *  *  *  *  *  *  
   6  | *  *  *  *  *  *  *  *  *  *  *  
   5  | *  *  *  *  *  *  *  *  *  *  *  
   4  | *  *  *  *  *  *  *  *  *  *  *  
   3  | *  *  *  *  *  *  *  *  *  *  *  
   2  | *  *  *  *  *  *  *  *  *  *  *  
   1  | *  *  *  *  *  *  *  *  *  *  *  
      +---------------------------------
        1  2  3  4  5  6  7  8  9 10 >10


Solution by Arnuld (Category 0)

This one is the horizontal-histogram. Since Richard Heathfield only created the vertical-histogram, so i thought posting horizontal-histogram will be good. In fact, it is much easier, a Vertical-Histogram is a mind-bending exercise // Those solutions do not count the last word if the input after it ends with EOF.

/* K&R2, section 1.6 Arrays, exercise 1-13

STATEMENT:
write a programme to print a histogram of the lengths
of words in ts input.


METHOD to solve the problem:

1.) we will create an array which will hold a number corresponding to 
how many times a that specific length occurs.

2.) for simplicity, we will not consider words with length > 10. any words
    having more than 10 characters will be discarded.

3.) First we will attempt a horizontal histogram

*/

#include <stdio.h>

#define MAXWORDLEN 10
#define IN          1
#define OUT         0


int main()
{
  int c = EOF;
  int i = 0;
  int j = 0;
  int arr_of_len[MAXWORDLEN + 1];
  int state = IN;
  int nc = 0;

  
  for(i = 0; i <= MAXWORDLEN; ++i)
    arr_of_len[i] = 0;

  while((c = getchar()) != EOF)
    {
      ++nc;

      if(c == ' ' || c == '\t' || c == '\n')
	{
	  state = OUT;
	  --nc;
	}

      if(state == OUT)
	{
	  if(nc != 0 && nc <= MAXWORDLEN)
	    ++arr_of_len[nc];
	      
	  state = IN;
	  nc = 0;
	}
    }

  for(i=1; i <= MAXWORDLEN; ++i)
    {
      printf("|%2d| ", i);
      for(j = 0; j < arr_of_len[i]; ++j)
	putchar('*');
      
      putchar('\n');
    }


  return 0;
}   


Here's the output of the program when given its own source as input:

| 1| *******************************************
| 2| *****************************************
| 3| ***********************
| 4| *********************
| 5| ********************
| 6| *********
| 7| ********
| 8| ********
| 9| ****
|10| ******



This one is a little different:

/* K&R2: 1.6 Arrays, exercise 1-13

STATEMENT:
write a programme to print a histogram of the lengths of words
in input. it is easy to draw the histogram with bars horizontal;
a vertical orientation i smore challenging.

NOTE: this code uses HORIZONTAL bars.


METHOD:


1.) we will count the length of each word by counting the 
characters it has.
 
2.) we use an array where we will keep track of how many words 
of a specific length we have encountered.

3.) for simplicity, we will not take into account any words 
having more than 10 characters in it. extra characters will
simply be discarded.

*/


#include<stdio.h>

#define IN        1
#define OUT       0
#define MAXLENGTH 11

int main()
{
  int i = 0;
  int j =0;  /* i and j are simply index counters */  
  int c = 0;
  int nchar = 0;  /* number of characters in a word */
  int inspace = IN; /* a flag to know whether we are inside of outside the word */ 
  int wordlen[MAXLENGTH]; /* counts how many words of a particular length we have seen */

  for(i = 0; i < MAXLENGTH; ++i)
    wordlen[i] = 0;

  while((c = getchar()) != EOF)
    {
      if(c == ' ' || c == '\t' || c == '\n')
	{
	  if (inspace == OUT)
	    {
	      if(nchar < MAXLENGTH)
		++wordlen[nchar];
	    }
	  
	  inspace = IN;
	  nchar = 0;
	}
      else
	{
	  ++nchar;
	  if(c == '"' || c == '\'')
	    --nchar;
	  inspace = OUT;
	}
    }


  /* printing the Horizontal-Histogram */
  for(i = 1; i < MAXLENGTH; ++i)
    {
      printf("%2d| ", i);
      for(j = 0; j < wordlen[i]; ++j)
	putchar('*');

      putchar('\n');
    }

  
  return 0;
}


Here's the output of the program when given its own source as input:

 1| *********************************************
 2| *************************************************
 3| ****************************
 4| *******************************
 5| *******************
 6| *******
 7| **********
 8| **********
 9| ****
10| ***********

Solution by Flash Gordon (Category 1)

This one is heavily based on Richard's solution above but it uses features of C beyond those discussed in chapter 1 of K&R 2. When I say heavily based on Richard's solution, I mean that I started with his code and edited it a bit at a time in to what you see below.

#include <stdio.h>
#include <limits.h>

#define MAXWORDLEN 10

int main(void)
{
  int c;
  int inspace = 0;
  unsigned long lengtharr[MAXWORDLEN + 1] = { 0 };
  int wordlen = 0;
  unsigned long thisval;
  unsigned long maxval = 0;
  int countdigits = 1;
  unsigned long countdiglim = 10;
  int thisidx;

  do {
    c = getchar();

    if (c == ' ' || c == '\t' || c == '\n' || c == EOF) {
      if (!inspace) {
        inspace = 1;

        if (wordlen > 0) {
          if (wordlen > MAXWORDLEN+1)
            wordlen = MAXWORDLEN+1;

          if (lengtharr[wordlen - 1] < ULONG_MAX) {
            thisval = ++lengtharr[wordlen - 1];
            if (thisval > maxval) {
              maxval = thisval;
              if (maxval >= countdiglim) {
                ++countdigits;
                countdiglim *= 10;
              }
            }
          }
        }
        wordlen = 0;
      }
    }
    else {
      inspace = 0;
      wordlen++;
    }
  } while (c != EOF);

  for (thisval = maxval; thisval > 0; thisval--) {
    if (thisval == ULONG_MAX)
      printf("%*s  | ", countdigits, "lots");
    else
      printf("%*lu  | ", countdigits, thisval);
    for (thisidx = 0; thisidx <= MAXWORDLEN; thisidx++) {
      if (lengtharr[thisidx] >= thisval)
        printf("*  ");
      else
        printf("   ");
    }
    printf("\n");
  }

  printf("  %*s+",countdigits,"");
  for(thisidx = 0; thisidx <= MAXWORDLEN; thisidx++)
    printf("---");

  printf("\n   %*s",countdigits,"");
  for(thisidx = 0; thisidx < MAXWORDLEN; thisidx++)
    printf("%2d ", thisidx + 1);
  printf(">%d\n", MAXWORDLEN);

  return 0;
}


Here's the output of the program when given its own source as input:

59  | *
58  | *
57  | *
56  | *
55  | *
54  | *
53  | *
52  | *
51  | *
50  | *
49  | *
48  | *
47  | *  *
46  | *  *
45  | *  *
44  | *  *
43  | *  *
42  | *  *
41  | *  *
40  | *  *
39  | *  *
38  | *  *
37  | *  *
36  | *  *
35  | *  *
34  | *  *
33  | *  *
32  | *  *
31  | *  *
30  | *  *
29  | *  *
28  | *  *
27  | *  *                          *
26  | *  *                          *
25  | *  *                          *
24  | *  *                          *
23  | *  *                          *
22  | *  *                          *
21  | *  *                          *
20  | *  *                          *
19  | *  *                 *        *
18  | *  *                 *        *
17  | *  *                 *        *
16  | *  *              *  *        *
15  | *  *              *  *        *
14  | *  *  *           *  *        *
13  | *  *  *           *  *     *  *
12  | *  *  *           *  *     *  *
11  | *  *  *           *  *     *  *
10  | *  *  *  *        *  *     *  *
 9  | *  *  *  *        *  *     *  *
 8  | *  *  *  *        *  *     *  *
 7  | *  *  *  *        *  *     *  *
 6  | *  *  *  *        *  *     *  *
 5  | *  *  *  *        *  *     *  *
 4  | *  *  *  *        *  *     *  *
 3  | *  *  *  *     *  *  *  *  *  *
 2  | *  *  *  *  *  *  *  *  *  *  *
 1  | *  *  *  *  *  *  *  *  *  *  *
    +---------------------------------
      1  2  3  4  5  6  7  8  9 10 >10

Solution by Pilcrow

/********************************************************
I think this is Category 0, but I may be wrong.

I didn't look at any other soutions before I wrote this,
and I have no idea what similarity it may or may not have
to other solutions.  I give a statistical summary of word
lengths, followed by both a horiontal and a vertical
histograph. The input need not be ended by a newline.
-- Pilcrow
********************************************************/

#include <stdio.h>
#define is__lower(N) ((N) >= 'a' && (N) <= 'z')
#define is__upper(N) ((N) >= 'A' && (N) <= 'Z')
#define is__alpha(N) (is__upper(N) || is__lower(N))
#define OUT__WORD    0
#define IN__WORD     1
#define MAX_WRD_LEN  1000

int main()
{
    int status, longest, most, i, j, k, len;
    char c;
    int word[MAX_WRD_LEN];

    for(i=0;i < MAX_WRD_LEN;i++){word[i] = 0;}  /* clear counts */
    len = 0;
    status = OUT__WORD;

    while((c=getchar())!= EOF) {       /* for each input char */
        if(is__alpha(c)) {             /* if an alphabetic */
            if(status == OUT__WORD) {  /* beginning word? */
                status = IN__WORD;     /* now inside a word */
                ++word[len];           /* bump prev word length's count */
                len = 1;               /* reset to words of length 1 */
            }else {++len;}             /* in a word, bump length of current word */
        }else {                        /* not an alphabetic */
            status = OUT__WORD;        /* now not in a word */
        }
    }
    ++word[len];                       /* bump last word length count */

    longest = 0, most = 0;
    puts("\nSTATISTICS\n");
    for(i=1;i< MAX_WRD_LEN;i++) {
        if(word[i] && i > longest)longest = i;
        if(word[i] > most)most=word[i];
        if(word[i]){printf("%2d words of length %d\n",word[i],i);}
    }
    printf("\ngreatest word length: %d\n",longest);
    printf("most words of a given length: %d\n",most);

/* horizontal histograph */
    puts("\nHORIONTAL HISTOGRAPH");
    puts("\nword length | graph");
    for(i=1;i <=longest; i++) {
        printf("%11d : ",i);
        for(j=1;j<=word[i];j++) printf("x");
        putchar('\n');
    }

/* vertical histograph */
    puts("\nVERTICAL HISTOGRAPH");
    puts("\nWd Ct:");
    for(k=most;k>0;k--) {
        printf("%5d:   ",k);
        for(i = 1; i<= longest; i++) {
            if(word[i] < k) printf("    ");
            else printf("x   ");
        }
        putchar('\n');
    }
    printf("      ");
    for(i=1;i<=longest;i++)printf("====");
    printf("\nWd Ln:");
    for(i=1;i<=longest;i++)printf("%4d",i);
    putchar('\n');
    return 0;
}


Here's the output of the program when given its own source as input:


STATISTICS

91 words of length 1
37 words of length 2
51 words of length 3
61 words of length 4
26 words of length 5
35 words of length 6
19 words of length 7
 5 words of length 8
 5 words of length 9
10 words of length 10
 2 words of length 11

greatest word length: 11
most words of a given length: 91

HORIONTAL HISTOGRAPH

word length | graph
          1 : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          2 : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          3 : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          4 : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          5 : xxxxxxxxxxxxxxxxxxxxxxxxxx
          6 : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          7 : xxxxxxxxxxxxxxxxxxx
          8 : xxxxx
          9 : xxxxx
         10 : xxxxxxxxxx
         11 : xx

VERTICAL HISTOGRAPH

Wd Ct:
   91:   x
   90:   x
   89:   x
   88:   x
   87:   x
   86:   x
   85:   x
   84:   x
   83:   x
   82:   x
   81:   x
   80:   x
   79:   x
   78:   x
   77:   x
   76:   x
   75:   x
   74:   x
   73:   x
   72:   x
   71:   x
   70:   x
   69:   x
   68:   x
   67:   x
   66:   x
   65:   x
   64:   x
   63:   x
   62:   x
   61:   x           x
   60:   x           x
   59:   x           x
   58:   x           x
   57:   x           x
   56:   x           x
   55:   x           x
   54:   x           x
   53:   x           x
   52:   x           x
   51:   x       x   x
   50:   x       x   x
   49:   x       x   x
   48:   x       x   x
   47:   x       x   x
   46:   x       x   x
   45:   x       x   x
   44:   x       x   x
   43:   x       x   x
   42:   x       x   x
   41:   x       x   x
   40:   x       x   x
   39:   x       x   x
   38:   x       x   x
   37:   x   x   x   x
   36:   x   x   x   x
   35:   x   x   x   x       x
   34:   x   x   x   x       x
   33:   x   x   x   x       x
   32:   x   x   x   x       x
   31:   x   x   x   x       x
   30:   x   x   x   x       x
   29:   x   x   x   x       x
   28:   x   x   x   x       x
   27:   x   x   x   x       x
   26:   x   x   x   x   x   x
   25:   x   x   x   x   x   x
   24:   x   x   x   x   x   x
   23:   x   x   x   x   x   x
   22:   x   x   x   x   x   x
   21:   x   x   x   x   x   x
   20:   x   x   x   x   x   x
   19:   x   x   x   x   x   x   x
   18:   x   x   x   x   x   x   x
   17:   x   x   x   x   x   x   x
   16:   x   x   x   x   x   x   x
   15:   x   x   x   x   x   x   x
   14:   x   x   x   x   x   x   x
   13:   x   x   x   x   x   x   x
   12:   x   x   x   x   x   x   x
   11:   x   x   x   x   x   x   x
   10:   x   x   x   x   x   x   x           x
    9:   x   x   x   x   x   x   x           x
    8:   x   x   x   x   x   x   x           x
    7:   x   x   x   x   x   x   x           x
    6:   x   x   x   x   x   x   x           x
    5:   x   x   x   x   x   x   x   x   x   x
    4:   x   x   x   x   x   x   x   x   x   x
    3:   x   x   x   x   x   x   x   x   x   x
    2:   x   x   x   x   x   x   x   x   x   x   x
    1:   x   x   x   x   x   x   x   x   x   x   x
      ============================================
Wd Ln:   1   2   3   4   5   6   7   8   9  10  11

Solution by Bocchio (Category 0)

This program assumes little input with no more than 99 repetitions of each length. This can be easily increased.

#include <stdio.h>

/* Prints a histogram of the length of words in the input                    */
/*****************************************************************************/
/* This program doesn't count the last word if the input didn't finished in  */
/* a blank. Fortunately in the bast majority of cases the last character is  */
/* a new line character                                                      */
/*****************************************************************************/
/* Vertical version                                                          */

int main()
{
    int len_freq[11];          /* Stores the freq of each length             */
    int length, height;        /* Stores actual length and highest freq      */
    int c, i, k;

    length = height = 0;       /* Start with current length and highest      */
                               /* frequency being 0                          */
    for(i = 0; i <= 10; ++i)   /* Initialise each element of the len_freq    */
        len_freq[i] = 0;       /* array to be 0                              */

    /* Reads the input storing each frequency                                */
    while((c = getchar()) != EOF){
        if(c != ' ' && c != '\n' && c != '\t')
            ++length;
        else if(length != 0){
            if(length <= 10){
                ++len_freq[length-1];
                if(height < len_freq[length-1])
                    height = len_freq[length-1];
            }
            else{
                ++len_freq[10];
                if(height < len_freq[10])
                    height = len_freq[10];
            }
            length = 0;
        }
    }

    /* Creates the histogram                                                 */
    for(i = height; i > 0; --i){
        printf("%2d|", i);
        for(k = 0; k <= 10; ++k){
            if(len_freq[k] >= i)
                printf("   #");
            else
                printf("    ");
        }
        printf("\n");
    }

    printf("  +");
    for(i = 0; i <= 10; ++i)
        printf("----");
    printf("\n   ");

    for(i = 0; i <= 10; ++i){
        if(i < 10)
            printf("%4d", i+1);
        else
            printf(" +10");
    }
    printf("\n");

    return 0;
}

Here's the output of the program when given its own source as input:

63|       #                                    
62|       #                                    
61|       #                                    
60|       #                                    
59|       #                                    
58|       #                                    
57|       #                                    
56|       #                                    
55|       #                                    
54|       #                                    
53|       #                                    
52|       #                                    
51|       #                                    
50|       #                                    
49|       #                                    
48|       #                                    
47|       #                                    
46|       #                                    
45|       #                                    
44|       #                                    
43|       #                                    
42|       #                                    
41|       #                                    
40|       #                                    
39|   #   #                                    
38|   #   #                                    
37|   #   #                                    
36|   #   #                                    
35|   #   #                                    
34|   #   #                                    
33|   #   #                                    
32|   #   #                                    
31|   #   #                                    
30|   #   #                                    
29|   #   #                                    
28|   #   #                                    
27|   #   #                                    
26|   #   #   #                                
25|   #   #   #                                
24|   #   #   #                                
23|   #   #   #   #                            
22|   #   #   #   #   #                        
21|   #   #   #   #   #                        
20|   #   #   #   #   #                        
19|   #   #   #   #   #                        
18|   #   #   #   #   #   #                    
17|   #   #   #   #   #   #                   #
16|   #   #   #   #   #   #                   #
15|   #   #   #   #   #   #                   #
14|   #   #   #   #   #   #                   #
13|   #   #   #   #   #   #                   #
12|   #   #   #   #   #   #   #               #
11|   #   #   #   #   #   #   #       #       #
10|   #   #   #   #   #   #   #   #   #       #
 9|   #   #   #   #   #   #   #   #   #       #
 8|   #   #   #   #   #   #   #   #   #       #
 7|   #   #   #   #   #   #   #   #   #       #
 6|   #   #   #   #   #   #   #   #   #       #
 5|   #   #   #   #   #   #   #   #   #       #
 4|   #   #   #   #   #   #   #   #   #   #   #
 3|   #   #   #   #   #   #   #   #   #   #   #
 2|   #   #   #   #   #   #   #   #   #   #   #
 1|   #   #   #   #   #   #   #   #   #   #   #
  +--------------------------------------------
      1   2   3   4   5   6   7   8   9  10 +10

Solution by dchaudh (Category 0)

#include <stdio.h>

#define ON               1
#define OFF              0
#define MAX_ARRAY_LENGTH 100

int main(int argv, char *argc[])
{
  //parse input
  int currentWordLength = 0;
  char c                = 0x0;
  int wasInWord         = 0;
  int isInWord          = 0;

  int frequencies[MAX_ARRAY_LENGTH];
  for(int i = 0; i < MAX_ARRAY_LENGTH; ++i) //initialize to zero
    frequencies[i] = 0;
  
  while( (c = getchar()) != EOF )
  {
    isInWord = (c >= 0x21) && (c <= 0x7E);
    
    if (isInWord)
      currentWordLength++;
    else if ( wasInWord )
    {
      ++frequencies[ currentWordLength - 1 ];
      currentWordLength = 0;
    }

    wasInWord = isInWord;
  }

  //measure histogram bars and store as an array
  int maxWordLength = 0;
  int maxFrequency  = 0;

  for(int i = 0 ;i < MAX_ARRAY_LENGTH; ++i)
  {
    if ( frequencies[i] > 0 )
    {
      maxWordLength = i+1;

      if ( frequencies[i] > maxFrequency )
        maxFrequency = frequencies[i];
    }
  }

  int maxY = maxFrequency;
  int maxX = maxWordLength;
  
  char verticalHistogram[ maxY ][ maxX ];
  for(int i = 0; i < maxX; ++i)
  {
    for(int j = 0; j <= maxY; ++j)
      verticalHistogram [j][i] =
          ( j >= maxY - frequencies[i] ) && ( j < maxY ) ? '*' : ' ';
  }

  //print histogram and accompanying table
  printf("\n\nHistogram of Frequency (y-axis) vs. Word Length (x-axis):\n\n");

  for(int j = 0; j < maxY; ++j)
  {
    printf("%11d%1s",maxY-j,"|");
    for(int i = 0; i < maxX; ++i)
    {
      printf("%4c",verticalHistogram[j][i]);
    }
    printf("\n");
  }

  printf("%12s","");

  for(int i = 0; i < maxX; ++i)
    printf("----");
  
  printf("\n%11s",   "Word Length:");
  for(int i = 0; i < maxX; ++i)
    printf("%4d", i+1 );

  printf("\n%11s", "Frequency:  ");
  for(int i = 0; i < maxX; ++i)
    printf("%4d", frequencies[i]);

  printf("\n\n");

  return 1;
}


Here's the result from parsing the Gettysburg Address:


Four score and seven years ago our fathers brought forth on this continent, a new nation, 
conceived in Liberty, and dedicated to the proposition that all men are created equal.

Now we are engaged in a great civil war, testing whether that nation, or any nation so 
conceived and dedicated, can long endure. We are met on a great battle-field of that war. 
We have come to dedicate a portion of that field, as a final resting place for those who 
here gave their lives that that nation might live. It is altogether fitting and proper 
that we should do this.

But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not 
hallow -- this ground. The brave men, living and dead, who struggled here, have consecrated 
it, far above our poor power to add or detract. The world will little note, nor long remember 
what we say here, but it can never forget what they did here. It is for us the living, 
rather, to be dedicated here to the unfinished work which they who fought here have thus 
far so nobly advanced. It is rather for us to be here dedicated to the great task remaining 
before us -- that from these honored dead we take increased devotion to that cause for which 
they gave the last full measure of devotion -- that we here highly resolve that these dead 
shall not have died in vain -- that this nation, under God, shall have a new birth of 
freedom -- and that government of the people, by the people, for the people, shall not 
perish from the earth.



Histogram of Frequency (y-axis) vs. Word Length (x-axis):

         56|           *   *                            
         55|           *   *                            
         54|           *   *                            
         53|           *   *                            
         52|           *   *                            
         51|           *   *                            
         50|           *   *                            
         49|       *   *   *                            
         48|       *   *   *                            
         47|       *   *   *                            
         46|       *   *   *                            
         45|       *   *   *                            
         44|       *   *   *                            
         43|       *   *   *                            
         42|       *   *   *                            
         41|       *   *   *                            
         40|       *   *   *                            
         39|       *   *   *                            
         38|       *   *   *                            
         37|       *   *   *   *                        
         36|       *   *   *   *                        
         35|       *   *   *   *                        
         34|       *   *   *   *                        
         33|       *   *   *   *                        
         32|       *   *   *   *                        
         31|       *   *   *   *                        
         30|       *   *   *   *                        
         29|       *   *   *   *                        
         28|       *   *   *   *                        
         27|       *   *   *   *                        
         26|       *   *   *   *                        
         25|       *   *   *   *                        
         24|       *   *   *   *                        
         23|       *   *   *   *       *                
         22|       *   *   *   *       *                
         21|       *   *   *   *       *                
         20|       *   *   *   *       *                
         19|       *   *   *   *       *                
         18|       *   *   *   *   *   *                
         17|       *   *   *   *   *   *                
         16|       *   *   *   *   *   *                
         15|       *   *   *   *   *   *                
         14|       *   *   *   *   *   *                
         13|       *   *   *   *   *   *                
         12|       *   *   *   *   *   *                
         11|       *   *   *   *   *   *       *        
         10|       *   *   *   *   *   *       *        
          9|       *   *   *   *   *   *       *        
          8|       *   *   *   *   *   *       *        
          7|   *   *   *   *   *   *   *       *        
          6|   *   *   *   *   *   *   *   *   *        
          5|   *   *   *   *   *   *   *   *   *        
          4|   *   *   *   *   *   *   *   *   *   *   *
          3|   *   *   *   *   *   *   *   *   *   *   *
          2|   *   *   *   *   *   *   *   *   *   *   *
          1|   *   *   *   *   *   *   *   *   *   *   *
            --------------------------------------------
Word Length:   1   2   3   4   5   6   7   8   9  10  11
Frequency:     7  49  56  56  37  18  23   6  11   4   4

Solution by kreativitetNO (Category 0)

You could frown upon me using the MIN(x, y) macro since it hasn't been covered in the book yet, but it would be trivial to replace it with a function, if/else or the same ternary expression that's used to define the macro. I just think it looks tidier this way.

/* Configurable with "fancy" output */
#include <stdio.h>

#define MINLEN 2 // shortest word to count
#define MAXLEN 10 // longest word to count
#define MAXCOUNT 20 // graph cut-off
#define MIN(x, y) (x > y) ? y : x
/*
Replace macro with this function if you don't want to use it:
int min(int x, int y) {
    if (x > y)
        return y;
    else
        return x;
}
*/

int main(void) {
    /* couple of counters */
    int i, j;
    
    /* character input */
    int c;
    
    /* current word length and stored word lengths */
    int cwl, wl[MAXLEN-MINLEN+1];
    
    cwl = 0;
    for (i = 0; i <= MAXLEN-MINLEN; ++i)
        wl[i] = 0;

    while ((c = getchar()) != EOF) {
        if (c != ' ' && c != '\t' && c != '\n') {
            cwl++;
        }
        else if (cwl > 0) {
            if (cwl >= MINLEN)
                wl[MIN(cwl-MINLEN, MAXLEN-MINLEN)]++;
            cwl = 0;
        }
    }

    if (cwl >= MINLEN)
        wl[MIN(cwl-MINLEN, MAXLEN-MINLEN)]++;

    for (i = MAXCOUNT; i > 0; --i) {
        for (j = 0; j <= MAXLEN-MINLEN; ++j) {
            if (wl[j] > i && i == MAXCOUNT)
                putchar('+');
            else if (wl[j] >= i)
                putchar('\260' + (MIN(wl[j]-i, 2)));
            else
                putchar(' ');
            printf("    ");
        }
        putchar('\n');
    }
    for (j = 0; j <= MAXLEN-MINLEN; j++) {
        printf("%s%-3d", j == MAXLEN-MINLEN ? ">=" : "  ", j+MINLEN);
    }
    printf("+\n");
    return 0;
}

Output based on source code (HTML pre doesn't do it justice):

+

▓
▓         ░                             ░
▓         ▒                             ▒
▓         ▓                             ▓
▓    ░    ▓                             ▓
▓    ▒    ▓                             ▓
▓    ▓    ▓                             ▓
▓    ▓    ▓                             ▓
▓    ▓    ▓                             ▓
▓    ▓    ▓         ░    ░              ▓
▓    ▓    ▓         ▒    ▒              ▓
▓    ▓    ▓    ░    ▓    ▓              ▓
▓    ▓    ▓    ▒    ▓    ▓              ▓
▓    ▓    ▓    ▓    ▓    ▓              ▓
▓    ▓    ▓    ▓    ▓    ▓    ░    ░    ▓
▓    ▓    ▓    ▓    ▓    ▓    ▒    ▒    ▓
▓    ▓    ▓    ▓    ▓    ▓    ▓    ▓    ▓
▓    ▓    ▓    ▓    ▓    ▓    ▓    ▓    ▓
▓    ▓    ▓    ▓    ▓    ▓    ▓    ▓    ▓
2    3    4    5    6    7    8    9    >=10


Solution by scopych

#include <stdio.h>

/* Program prints a histogram of the lengths of
   words in its input. A horizontal oriented bars.
   Words grater 20 charecters colects in 21-st bar */

main()
{
        int             i        , count, c;
        int             nchars    [21];

        count = 0;
        for (i = 1; i <= 21; ++i)
                nchars[i] = 0;

        while ((c = getchar()) != EOF) {
                if (c != ' ' && c != '\n' && c != '\t') {
                        ++count;
                } else if (count > 0 && count <= 20) {
                        ++nchars[count];
                        count = 0;
                } else if (count > 20) {
                        ++nchars[21];
                        count = 0;
                }
        }
        printf("number of chars in words \n");
        for (i = 1; i < 22; ++i) {
                printf("%2d %4d ", i, nchars[i]);
                while (nchars[i] > 0) {
                        printf("|");
                        --nchars[i];
                }
                printf("\n");
        }
}

Output

number of chars in words
 1   36 ||||||||||||||||||||||||||||||||||||
 2   34 ||||||||||||||||||||||||||||||||||
 3   13 |||||||||||||
 4    6 ||||||
 5   15 |||||||||||||||
 6    8 ||||||||
 7    3 |||
 8    3 |||
 9    3 |||
10    4 ||||
11    2 ||
12    2 ||
13    2 ||
14    1 |
15    0
16    1 |
17    0
18    0
19    0
20    0
21    0

Solution by CakeOfTrust

This solution produces a big vertical histogram. It X-axis is drawn up to the biggest word encountered. Its Y-axis is for %, not for the actual amount of words.

#include <stdio.h>

#define HIST_OX_LIM 29
#define HIST_OY_LIM 100
#define SIZE_V 2
#define SIZE_H 3

int main(void)
{
  int c, oy, hist[HIST_OX_LIM], ox, wL, size_h, size_v;

  for (ox = 0; ox < HIST_OX_LIM; ++ox)
      hist[ox] = 0;

  for (c = getchar(); c != EOF;)
      {
          if  (c == '\n' || c == ' ' || c == '\t')
              c = getchar();

          else
              {
                  for (wL = 0; c != EOF && c != ' ' && c != '\t' && c != '\n'; wL++)
                      c = getchar();

                  ++hist[wL - 1];

                  /* There was a way to count words without wL variable but it would backfire
                      later because one would still need a variable to produce scalable output.

                      for (ox = 0; c != EOF && c != ' ' && c != '\t' && c != '\n'; ++ox)
                          {
                              ++hist[ox];
                              c = getchar();

                              if (ox > 0)
                                  --hist[ox - 1];
                          }

                  */
              }
      }

  putchar('\n');

  wL = 0;

  for (c = 0; ox > 0; --ox)
          c = c + hist[ox - 1];

  for (ox = HIST_OX_LIM; ox > 0; --ox)
      if (hist[ox -1] != 0)
          {
              wL = ox;
              ox = 0;
          }

  for (oy = HIST_OY_LIM; oy > 0; --oy)
      {
          printf("%3d|  ", oy);

          for (size_v = SIZE_V; size_v > 0; --size_v)
          {
              if (size_v < SIZE_V)
                  {
                      putchar('\n');
                      putchar(' ');
                      putchar(' ');
                      putchar(' ');
                      putchar('|');
                      putchar(' ');
                      putchar(' ');
                  }

              for (ox = 0; ox < wL; ++ox)
                {
                    for (size_h = SIZE_H; size_h > 0; --size_h)
                        if ((hist[ox]*1.0*HIST_OY_LIM/c) >= oy*1.0)
                            putchar('#');

                        else
                            putchar(' ');

                    putchar(' ');
                }
          }

          putchar('\n');
      }

  putchar(' ');
  putchar(' ');
  putchar(' ');
  putchar('|');

  for(; ox + 1 > 0; --ox)
      for (size_h = SIZE_H + 1; size_h > 0; --size_h)
          putchar('_');

  putchar('\n' );

  printf("      ");

  for (; ox + 1 < wL; ++ox)
      printf("%2d  ", (ox + 2));

  putchar('\n');

  return 0;
}

Output

100|                                              
   |                                              
 99|                                              
   |                                              
 98|                                              
   |                                              
 97|                                              
   |                                              
 96|                                              
   |                                              
 95|                                              
   |                                              
 94|                                              
   |                                              
 93|                                              
   |                                              
 92|                                              
   |                                              
 91|                                              
   |                                              
 90|                                              
   |                                              
 89|                                              
   |                                              
 88|                                              
   |                                              
 87|                                              
   |                                              
 86|                                              
   |                                              
 85|                                              
   |                                              
 84|                                              
   |                                              
 83|                                              
   |                                              
 82|                                              
   |                                              
 81|                                              
   |                                              
 80|                                              
   |                                              
 79|                                              
   |                                              
 78|                                              
   |                                              
 77|                                              
   |                                              
 76|                                              
   |                                              
 75|                                              
   |                                              
 74|                                              
   |                                              
 73|                                              
   |                                              
 72|                                              
   |                                              
 71|                                              
   |                                              
 70|                                              
   |                                              
 69|                                              
   |                                              
 68|                                              
   |                                              
 67|                                              
   |                                              
 66|                                              
   |                                              
 65|                                              
   |                                              
 64|                                              
   |                                              
 63|                                              
   |                                              
 62|                                              
   |                                              
 61|                                              
   |                                              
 60|                                              
   |                                              
 59|                                              
   |                                              
 58|                                              
   |                                              
 57|                                              
   |                                              
 56|                                              
   |                                              
 55|                                              
   |                                              
 54|                                              
   |                                              
 53|                                              
   |                                              
 52|                                              
   |                                              
 51|                                              
   |                                              
 50|                                              
   |                                              
 49|                                              
   |                                              
 48|                                              
   |                                              
 47|                                              
   |                                              
 46|                                              
   |                                              
 45|                                              
   |                                              
 44|                                              
   |                                              
 43|                                              
   |                                              
 42|                                              
   |                                              
 41|                                              
   |                                              
 40|                                              
   |                                              
 39|                                              
   |                                              
 38|                                              
   |                                              
 37|                                              
   |                                              
 36|                                              
   |                                              
 35|                                              
   |                                              
 34|                                              
   |                                              
 33|  ###                                         
   |  ###                                         
 32|  ###                                         
   |  ###                                         
 31|  ###                                         
   |  ###                                         
 30|  ###                                         
   |  ###                                         
 29|  ###                                         
   |  ###                                         
 28|  ###                                         
   |  ###                                         
 27|  ###                                         
   |  ###                                         
 26|  ###                                         
   |  ###                                         
 25|  ###                                         
   |  ###                                         
 24|  ###                                         
   |  ###                                         
 23|  ###                                         
   |  ###                                         
 22|  ###                                         
   |  ###                                         
 21|  ###                                         
   |  ###                                         
 20|  ###                                         
   |  ###                                         
 19|  ###                                         
   |  ###                                         
 18|  ###                                         
   |  ###                                         
 17|  ###                                         
   |  ###                                         
 16|  ### ### ###                                 
   |  ### ### ###                                 
 15|  ### ### ###                                 
   |  ### ### ###                                 
 14|  ### ### ###                                 
   |  ### ### ###                                 
 13|  ### ### ###                                 
   |  ### ### ###                                 
 12|  ### ### ###                                 
   |  ### ### ###                                 
 11|  ### ### ###                                 
   |  ### ### ###                                 
 10|  ### ### ###                                 
   |  ### ### ###                                 
  9|  ### ### ###                                 
   |  ### ### ###                                 
  8|  ### ### ###             ###     ### ### ### 
   |  ### ### ###             ###     ### ### ### 
  7|  ### ### ###             ###     ### ### ### 
   |  ### ### ###             ###     ### ### ### 
  6|  ### ### ###             ###     ### ### ### 
   |  ### ### ###             ###     ### ### ### 
  5|  ### ### ###             ###     ### ### ### 
   |  ### ### ###             ###     ### ### ### 
  4|  ### ### ###             ###     ### ### ### 
   |  ### ### ###             ###     ### ### ### 
  3|  ### ### ###             ###     ### ### ### 
   |  ### ### ###             ###     ### ### ### 
  2|  ### ### ###             ###     ### ### ### 
   |  ### ### ###             ###     ### ### ### 
  1|  ### ### ###             ###     ### ### ### 
   |  ### ### ###             ###     ### ### ### 
   |________________________________________________
       1   2   3   4   5   6   7   8   9  10  11  

Solution by [Octavian]

This is a simple solution that shows the frequency of words by number of characters. It assumes that the number of characters in one word does not exceed 10 characters, but it can be changed to larger values.

#include <stdio.h>

int main(void)
{
        int c, i, j, wcount;
        int wlengths[10];

        wcount = 0;

        for (i = 0; i <= 9; ++i)
                wlengths[i] = 0;

        while ((c = getchar()) != EOF)
                if (c != ' ' && c != '\n' && c != '\t')
                        ++wcount;
                else
                {
                        ++wlengths[wcount];
                        wcount = 0;
                }

        printf("\n");
        for (i = 0; i <= 9; ++i)
        {
                printf("%d", i);
                for (j = 1; j <= wlengths[i]; ++j)
                        printf("|");
                printf("\n");
        }

Output

0|
1|||
2||||
3||||
4|||||
5||
6||
7|
8|
9|

Solution by sl4y3r 0wn3r

#include <stdio.h>

/* *
 * Exercise 1-13. Write a program to print a histogram of the lengths of words in
 * its input. It is easy to draw the histogram with the bars horizontal; a vertical
 * orientation is more challenging.
 * ----
 * ANSI C K&R - CHARACTER INPUT AND OUTPUT: PAGE 15 
 * The quantities IS_LOWER, IS_UPPER, IS_ALPHA, MAXLEN, OUT and IN (macros)
 * are symbolic constant, not variables, so they do not appear in declarations.
 * Symbolic constant names are conventionally written in upper case so they can
 * be readily distinguished from lower case variable name.
 * */
#define IS_UPPER(N) ((N) >= 'A' && (N) <= 'Z')   /* 'A'==65 && 'Z'==90 */
#define IS_LOWER(N) ((N) >= 'a' && (N) <= 'z')   /* 'a'==97 && 'z'==122 */
#define IS_ALPHA(N) (IS_LOWER(N) || IS_UPPER(N)) /* [A-Za-z] x*/
#define MAXLEN  17 /* buffer limit length */
#define OUT 0 /* outside the word */
#define IN  1 /* inside the word */

int main(void)
{
  int c = EOF,
  /* word buffer & word length */
      wbuf[MAXLEN],
      wlen = 0;
  int state = OUT,
  /* X and Y axis */
      x = 0, /* horizontal histogram */
      y = 0; /* vertical histogram */

  /* fill word buffer with zero */
  for (int i = 0; i <= MAXLEN; i++)
    wbuf[i] = 0;

  /* word count while giving data */
  while((c = getchar()) != EOF) {
    if (IS_ALPHA(c) && wlen < MAXLEN) {
      state = IN;
      ++wlen;
    } else if (wlen > 0 && wlen < MAXLEN) {
      state = OUT;
      ++wbuf[wlen];
      wlen = 0;
    }
  }
  ++wbuf[wlen]; /* return value without EOF */

  /* give to 'x' and 'y' the length of longest word */
  for (int i = 1; i < MAXLEN; i++) {
    if (wbuf[i] && i > x)
      x = i;
    if (wbuf[i] > y)
      y = wbuf[i];
  }

  /* horizontal histogram */
  puts("\nHORIZONTAL HISTOGRAM");
  for (int i = 1; i <= x; i++) {
    printf("%2d | ", i);
    for (int j = 0; j < wbuf[i]; j++)
      printf("* ");
  
    putchar('\n');
  }

  /* *
   * vertical histogram 
   * building the 'y' axis
   * */
  puts("\nVERTICAL HISTOGRAM");
  for (int i = y; i > 0; i--) {
    printf("%2d |", i);
    for(int j = 1; j <= x; j++) {
      if (wbuf[j] < i)
        printf("      ");
      else
        printf(" *    ");
    }
    putchar('\n');
  }
  if (wlen < MAXLEN)
    printf("   +--");

  for (int i = 1; i < x; i++)
    printf("------");
  putchar('\n');

  for (int i = 1; i <= x; i++)
    printf("%6d", i);
  putchar('\n');

  return 0;
}

Output:

HORIZONTAL HISTOGRAM
 1 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 2 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 3 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 4 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 5 | * * * * * * * * * * * * * * * * * * * * * * * * * * 
 6 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
 7 | * * * * * * * * * * * * * 
 8 | * * * * * * * * * * 
 9 | * * * * * * * * * * * 
10 | * * * * 
11 | * * * 
12 | * 
13 | * 
14 | * 

VERTICAL HISTOGRAM
89 | *                                                                                  
88 | *                                                                                  
87 | *                                                                                  
86 | *                                                                                  
85 | *                                                                                  
84 | *                                                                                  
83 | *                                                                                  
82 | *                                                                                  
81 | *                                                                                  
80 | *                                                                                  
79 | *                                                                                  
78 | *                                                                                  
77 | *                                                                                  
76 | *                                                                                  
75 | *                                                                                  
74 | *                                                                                  
73 | *                                                                                  
72 | *                                                                                  
71 | *                                                                                  
70 | *                                                                                  
69 | *                                                                                  
68 | *                                                                                  
67 | *                                                                                  
66 | *                                                                                  
65 | *                                                                                  
64 | *                                                                                  
63 | *                                                                                  
62 | *                                                                                  
61 | *                                                                                  
60 | *                                                                                  
59 | *                                                                                  
58 | *                                                                                  
57 | *                                                                                  
56 | *                                                                                  
55 | *                                                                                  
54 | *                                                                                  
53 | *                                                                                  
52 | *                                                                                  
51 | *                                                                                  
50 | *                 *                                                                
49 | *                 *                                                                
48 | *                 *                                                                
47 | *                 *                                                                
46 | *                 *                                                                
45 | *                 *                                                                
44 | *           *     *                                                                
43 | *           *     *                                                                
42 | *           *     *                                                                
41 | *           *     *                                                                
40 | *           *     *                                                                
39 | *           *     *                                                                
38 | *           *     *                                                                
37 | *           *     *                                                                
36 | *           *     *                                                                
35 | *           *     *                                                                
34 | *     *     *     *           *                                                    
33 | *     *     *     *           *                                                    
32 | *     *     *     *           *                                                    
31 | *     *     *     *           *                                                    
30 | *     *     *     *           *                                                    
29 | *     *     *     *           *                                                    
28 | *     *     *     *           *                                                    
27 | *     *     *     *           *                                                    
26 | *     *     *     *     *     *                                                    
25 | *     *     *     *     *     *                                                    
24 | *     *     *     *     *     *                                                    
23 | *     *     *     *     *     *                                                    
22 | *     *     *     *     *     *                                                    
21 | *     *     *     *     *     *                                                    
20 | *     *     *     *     *     *                                                    
19 | *     *     *     *     *     *                                                    
18 | *     *     *     *     *     *                                                    
17 | *     *     *     *     *     *                                                    
16 | *     *     *     *     *     *                                                    
15 | *     *     *     *     *     *                                                    
14 | *     *     *     *     *     *                                                    
13 | *     *     *     *     *     *     *                                              
12 | *     *     *     *     *     *     *                                              
11 | *     *     *     *     *     *     *           *                                  
10 | *     *     *     *     *     *     *     *     *                                  
 9 | *     *     *     *     *     *     *     *     *                                  
 8 | *     *     *     *     *     *     *     *     *                                  
 7 | *     *     *     *     *     *     *     *     *                                  
 6 | *     *     *     *     *     *     *     *     *                                  
 5 | *     *     *     *     *     *     *     *     *                                  
 4 | *     *     *     *     *     *     *     *     *     *                            
 3 | *     *     *     *     *     *     *     *     *     *     *                      
 2 | *     *     *     *     *     *     *     *     *     *     *                      
 1 | *     *     *     *     *     *     *     *     *     *     *     *     *     *    
   +--------------------------------------------------------------------------------
     1     2     3     4     5     6     7     8     9    10    11    12    13    14

Solution by Marvelcoder

* HorizontalHistogram.c
*
*  Created on: 18-Jul-2020
*      Author: Marvelcoder
*
#include<stdio.h>

#define ARRAY_LENGTH 15

int main(){

	int ch,array[ARRAY_LENGTH]={0},barray[ARRAY_LENGTH]={0},index,count,temp,visited,fqncy;

	index=count=temp=visited=fqncy=0;

	while((ch=getchar())!=EOF){
		if(ch==' '||ch=='\t'||ch=='\n'){
			if(count!=0){
				array[index]=count;
				++index;
				count=0;
			}
		}else ++count;
	}

	//Prints the length of each word
	for(int i=0;i<ARRAY_LENGTH;i++){
		printf("%d ",array[i]);
	}

	printf("\n");

	/*
	 * This block of code calculates the frequency of each element from one array
	 * and sets it in corresponding location in another array.
	 *
	 * For ex: 5 is at 0th index and it's frequency is 3
	 * so 3 is set at 0th index in another array.
	 */
	for(int i=0;i<ARRAY_LENGTH;i++){
		temp=i;
		while(temp>=0){
			if(array[i]==array[--temp]){
				visited=1;
				break;
			}
		}

		if(visited==0){
			for(int j=0;j<ARRAY_LENGTH;j++){
				if(array[i]==array[j]){
					++fqncy;
				}
			}
		}

		if(visited==0){
			barray[i] = fqncy;
			fqncy=0;
		}
		visited=0;
	}

	//Prints the frequency of each word
	for(int i=0;i<ARRAY_LENGTH;i++){
		printf("%d ",barray[i]);
	}
	printf("\n---------------HORIZONTAL HISTOGRAM STARTS--------------------\n");

	for(int i=1;i<=11;i++){
		if(i==11){printf(">10 ");}
		else if(i==10){printf("%d  ",i);}
		else{printf("%d   ",i);}
		for(int j=0;j<ARRAY_LENGTH;j++){
			if(i<11 && i==array[j]){
				printf("X ");
			}else if(i>10 && array[j]>10){
				printf("X ");
			}
		}
		printf("\n\n");
	}

	printf("----------------HORIZONTAL HISTOGRAM ENDS------------------\n");

return 0;

}


Output

---------------HORIZONTAL HISTOGRAM STARTS--------------------
1   X X 

2   X X X X 

3   X 

4   X X X 

5   X X 

6   X 

7   

8   

9   

10  X 

>10 X 

----------------HORIZONTAL HISTOGRAM ENDS------------------


* VerticalHistogram.c
*
*  Created on: 20-Jul-2020
*      Author: Marvelcoder
*
#include<stdio.h>

#define WORD_LENGTH 15

int main(){

	int character,varray[WORD_LENGTH]={0},i,count,max,temp,visited,barray[WORD_LENGTH]={0},fqncy,found;

	i=count=found=max=fqncy=temp=visited=0;

	while((character=getchar())!=EOF){
		if(character!=' '&&character!='\n'&&character!='\t'){
			++count;
		}else{
			if(count!=0){
				varray[i]=count;
				i++;
				count=0;
			}
		}
	}

	//Prints the length of each word
	for(i=0;i<WORD_LENGTH;i++){
		printf("%d ",varray[i]);
	}

	printf("\n");

	/*
	 * This block of code calculates the frequency of each element from one array
	 * and sets it in corresponding location in another array.
	 *
	 * For ex: 5 is at 0th index and it's frequency is 3
	 * so 3 is set at 0th index in another array.
	 */
	for(int i=0;i<WORD_LENGTH;i++){
		temp=i;
		while(temp>=0){
			if(varray[i]==varray[--temp]){
				visited=1;
				break;
			}
		}

		if(visited==0){
			for(int j=0;j<WORD_LENGTH;j++){
				if(varray[i]==varray[j]){
					++fqncy;
				}
			}
		}

		if(visited==0){
			barray[i] = fqncy;
			fqncy=0;
		}
		visited=0;
	}

	//Prints the frequency of each word
	for(i=0;i<WORD_LENGTH;i++){
		printf("%d ",barray[i]);
	}



	//Finds the maximum frequency which will be on Y-axis
	for(i=0;i<WORD_LENGTH;i++){
		if(barray[i] > max){
			max = barray[i];
		}
	}

	printf("\n---------------VERTICAL HISTOGRAM STARTS--------------------\n");



	for(i=max;i>0;i--){
		printf("%d",i);

		for(int j=1;j<=11;j++){
			found=1;
			for(int k=0;k<WORD_LENGTH;k++){
				if(j==varray[k] && j<11){
					if(barray[k]==i){
						printf(" X ");
						--barray[k];
						found=0;
					}
				}else if(j>10 && barray[k]==i){
					printf("   X");
					found=0;
				}
			}
			if(found==1){
				printf("   ");
			}
		}
		printf("\n\n");
	}

	printf(" ");

		for(i=1;i<=11;i++){
			if(i==11){
				printf(">10");
			}else{
				printf(" %d ",i);
			}
		}
		printf("\n---------------VERTICAL HISTOGRAM ENDS--------------------\n");


	return 0;
}


Output

---------------VERTICAL HISTOGRAM STARTS--------------------
6          X                      

5          X                      

4          X                      

3    X     X                      

2    X     X                      X

1 X  X     X  X  X     X          

  1  2  3  4  5  6  7  8  9  10 >10
---------------VERTICAL HISTOGRAM ENDS--------------------
Personal tools