spelling checker

This is a discussion on spelling checker within the C Programming forums, part of the General Programming Boards category; hi, Im making a spelling checker for a new task. Code: # include <stdio.h> # include <string.h> # include <ctype.h> ...

  1. #1
    Registered User
    Join Date
    Sep 2009
    Location
    Netherlands
    Posts
    17

    spelling checker

    hi,

    Im making a spelling checker for a new task.

    Code:
    # include <stdio.h>
    # include <string.h>
    # include <ctype.h>
    
    # define MAXLINE 256
    
    void spatie(char * entered_line, int length);
    void hoofdletter(char * entered_line);
    void spelling(char * entered_line, int length);
    void dot(char * entered_line, int lenght);
    
    void main (void)
    {
    	char a;
    	char entered_line[MAXLINE + 1];
    	int length = 0;
    
    	printf("--- Welcome to Tom's amazing spelling corrector ---\n\n");
    	printf(" Type 'end' when finished.\n\n");
    	
    	while (1) 
    	{
    	printf("Type line:");
    		while ( ( a = getchar()) != '\n' && length < MAXLINE)
    		{
    			entered_line[length++] = a;
    		}
    		entered_line [length] = '\0';
    
    
    
    			if (strcmp(entered_line, "end") == 0)
    			{
    				printf(" Have a nice day!\n");
    				break;
    			}
    			else
    			{
    				spatie(entered_line, length);
                                    spelling(entered_line, length);
    				//spellingfunctie
    				// dubbele woorden functie
    				length = strlen(entered_line);
    				hoofdletter(entered_line);
    				dot(entered_line, length);
    				
    				
    				
    				
    				// zelf verzinnen functie
    				printf("Corrected:%s\n\n", entered_line);
    			}
    
    	}
    
    
    }
    
    
    void hoofdletter(char * entered_line)
    {
    	entered_line [0] = toupper(entered_line[0]);
    }
    
    void spatie(char * entered_line, int length)
    {
    	int i=0;
    	int j=0;
    	int z=0;
    	
    	if (isspace(entered_line[0])) //spatie aan begin
    	{
    		for(i;i<length;i++)
    		entered_line [i] = entered_line[i+1];
    	}
    
    	
    	while (j<=length)   //meerdere spaties
    	{
    		if (isspace(entered_line[j]) && isspace(entered_line[j+1]))
    		{
    			for(j+1;j<=length;j++)
    			{
    			entered_line[j+1] = entered_line [j+2];
    			}
    		}
    		j++;
    	}
    	
    	for (z=0;z<l=ength;z++)   //spaties voor leesteken
    	{
    		if (isspace(entered_line[z]) && ispunct(entered_line[z+1]))
    		{
    			for(z+1;z<=length;z++)
    			{
    			entered_line[z+1] = entered_line [z+2];
    			}
    		}
    	}
    	
    
    }
    
    void dot(char * entered_line, int length)
    {
    	if (ispunct(entered_line [length-1]))
    	{
    	}
    	else
    	{
    		entered_line [length] = '.';
    		entered_line [length+1] = '\0';
    	}
    }
    
    void spelling (char* entered_line, int length)
    {
    	int i=0;
    	
    
    	for(i;i<length;i++)
    	{
    		for(i=0; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		entered_line[i] = '\0';
    		if(strcmpi(entered_line,"teh") == 0)
    		{
    			entered_line = "the";
    		}
    
    	}
    	
    
    }
    It should do several things but 2 things are not working. It should remove double spaces (function is called spatie). But the problem is it only removes 1 double space and stops after that. How can this be solved?
    Second problem is that i want to correct teh into the. But this function doenst work either?

    Thanks for your help,
    tom
    Last edited by Tom.b; 10-12-2009 at 01:48 PM.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Wrap the whole thing in another loop. Check until you hit the end of the string.
    Code:
    while not at end of string
        check for double space
            squish string back to this point
    For your second option, you want to search until you find 'teh', then swap the positions of the h and the e.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Sep 2009
    Location
    Netherlands
    Posts
    17
    i already have this see the while loop with the j<=length. Or do you mean something different? For the second problem i search for end of a word and then compare it to the string "teh". And do this for the entire string length. But there is something wrong???

  4. #4
    Registered User
    Join Date
    Sep 2009
    Location
    Netherlands
    Posts
    17
    i have this code right now:
    Code:
    // File: P5.cpp
    // Tom Bruls
    // 0719757
    
    # include <stdio.h>
    # include <string.h>
    # include <ctype.h>
    
    # define MAXLINE 256
    
    void spatie(char * entered_line, int length);
    void hoofdletter(char * entered_line);
    void spelling(char * entered_line, int length);
    void dot(char * entered_line, int length);
    void tom(char * entered_line, int length);
    void dubbelewoorden(char * entered_line, int length);
    
    void main (void)
    {
    	char a;
    	char entered_line[MAXLINE + 1];
    	int length = 0;
    
    	printf("--- Welcome to Tom's amazing spelling corrector ---\n\n");
    	printf(" Type 'end' when finished.\n\n");
    	
    	while (1) 
    	{
    	printf("Type line:");
    		length = 0;
    		while ( ( a = getchar()) != '\n' && length < MAXLINE)
    		{
    			entered_line[length++] = a;
    		}
    		entered_line [length] = '\0';
    
    
    
    			if (strcmp(entered_line, "end") == 0)
    			{
    				printf(" Have a nice day!\n");
    				break;
    			}
    			else
    			{
    				spatie(entered_line, length);
    				spelling(entered_line, length);
    				dubbelewoorden(entered_line, length);
    				tom(entered_line, length);
    				length = strlen(entered_line);
    				hoofdletter(entered_line);
    				dot(entered_line, length);
    				
    				
    				printf("Corrected:%s\n\n", entered_line);
    			}
    
    	}
    
    
    }
    
    
    void hoofdletter(char * entered_line)
    {
    	entered_line [0] = toupper(entered_line[0]);
    }
    
    void spatie(char * entered_line, int length)
    {
    	int i=0;
    	int j=0;
    	int z=0;
    	int u=0;
    	int k=0;
    	
    	if (isspace(entered_line[0])) //spatie aan begin
    	{
    		for(i=0;i<length;i++)
    		{
    			entered_line [i] = entered_line[i+1];
    		}
    		entered_line [length] = '\0';
    	}
    
    	
    	while (j<length)   //meerdere spaties
    	{
    		if (isspace(entered_line[j]) && isspace(entered_line[j+1]))
    		{
    			u = j;
    			for(u+1;u<=length;u++)
    			{
    			entered_line[u+1] = entered_line [u+2];
    			}
    			length = length -1;
    		}
    		else
    		{
    			j++;
    		}
    		entered_line [length] = '\0';
    	}
    	
    	while (z<length)   //spaties voor leesteken
    	{
    		if (isspace(entered_line[z]) && ispunct(entered_line[z+1]))
    		{
    			k = z;
    			for(k+1;k<=length;k++)
    			{
    			entered_line[k] = entered_line [k+1];
    			}
    			length = length -1;
    		}
    		else
    		{
    			z++;
    		}
    		entered_line [length] = '\0';
    	}
    	
    
    }
    
    void dot(char * entered_line, int length)
    {
    	if (ispunct(entered_line [length-1]))
    	{
    	}
    	else
    	{
    		entered_line [length] = '.';
    		entered_line [length+1] = '\0';
    	}
    }
    
    void spelling (char* entered_line, int length)
    {
    	int i=0;
    	int u=0;
    	
    	while(u<=length)
    	{
    		for(i=u; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		{
    			;
    		}
    		entered_line[i] = '\0';
    
    		if(strcmpi(entered_line,"teh") == 0)
    		{
    			strcpy(entered_line, "the");
    		}
    		if(strcmpi(entered_line, "eb") == 0)
    		{
    			strcpy(entered_line, "be");
    		}
    		if(strcmpi(entered_line, "si") == 0)
    		{
    			strcpy(entered_line, "is");
    		}
    		if(strcmpi(entered_line, "adn") == 0)
    		{
    			strcpy(entered_line, "and");
    		}
            
    		entered_line[i] = ' ';
    		u=i;
    	}
    		
    		
    		
    
    
    	
    	
    
    }
    
    void tom (char* entered_line, int length)
    {
    	int i=0;
    	int u=0;
    	
    
    	for(i;i<length;i++)
    	{
    		for(i; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		{
    			;
    		}
    		entered_line[i] = '\0';
    
    		if(strcmpi(entered_line,"tom") == 0)
    		{
    			strcpy(entered_line, "TOM");
    		}
    	}
    }
    
    void dubbelewoorden (char* entered_line, int length)
    {
    }
    Im having trouble with the spelling function. I can make it the way it only corrects the first word, but i want it to correct the entire line. I coded it the way above but it doesnt work. I hope you can help me!

  5. #5
    Registered User
    Join Date
    Mar 2009
    Posts
    48
    What exactly were you trying to do here in for loops:
    Code:
    for(u+1;u<=length;u++).
    .
    .
    for(k+1;k<=length;k++)
    You will also possibly go out of bounds with these statements :
    Code:
    entered_line [length] = '\0';
    for(u+1;u<=length;u++)
    {
         entered_line[u+1] = entered_line [u+2];
    			}
         length = length -1;
    If I understand your function
    Code:
    void spatie(char * entered_line, int length)
    /* First you check whether the first letter is a space*/
         if (isspace(entered_line[0])) //spatie aan begin
    	{
    		for(i=0;i< length - 1; i++) /*Equivalent to a shift left*/
    		{
    			entered_line [i] = entered_line[i+1];
    		}
    		entered_line [length - 1] = '\0';/*This is not required as the null terminator
                                                                                       will be copied to length - 1*/
    	}
    Code:
    /*Now for 2 spaces, let's make a for loop*/
        for (j = 1; j < length; j++) {
             if (isspace(a[j - 1]) && isspace(a[j])) {
                  for (u = j; u < length - 1; u++)
                        entered_line[u] = entered_line[u + 1]; /*If you need one space*/
             }
        }
    If the user can give a double space, the user might as well give any number of spaces, in that case
    neither the double space would work nor checking whether the first character is a space will work .
    Last edited by zalezog; 11-10-2009 at 11:41 AM.

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,308
    It's "int main" in C and C++, never "void main".

    For a better spelling suggestor/corrector etc, get yourself a plaintext dictionary file, and try implementing the algorithm from here:
    Damerau–Levenshtein distance - Wikipedia, the free encyclopedia
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    Registered User
    Join Date
    Sep 2009
    Location
    Netherlands
    Posts
    17
    Code:
    // File: P5.cpp
    // Tom Bruls
    // 0719757
    
    # include <stdio.h>
    # include <string.h>
    # include <ctype.h>
    
    # define MAXLINE 256
    
    void spatie(char * entered_line, int length);
    void hoofdletter(char * entered_line);
    void spelling(char * entered_line, int length);
    void dot(char * entered_line, int length);
    void tom(char * entered_line, int length);
    void dubbelewoorden(char * entered_line, int length);
    
    void main (void)
    {
    	char a;
    	char entered_line[MAXLINE + 1];
    	int length = 0;
    
    	printf("--- Welcome to Tom's amazing spelling corrector ---\n\n");
    	printf("Type 'end' when finished.\n\n");
    	
    	while (1) 
    	{
    	printf("Type line:");
    		length = 0;
    		while ( ( a = getchar()) != '\n' && length < MAXLINE)
    		{
    			entered_line[length++] = a;
    		}
    		entered_line [length] = '\0';
    
    
    
    			if (strcmp(entered_line, "end") == 0)
    			{
    				printf(" Have a nice day!\n");
    				break;
    			}
    			else
    			{
    				spatie(entered_line, length);
    				tom(entered_line, length);
    				spelling(entered_line, length);
    				dubbelewoorden(entered_line, length);
    				length = strlen(entered_line);
    				hoofdletter(entered_line);
    				dot(entered_line, length);
    				
    				
    				printf("Corrected:%s\n\n", entered_line);
    			}
    
    	}
    
    
    }
    
    
    void hoofdletter(char * entered_line)
    {
    	entered_line [0] = toupper(entered_line[0]);
    }
    
    void spatie(char * entered_line, int length)
    {
    	int i=0;
    	int j=0;
    	int z=0;
    	int u=0;
    	int k=0;
    	
    	while (j<length)   //meerdere spaties
    	{
    		if (isspace(entered_line[j]) && isspace(entered_line[j+1]))
    		{
    			u = j;
    			for(u+1;u<length;u++)
    			{
    			entered_line[u+1] = entered_line [u+2];
    			}
    			length = length -1;
    		}
    		else
    		{
    			j++;
    		}
    		entered_line [length] = '\0';
    	}
    	
    	if (isspace(entered_line[0])) //spatie aan begin
    	{
    		for(i=0;i<length;i++)
    		{
    			entered_line [i] = entered_line[i+1];
    		}
    		length = length-1;
    	}
    	
    	while (z<length)   //spaties voor leesteken
    	{
    		if (isspace(entered_line[z]) && ispunct(entered_line[z+1]))
    		{
    			k = z;
    			for(k+1;k<length;k++)
    			{
    			entered_line[k] = entered_line [k+1];
    			}
    			length = length -1;
    		}
    		else
    		{
    			z++;
    		}
    		entered_line [length] = '\0';
    	}
    	
    
    }
    
    void dot(char * entered_line, int length)
    {
    	if (ispunct(entered_line [length-1]))
    	{
    	}
    	else
    	{
    		entered_line [length] = '.';
    		entered_line [length+1] = '\0';
    	}
    }
    
    void spelling (char* entered_line, int length)
    {
    	int i=0;
    	int u=0;
    
    	while(u<=length)
    	{
    		for(i=u; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		{
    			;
    		}
    		entered_line[i] = '\0';
    
    		if(strcmpi(&entered_line[u], "teh") == 0)
    		{
    			strcpy(&entered_line[u], "the");
    		}
    		if(strcmpi(&entered_line[u], "adn") == 0)
    		{
    			strcpy(&entered_line[u], "and");
    		}
    		if(strcmpi(&entered_line[u], "si") == 0)
    		{
    			strcpy(&entered_line[u], "is");
    		}
    		if(strcmpi(&entered_line[u], "eb") == 0)
    		{
    			strcpy(&entered_line[u], "be");
    		}
    
    		entered_line[i] = ' ';
    		u=i+1;
    		
    	}
    	entered_line[length] = '\0';
    
    }
    
    void tom (char* entered_line, int length)
    {
    	int i=0;
    	int u=0;
    	
    
    	while(u<length)
    	{
    		for(i=u; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		{
    			;
    		}
    		entered_line[i] = '\0';
    
    		if(strcmpi(&entered_line[u],"tom") == 0)
    		{
    			strcpy(&entered_line[u], "TOM");
    		}
    		entered_line[i] = ' ';
    		u=i+1;
    	}
    	entered_line[length] = '\0';
    }
    
    void dubbelewoorden (char* entered_line, int length)
    {
    	int i=0;
    	int u=0;
    	int k=0;
    	int z=0;
    	int length2;
    
    	while(u<=length)
    	{
    		for(i=u; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		{
    			;
    		}
    		entered_line[i] = '\0';
    		
    
    		for(k=i+1; (entered_line[k] != '\0') && (!isspace(entered_line[k]));k++)
    		{
    			;
    		}
    		entered_line[k] = '\0';
    
    		if(strcmpi(&entered_line[u],&entered_line[i+1]) == 0)
    		{
    			length2= strlen(&entered_line[i]);
    				for(i+1;i<=length;i++)
    				{
    					entered_line[i+1] = entered_line [i+length2];
    				}		
    				length = length - length2;
    		}
    		entered_line[i]= ' ';
    		u=i+1;
    	}
    	entered_line[length]= '\0';
    
    		
    }
    Every function works now. But if you add the space function together with one that corrects wrong words i get this error:

    http://i37.tinypic.com/x6fz2s.jpg

  8. #8
    Registered User
    Join Date
    Sep 2009
    Location
    Netherlands
    Posts
    17
    All problems are solved except for 1, it is in the function dubbelewoorden. This function is supposed to delete double words. Problem is it works but only for 1 word. Example if i type:be be be aaaa. The answer will be: Be be aaaa. I need to finish it before deadline at noon saturday-sunday, please help me!

    Code:
    // File: P5.cpp
    // Tom Bruls
    // 0719757
    
    # include <stdio.h>
    # include <string.h>
    # include <ctype.h>
    
    # define MAXLINE 256
    
    void spatie(char * entered_line, int length);
    void hoofdletter(char * entered_line);
    void spelling(char * entered_line, int length3);
    void dot(char * entered_line, int length);
    void tom(char * entered_line, int length3);
    void dubbelewoorden(char * entered_line, int length3);
    
    void main (void)
    {
    	char a;
    	char entered_line[MAXLINE + 1];
    	int length = 0;
    	int length3;
    
    	printf("--- Welcome to Tom's amazing spelling corrector ---\n\n");
    	printf("Type 'end' when finished.\n\n");
    	
    	while (1) 
    	{
    	printf("Type line:");
    		length = 0;
    		while ( ( a = getchar()) != '\n' && length < MAXLINE)
    		{
    			entered_line[length++] = a;
    		}
    		entered_line [length] = '\0';
    
    
    
    			if (strcmp(entered_line, "end") == 0)
    			{
    				printf(" Have a nice day!\n");
    				break;
    			}
    			else
    			{
    				spatie(entered_line, length);
    				length3 = strlen(entered_line);
    				tom(entered_line, length3);
    				spelling(entered_line, length3);
    				dubbelewoorden(entered_line, length3);
    				length = strlen(entered_line);
    				hoofdletter(entered_line);
    				dot(entered_line, length);
    				
    				
    				printf("Corrected:%s\n\n", entered_line);
    			}
    
    	}
    
    
    }
    
    
    void hoofdletter(char * entered_line)
    {
    	entered_line [0] = toupper(entered_line[0]);
    }
    
    void spatie(char * entered_line, int length)
    {
    	int i=0;
    	int j=0;
    	int z=0;
    	int u=0;
    	int k=0;
    	
    	while (j<length-1)   //meerdere spaties
    	{
    		if (isspace(entered_line[j]) && isspace(entered_line[j+1]))
    		{
    			u = j;
    			for(u+1;u<length;u++)
    			{
    			entered_line[u] = entered_line [u+1];
    			}
    			length = length -1;
    		}
    		else
    		{
    			j++;
    		}
    	}
    	entered_line [length] = '\0';
    	
    	if (isspace(entered_line[0])) //spatie aan begin
    	{
    		for(i=0;i<length;i++)
    		{
    			entered_line [i] = entered_line[i+1];
    		}
    		length = length-1;
    	}
    	
    	while (z<length-1)   //spaties voor leesteken
    	{
    		if (isspace(entered_line[z]) && ispunct(entered_line[z+1]))
    		{
    			k = z;
    			for(k+1;k<length;k++)
    			{
    			entered_line[k] = entered_line [k+1];
    			}
    			length = length -1;
    		}
    		else
    		{
    			z++;
    		}
    		entered_line [length] = '\0';
    	}
    
    	if (isspace(entered_line[length-1]))
    	{
    		entered_line[length-1]= entered_line[length];
    	}
    	
    }
    
    void dot(char * entered_line, int length)
    {
    	if (ispunct(entered_line [length-1]))
    	{
    	}
    	else
    	{
    		entered_line [length] = '.';
    		entered_line [length+1] = '\0';
    	}
    }
    
    void spelling (char* entered_line, int length3)
    {
    	int i=0;
    	int u=0;
    
    	while(u<length3)
    	{
    		for(i=u; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		{
    			;
    		}
    		entered_line[i] = '\0';
    
    		if(strcmpi(&entered_line[u], "teh") == 0)
    		{
    			strcpy(&entered_line[u], "the");
    		}
    		if(strcmpi(&entered_line[u], "adn") == 0)
    		{
    			strcpy(&entered_line[u], "and");
    		}
    		if(strcmpi(&entered_line[u], "si") == 0)
    		{
    			strcpy(&entered_line[u], "is");
    		}
    		if(strcmpi(&entered_line[u], "eb") == 0)
    		{
    			strcpy(&entered_line[u], "be");
    		}
    
    		entered_line[i] = ' ';
    		u=i+1;
    		
    	}
    	entered_line[length3] = '\0';
    
    }
    
    void tom (char* entered_line, int length3)
    {
    	int i=0;
    	int u=0;
    	int a;
    	
    
    	while(u<length3)
    	{
    		for(i=u; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		{
    			;
    		}
    		
    		entered_line[i] = '\0';
    
    		if(strcmpi(&entered_line[u],"tom") == 0)
    		{
    			strcpy(&entered_line[u], "TOM");
    		}
    		
    		entered_line[i] = ' ';
    		u=i+1;
    	}
    	entered_line[length3] = '\0';
    }
    
    void dubbelewoorden (char* entered_line, int length3)
    {
    	int i=0;
    	int u=0;
    	int k=0;
    	int f;
    	int z=0;
    	int length2;
    
    	while(u<length3)//length3 is goed nagekeken met breakpoint
    	{
    		for(i=u; (entered_line[i] != '\0') && (!isspace(entered_line[i]));i++)
    		{
    			;
    		}
    		entered_line[i] = '\0'; // eerste woord afgekapt
    		f = i;
    				
    
    		for(k=i+1; (entered_line[k] != '\0') && (!isspace(entered_line[k]));k++)
    		{
    			;
    		}
    		entered_line[k] = '\0'; //tweede woord afgekapt
    
    		if(strcmpi(&entered_line[u],&entered_line[i+1]) == 0)
    		{
    			length2= strlen(&entered_line[u]); //lengte van woord + 0 karakter
    				for(u;u<length3 -1;u++)
    				{
    					entered_line[u] = entered_line [i+1]; //eerste letter van het tweede woord wordt naar de eerste letter van het eerste woord gekopieerd
    					i = i +1;
    				}		
    				
    				length3 = length3 - length2;				//nieuwe lengte van de string
    				length3 = length3 -1;
    		}
    		entered_line[f]= ' '; //wordt weer spatie
    		u=f+1; //naar volgende woord
    	}
    	entered_line[length3]= '\0';
    
    		
    }
    Last edited by Tom.b; 11-12-2009 at 01:20 PM.

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    OK, we have two words, and they're repeats. You're not worried about doubled words that are not repeats, right?

    Say we have "mein mein mein". Your programs compares the first mein with the second mein, and deletes the first mein?

    Does it then transfer the second mein, into the position that is ready to be compared with the third mein?

    You need that hand off, from the second word to the first word, (or deleting the second word, and moving on to the next word to compare it with the first mein, in it's turn).

    I'm crap with Dutch, but I don't see either of those being done in your code. Looks like after one comparison and deletion of a duplicate, the loop just goes on to the next words. If there has been a deleted duplicate word, the counter in the loop should be adjusted (decremented), or other variables adjusted, to set it up before the loop returns to the top again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. MISRA C Checker open source
    By huwan in forum Tech Board
    Replies: 8
    Last Post: 10-27-2009, 08:13 AM
  2. Spell Checker
    By DeepFyre in forum Tech Board
    Replies: 2
    Last Post: 02-11-2005, 11:17 AM
  3. Spell checker poem.
    By adrianxw in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 01-13-2004, 09:49 AM
  4. spell checker in c needs help
    By madmax in forum C Programming
    Replies: 3
    Last Post: 03-13-2003, 08:36 AM
  5. IDEA: Spelling Checker
    By fletch in forum Contests Board
    Replies: 14
    Last Post: 08-17-2002, 11:20 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21