Skip to content

Instantly share code, notes, and snippets.

@markandrus
Created December 4, 2012 00:22
Show Gist options
  • Select an option

  • Save markandrus/4199333 to your computer and use it in GitHub Desktop.

Select an option

Save markandrus/4199333 to your computer and use it in GitHub Desktop.
telephone
#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