15. 电话号码问题
商业单位需要容易记忆的电话号码,有一些方法可以让电话号码变得更容易记忆。譬如,可以把电话号码写成单词或短语,如 MON-GLOP 可以代表滑铁卢大学的电话。有时仅仅是把号码的一部分写成单词,如打 310-GINO 便可向 GINO 比萨饼店定购比萨。另一种让电话号码容易记忆的方法是将数字用一种容易记的方式组合起来,譬如 3-10-10-10 也可以代表 GINO 比萨饼店。
电话号码的标准形式是七位十进制数字,在它的第三位和第四位之间用连字符连接(例如:666-1200)。电话的键盘提供了字符与数字之间的映射关系,如下所示:
2 | A、B和C |
3 | D、E和F |
4 | G、H和I |
5 | J、K和L |
6 | M、N和O |
7 | P、R和S |
8 | T、U和V |
9 | W、X和Y |
Q 和 Z 没有映射到键盘,而连字符不需要被拨打并且可以根据需要添加和删除。MON-GLOP 的标准形式是 666-4567,310-GINO 的标准形式是310-4466,3-10-10-10的标准形式也是 310-1010。
如果两个电话号码有相同的标准形式,那么这两个电话号码是相同的。
你所在的公司正在编辑一本当地商业单位的电话簿,作为质量控制流程的一部分,你需要确认在该电话簿中有没有错误的电话号码,以及有没有两个(或两个以上的)商业单位使用相同的电话号码。由于当地只使用了 3 和 6 两个区段,因此电话号码的第一个数字应当永远是 3 或者 6,如果出现了其它数字,就表示这个电话号码错了。此外,如果电话号码中出现了 Q 和 Z,也说明这个电话错了。
输入
一次输入为一个样例。每个号码一行,由一组包含十进制数、大写字母(Q、Z 除外)和连字符的字符串组成(每行的字符不会超过 20 个)。每次输入的数据可能会非常大,譬如超过 1,000,000 个电话号码。
你可以假设输入中可能会出现重复的电话号码不超过 1,500 个,每个号码重复的次数不超过 1000 次。
输出
输出包括两个部分,第一个部分是错误的电话号码,对于这些号码应当按照输入的顺序以原始的形式输出。在输出错误电话号码前输出“Error:”,随后输出这些号码,如果没有错误的电话号码,则输出“Not found.”。
第二部分是重复的电话号码,对每一个在电话簿中以任何形式出现一次以上的电话号码,生成一行输出。这一行应以标准形式给出电话号码,其后跟随一个空格,空格后跟随电话号码在电话簿中出现的次数。所有重复的电话号码输出行应以号码的升序排列(小号码在前)。在输出重复电话号码前输出“Duplication”,随后按照上述格式输出号码,如果在输入中没有重复的电话号码,则输出:“Not found.”。
注意
你所编写的程序以后可能会在一种特殊的嵌入式设备上运行,为了降低成本,这种设备使用的 CPU 不是很快、可用的 RAM 为 288K(跟 GBA 一样)且它没有磁盘设备因此不能使用文件作为数据的临时存储。
提示
请参考《编程珠玑》第一部分,若程序不能在规定的内存中运行,则不得分。
#include<stdio.h>
#include<string.h>
#include<malloc.h>
long count[1600];
long pows(int b,int x);
long trans(char a[]);
int checkerror(char a[]);
void compositor(long st[],int q);
void main()
{ char a[15];
int flag=0,flag1=0,i,q=0;
long d,st[1600];
printf("Error:\n");
while(gets(a)!=NULL)
{
if( checkerror(a) )
{ d=trans(a);
for(i=0;i<=q;i++)
{ if(d==st[i])
{ count[i]++;
break;
}
}
if(i>q)
{ st[i]=d;
q++;
}
}
else
{ printf("%s\n",a);
flag=1;
}
}
if(!flag)
printf("Not found.\n");
printf("\n");
compositor(st,q);
printf("Duplication:\n");
for(i=0;i<=q;i++)
{ if(count[i]!=0)
{ printf("%ld",st[i]/10000);
printf("-");
printf("%.4ld",st[i]%10000);
printf(" ");
printf("%d\n",count[i]+1);
flag1=1;
}
}
if(!flag1)
printf("Not found.\n");
}
int checkerror(char temp[15])
{ int i=0,len;
len=strlen(temp);
for(i=0;i<len;i++)
{ if(temp[i]==45)
continue;
if((temp[i]>=68&&temp[i]<=70)||(temp[i]>=77&&temp[i]<=79)||(temp[i]==51)||(temp[i]==54))
return 1;
else return 0;
}
return 0;
}
long trans(char temp[])
{ int b[10],d=0,i,len,q=0;
len=strlen(temp);
for(i=0;i<len;i++)
{ if(temp[i]==45)
continue;
if(temp[i]>=65&&temp[i]<=67)
{b[q]=2;q++;continue;}
if(temp[i]>=68&&temp[i]<=70)
{b[q]=3;q++;continue;}
if(temp[i]>=71&&temp[i]<=73)
{b[q]=4;q++;continue;}
if(temp[i]>=74&&temp[i]<=76)
{b[q]=5;q++;continue;}
if(temp[i]>=77&&temp[i]<=79)
{b[q]=6;q++;continue;}
if(temp[i]>=80&&temp[i]<=83)
{b[q]=7;q++;continue;}
if(temp[i]>=84&&temp[i]<=86)
{b[q]=8;q++;continue;}
if(temp[i]>=87&&temp[i]<=89)
{b[q]=9;q++;continue;}
else
{b[q]=temp[i]-48;q++;continue;}
}
for(q=0;q<7;q++)
d=d+ pows(b[q],6-q);
return d;
}
long pows(int b,int x)
{ int i;
long t=1;
for(i=0;i<x;i++)
t*=10;
return b*t;
}
void compositor(long st[],int q)
{ int i,j,k;
long temp;
for(i=0;i<=q-1;i++)
{ k=i;
for(j=k;j<=q;j++)
{ if(st[k]>st[j])
k=j;
}
if(k!=i)
{ temp=st[k];
st[k]=st[i];
st[i]=temp;
temp=count[k];
count[k]=count[i];
count[i]=temp;
}
}
}