C-带数字词
445 431 427 421 399 386 371 359 * 356 354 † 348 347个字符
而已。我认为我不能再缩短时间了。
所有换行符均为可读性,可以删除:
i;P(x){char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,
fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,
4RmagicS,zero,";while(x--)if(*++p-44&&!x++)*p>95|*p<48?putchar(*p),++i:P(*p-48);
}main(c){for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))P(c?c>19?P(c/10+18),
(c%=10)&&putchar(45):0,c:37);P(36);}
在下面,它没有被缩小,但是仍然很难阅读。请参阅下面的更易读的版本。
i;
P(x){
char*p=",one,two,three,four,five,six,sM,eight,nine,tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,";
while(x--)
if(*++p-44&&!x++)
*p>95|*p<48?putchar(*p),++i:P(*p-48);
}
main(c){
for(scanf("%d",&c);c+(i=-4);P(34),P(c=i),P(35))
P(c?
c>19?
P(c/10+18),
(c%=10)&&
putchar(45)
:0,
c
:37);
P(36);
}
展开并评论:
int count; /* type int is assumed in the minified version */
void print(int index){ /* the minified version assumes a return type of int, but it's ignored */
/* see explanation of this string after code */
char *word =
/* 1 - 9 */
",one,two,three,four,five,six,sM,eight,nine,"
/* 10 - 19 */
"tL,elM,twelve,NP,4P,fifP,6P,7P,8O,9P,"
/* 20 - 90, by tens */
"twLQ,NQ,forQ,fifQ,6Q,7Q,8y,9Q,"
/* lookup table */
"en,evL,thir,eL,tO,ty, is ,.\n,4RmagicS,zero,";
while(index >= 0){
if(*word == ',')
index--;
else if(index == 0) /* we found the right word */
if(*word >= '0' && *word < 'a') /* a compression marker */
print(*word - '0'/*convert to a number*/);
else{
putchar(*word); /* write the letter to the output */
++count;
}
++word;
}
}
int main(int argc, char **argv){ /* see note about this after code */
scanf("%d", &argc); /* parse user input to an integer */
while(argc != 4){
count = 0;
if(argc == 0)
print(37/*index of "zero"*/);
else{
if(argc > 19){
print(argc / 10/*high digit*/ + 20/*offset of "twenty"*/ - 2/*20 / 10*/);
argc %= 10; /* get low digit */
if(argc != 0) /* we need a hyphen before the low digit */
putchar('-');
}
print(argc/* if 0, then nothing is printed or counted */);
}
argc = count;
print(34/*" is "*/);
print(argc); /* print count as word */
print(35/*".\n"*/);
}
print(36/*"four is magic.\n"*/);
}
关于开头附近的编码字符串
数字的名称使用非常简单的方案进行压缩。常用的子字符串将替换为名称数组中的一个字符的索引。多余名称条目的“查找表”被添加到第一组中未完全使用的子字符串的末尾。查找是递归的:条目可以引用其他条目。
例如,11的压缩名称是elM
。该print()
函数逐字输出字符e
和l
(小写的“ L”,而不是数字“ 1”),但随后找到M
,因此它使用第29个条目的索引(ASCII'M'-ASCII'0')进行调用进入查询表。该字符串是evL
,因此它输出e
和v
,然后使用查找表中第28个条目的索引()再次调用自身en
,并逐字输出。这很有用,因为en
它也在eL
for中een
使用(在eight
in中使用eighteen
),在tO
for中teen
使用(用于其他每个-teen
名称)。
这种方案导致数字名称的压缩相当显着,而只需要解压缩少量代码即可。
字符串开头和结尾的逗号说明了在该字符串中找到子字符串的简单方式。在此处添加两个字符可以在以后保存更多字符。
关于滥用 main()
argv
被忽略(因此未在压缩版本中声明),argc的值被忽略,但是存储被重用以保存当前数字。这使我不必声明额外的变量。
关于缺乏 #include
有些人会抱怨省略#include <stdio.h>
就是作弊。根本不是。给出的是一个完全合法的C程序,可以在我知道的任何C编译器上正确编译(尽管有警告)。缺少stdio函数的原型,编译器会假定它们是return的cdecl函数int
,并相信您知道要传递的参数。无论如何,返回值在该程序中都会被忽略,它们都是cdecl(“ C”调用约定)函数,我们确实知道要传递哪些参数。
输出量
输出是预期的:
0
零是四。
四是魔术。
1个
一是三。
三是五。
五是四。
四是魔术。
4
四是魔术。
20
二十点是六点。
六是三。
三是五。
五是四。
四是魔术。
21
二十一就是九。
九点四。
四是魔术。
*以前的版本在规范的两个部分上没有标记:它没有处理零,并且在命令行而不是stdin上接受了输入。处理零会添加字符,但是使用stdin而不是命令行args以及其他一些优化可以节省相同数量的字符,从而导致冲洗。
†已更改要求,以明确数字字应打印在“ is”的两面。这个新版本满足了这一要求,并实现了更多的优化,以(超过)考虑所需的额外大小。