Created
December 4, 2012 00:22
-
-
Save markandrus/4199333 to your computer and use it in GitHub Desktop.
telephone
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <assert.h> | |
| #include <stdbool.h> | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| static char keypad[10][5]={"0","1","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"}; | |
| static char options[10] ={ 1 , 1 , 3 , 3 , 3 , 3 , 3 , 4 , 3 , 4 }; | |
| static inline bool | |
| is_digit (char c) | |
| { | |
| return '0' <= c && c <= '9'; | |
| } | |
| static char * | |
| digits_to_letters (char *t) | |
| { | |
| assert (t!=NULL); | |
| unsigned i; | |
| for (i=0; t[i]!='\0'; i++) | |
| if (is_digit (t[i])) | |
| t[i]=keypad[t[i]-'0'][0]; | |
| return t; | |
| } | |
| static bool | |
| next_letter (char *t, unsigned i) | |
| { | |
| switch (t[i]) | |
| { | |
| // Do nothing, | |
| case '0': t[i]='0'; return true; | |
| case '1': t[i]='1'; return true; | |
| case '9': t[i]='9'; return true; | |
| // Wrap, | |
| case 'C': t[i]='A'; return true; | |
| case 'F': t[i]='D'; return true; | |
| case 'I': t[i]='G'; return true; | |
| case 'L': t[i]='J'; return true; | |
| case 'O': t[i]='M'; return true; | |
| case 'S': t[i]='P'; return true; | |
| case 'V': t[i]='T'; return true; | |
| case 'Z': t[i]='W'; return true; | |
| // Or increment. | |
| default: t[i]++; return false; | |
| } | |
| } | |
| static inline char | |
| letter_to_digit (char c) | |
| { | |
| // Map letters to digits, | |
| if ('A' <= c && c <= 'C') c='2'; | |
| else if ('D' <= c && c <= 'F') c='3'; | |
| else if ('G' <= c && c <= 'I') c='4'; | |
| else if ('J' <= c && c <= 'L') c='5'; | |
| else if ('M' <= c && c <= 'O') c='6'; | |
| else if ('P' <= c && c <= 'S') c='7'; | |
| else if ('T' <= c && c <= 'V') c='8'; | |
| else if ('W' <= c && c <= 'Z') c='9'; | |
| // Except for '0' and '1'. | |
| return c; | |
| } | |
| static char * | |
| letters_to_digits (char *t) | |
| { | |
| assert (t!=NULL); | |
| unsigned i; | |
| for (i=0; t[i]!='\0'; i++) | |
| t[i]=letter_to_digit (t[i]); | |
| return t; | |
| } | |
| static inline bool | |
| is_letter (char c) | |
| { | |
| return 'A' <= c && c <= 'Z'; | |
| } | |
| static char * | |
| next_telephone_number (char *t, unsigned l, unsigned h) | |
| { | |
| assert (t!=NULL); | |
| assert (l <= h); | |
| if (is_letter (t[l])) | |
| { | |
| if (next_letter (t, l) && l<h) | |
| next_telephone_number (t, l+1, h); | |
| } | |
| else | |
| { | |
| if (l<h) | |
| next_telephone_number (t, l+1, h); | |
| } | |
| return t; | |
| } | |
| void | |
| map_telephone_numbers (char *t, void (*func)(char *)) | |
| { | |
| assert (t!=NULL); | |
| unsigned n=strlen (t), i; | |
| long long combinations=1; | |
| for (i=0; i<n; i++) | |
| if (is_digit (t[i])) | |
| combinations *= options[t[i]-'0']; | |
| else if (is_letter (t[i])) | |
| combinations *= options[letter_to_digit (t[i])-'0']; | |
| digits_to_letters (t); | |
| while (combinations>0) | |
| { | |
| func (t); | |
| combinations--; | |
| next_telephone_number (t, 0, n-1); | |
| } | |
| letters_to_digits (t); | |
| } | |
| void | |
| print_number (char *t) | |
| { | |
| printf ("%s\n", t); | |
| } | |
| int | |
| main (int argc, char **argv) | |
| { | |
| if (argc!=2) | |
| return -1; | |
| char *t=strdup (argv[1]); | |
| if (t==NULL) | |
| return -1; | |
| map_telephone_numbers (t, print_number); | |
| /* For inputs with no capital letters in them, the following is true: | |
| assert (strcmp (t, argv[1])==0); */ | |
| free (t); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment