88

谜题

我在高中时听到的一个小谜题是这样的......

  • 提问者会要求我给他一个数字;
  • 听到数字后,提问者会反复对其进行某种转换(例如,他可能会说10 是 3),直到最终到达数字 4 (此时他会以4 结束是魔术)。
  • 无论如何,任何数字似乎最终都可以变成四。

目标是尝试找出转换函数,然后自己能够可靠地监考这个谜题。

解决方案

任何一步的变换函数都是

  • 拿有问题的号码,
  • 计算其英文单词表示中的字母数量,忽略连字符或空格或“and”(例如,“ten”有 3 个字母,“thirty-34”有 10 个字母,“143”有20个字母)。
  • 返回该数量的字母。

对于我曾经关心过的所有数字,它都收敛到 4。由于“四”中也有四个字母,所以这里会有一个无限循环;相反,它只是按照惯例被称为魔术来结束序列。

挑战

您的挑战是创建一段代码,该代码将从用户那里读取一个数字,然后打印显示重复应用的转换函数的行,直到达到“四是魔术”。

具体来说:

  1. 解决方案本身必须是完整的程序。它们不能仅仅是在输入中接受数字因子的函数。
  2. 输入必须从标准输入中读取。(来自“echo”的管道或使用输入重定向很好,因为它也来自标准输入)
  3. 输入应该是数字形式。
  4. 对于转换函数的每次应用,都应打印一行:a is b.,其中 a 和 b 是转换中数字的数字形式。
  5. 需要句号(句号)!
  6. 最后一行自然应该说,4 is magic.
  7. 该代码应该为从0 到 99的所有数字产生正确的输出。

例子:

> 4
4 is magic.

> 12
12 is 6.
6 is 3.
3 is 5.
5 is 4.
4 is magic.

> 42
42 is 8.
8 is 5.
5 is 4.
4 is magic.

> 0
0 is 4.
4 is magic.

> 99
99 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

获胜者是源代码字符数最短的提交,这也是正确的。

奖金

您也可以尝试编写一个代码版本,在每次应用转换函数时打印出数字的英文名称。原始输入仍然是数字,但输出行应该具有数字的单词形式。

(使用您的代码绘制形状的双重奖励)

(编辑)一些澄清:

  1. 我确实希望这个词在所有适用的情况下都出现在两边,例如Nine is four. Four is magic.
  2. 不过,我不在乎大小写。而且我不在乎您如何分隔单词标记,尽管它们应该分开:ninety-nine可以,ninety nine可以,ninetynine不行。

我正在考虑将这些单独的类别用于挑战奖金竞争,所以如果你这样做,不要担心你的代码比数字版本长。

随意为每个版本提交一个解决方案。

4

30 回答 30

85

Perl,大约 147 个字符

大致基于 Platinum Azure 的解决方案:

               chop
              ($_.=
              <>);@
             u="433
            5443554
           366  887
          798   866
         555    766
        "=~     /\d
       /gx      ;#4
      sub       r{4
     -$_        ?$_
    <20         ?$u
   [$_          ]:(
  $'?           $u[
 $']            :0)
+$u[18+$&]:magic}print"
$_ is ",$_=r(),'.'while
                /\d
                /x;
                444
于 2010-07-13T20:23:48.007 回答
57

GolfScript - 101 96 93 92 91 90 94 86 字节

90 → 94:固定输出为 10 的倍数。
94 → 86:重组代码。使用 base 100 删除不可打印的字符。
86 → 85: 更短的转换为字符串。

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
于 2010-07-13T00:50:13.223 回答
30

Common Lisp 157 个字符

新的更符合标准的版本,现在读取标准输入并忽略空格和连字符:

(labels((g (x)(if(= x 4)(princ"4 is magic.")(let((n(length(remove-if(lambda(x)(find x" -"))(format nil"~r"x)))))(format t"~a is ~a.~%"x n)(g n)))))(g(read)))

以人类可读的形式:

 (labels ((g (x)
           (if (= x 4)
            (princ "4 is magic.")
            (let ((n (length (remove-if (lambda(x) (find x " -"))
                                        (format nil "~r" x)))))
               (format t"~a is ~a.~%" x n)
               (g n)))))
    (g (read)))

还有一些测试运行:

>24
24 is 10.
10 is 3.
3 is 5.
5 is 4.
4 is magic.

>23152436
23152436 is 64.
64 is 9.
9 is 4.
4 is magic.

奖励版本,165 个字符:

 (labels((g(x)(if(= x 4)(princ"four is magic.")(let*((f(format nil"~r"x))(n(length(remove-if(lambda(x)(find x" -"))f))))(format t"~a is ~r.~%"f n)(g n)))))(g(read)))

给予

>24
twenty-four is ten.
ten is three.
three is five.
five is four.
four is magic.

>234235
two hundred thirty-four thousand two hundred thirty-five is forty-eight.
forty-eight is ten.
ten is three.
three is five.
five is four.
four is magic.
于 2010-07-12T21:50:45.390 回答
21

Python 2.x, 144150 154 166字符

这将数字分成十个和一个并将它们相加。a and b or c如果为 0 ,c则返回的伪三元运算符的不良属性在b这里被滥用。

n=input()
x=0x4d2d0f47815890bd2
while n-4:p=n<20and x/10**n%10or 44378/4**(n/10-2)%4+x/10**(n%10)%10+4;print n,"is %d."%p;n=p
print"4 is magic."

以前的幼稚版本(150 个字符)。只需将所有长度编码为整数。

n=input()
while n-4:p=3+int('1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29',36)/10**n%10;print n,"is %d."%p;n=p
print"4 is magic."
于 2010-07-12T18:59:23.190 回答
20

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()函数逐字输出字符el(小写“L”,而不是数字“1”),但随后找到M,因此它使用第 29 个条目的索引(ASCII 'M' - ASCII '0')调用自身进入查找表。这个字符串是evL,所以它输出ev,然后用查找表中第 28 个条目的索引再次调用自身,即en,并且逐字输出。这很有用,因为en也用于eLfor een(在eightin之后使用eighteen),它用于tOfor teen(用于其他所有-teen名称)。

这种方案对数字名称进行了相当大的压缩,同时只需要少量代码即可解压缩。

字符串开头和结尾的逗号说明了在此字符串中找到子字符串的简单方式。在此处添加两个字符可以稍后保存更多字符。

关于滥用main()

argv被忽略(因此未在压缩版本中声明),argc 的值被忽略,但存储被重用以保存当前数字。这只是让我不必声明一个额外的变量。

关于缺乏#include

有些人会抱怨省略#include <stdio.h>是作弊。根本不是。给出的是一个完全合法的 C 程序,可以在我知道的任何 C 编译器上正确编译(尽管有警告)。由于缺少 stdio 函数的原型,编译器将假定它们是 cdecl 函数返回int,并相信您知道要传递哪些参数。无论如何,在这个程序中返回值被忽略了,它们都是 cdecl(“C”调用约定)函数,我们确实知道要传递什么参数。

输出

输出如预期:

0
零是四。
四是魔法。
1
一是三。
三是五。
五是四。
四是魔法。
4
四是魔法。
20
二十是六。
六是三。
三是五。
五是四。
四是魔法。
21
二十一是九。
九是四。
四是魔法。

*以前的版本在规范的两个部分没有标记:它没有处理零,并且它在命令行而不是标准输入上输入。处理零添加字符,但使用标准输入而不是命令行参数,以及其他一些优化保存了相同数量的字符,导致清洗。

要求已更改,明确数字字应印在“是”的两侧。这个新版本满足了这一要求,并实施了更多优化以(超过)考虑必要的额外大小。

于 2010-07-12T23:41:30.750 回答
10

J,107 112 个字符

'4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.
(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:

(换行仅供阅读)

用法和输出:

    '4 is magic.',~}:('.',~":@{.,' is ',":@{:)"1]2&{.\.(]{&(#.100 4$,#:3 u:ucp'䌵䐵吶梇禈榛ꪛ멩鮪鮺墊馊꥘誙誩墊馊ꥺ겻곋榛ꪛ멩鮪鮺'))^:a:12
12 is 6.    
6 is 3.     
3 is 5.     
5 is 4.     
4 is magic. 
于 2010-07-12T18:53:28.653 回答
10

T-SQL,413 451 499个字符

CREATE FUNCTION d(@N int) RETURNS int AS BEGIN
Declare @l char(50), @s char(50)
Select @l='0066555766',@s='03354435543668877987'
if @N<20 return 0+substring(@s,@N+1,1) return 0+substring(@l,(@N/10)+1,1) + 0+(substring(@s,@N%10+1,1))END
GO
CREATE proc M(@x int) as BEGIN
WITH r(p,n)AS(SELECT p=@x,n=dbo.d(@x) UNION ALL SELECT p=n,n=dbo.d(n) FROM r where n<>4)Select p,'is',n,'.' from r print '4 is magic.'END

(并不是我认真建议你这样做......真的我只是想写一个 CTE)

要使用:

M 95

退货

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.
于 2010-07-13T04:15:54.803 回答
9

Java(带样板文件),308 290 286 282 280 个字符

class A{public static void main(String[]a){int i=4,j=0;for(;;)System.out.printf("%d is %s.%n",i=i==4?new java.util.Scanner(System.in).nextInt():j,i!=4?j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:"magic");}}

我敢肯定 Groovy 会摆脱这些。

解释和格式化(所有注释、换行符和前导/尾随空格都被删除):

合理直截了当,但是

//boilerplate
class A{
   public static void main(String[]a){
      //i is current/left number, j right/next number.  i=4 signals to start
      //by reading input
      int i=4,j=0;
      for(;;)
         //print in the form "<left> is <right>."
         System.out.printf(
            "%d is %s.%n",
            i=i==4?
               //<left>: if i is 4 <left> will be a new starting number
               new java.util.Scanner(System.in).nextInt():
               //otherwise it's the next val
               j,
            i!=4?
               //use string to map number to its length (:;< come after 9 in ASCII)
               //48 is value of '0'.  store in j for next iteration
               j="43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:".charAt(i)-48:
               //i==4 is special case for right; print "magic"
               "magic");
   }
}

编辑:不再使用十六进制,这是更少的击键

于 2010-07-12T19:23:40.747 回答
9

Windows PowerShell:152 153 184字节

基于之前的解决方案,受其他解决方案的影响更大

$o="03354435543668877988"
for($input|sv b;($a=$b)-4){if(!($b=$o[$a])){$b=$o[$a%10]-48+"66555766"[($a-$a%10)/10-2]}$b-=48-4*!$a
"$a is $b."}'4 is magic.'
于 2010-07-12T21:50:55.217 回答
8

C,158 个字符

main(n,c){char*d="03354435543668877988";for(scanf("%d",&n);n-4;n=c)printf("%d is %d.\n",n,c=n?n<19?d[n]-48:d[n%10]-"_,**+++)**"[n/10]:4);puts("4 is magic.");}

(最初基于 Vlad 的 Python 代码,借用了 Tom Sirgedas 的 C++ 解决方案的一个技巧来挤出更多字符)

扩展版:

main(n, c) {
    char *d = "03354435543668877988";
    for (scanf("%d",&n); n-4; n = c)
        printf("%d is %d.\n", n, c = n ? n<19 ? d[n]-48 : d[n%10] - "_,**+++)**"[n/10]  : 4);
    puts("4 is magic.");
}
于 2010-07-12T20:36:59.883 回答
6

Perl:148 个字符

(Perl:233 181 212 206 200 199 198 185 179 149 148 个字符)

  • 将异常哈希移动到单元数组中。这导致我能够剪掉很多角色:-)
  • mobrule 指出了一个讨厌的错误。快速修复增加了 31 个字符,哎哟!
  • 针对零特殊情况进行了重构,也完成了温和的高尔夫运动。
  • 直接列表访问以供一次性使用而不是存储到数组?当然好!
  • 只为一个血腥的角色进行了如此多的重构。这确实是高尔夫球手的生活。:-(
  • 哎呀,简单的空白修复。现在198。
  • 重构了一些冗余代码。
  • 最后一个 return 关键字r是不必要的,剃掉了更多。
  • 根据评论进行大规模重构;不幸的是,我只能将它提高到 149,因为我必须修复我早期代码和评论者版本中都存在的错误。
  • 尝试裸词“魔术”。

让我们在 Perl 中进行一次适度的尝试,让这个球滚动起来。

@u=split'','4335443554366887798866555766';$_=<>;chop;print"$_ is ".($_=$_==4?0:$_<20?$u[$_]:($u[$_/10+18]+($_%10&&$u[$_%10]))or magic).".
"while$_

技巧:

太多!

于 2010-07-12T19:25:10.653 回答
6

C#:210 个字符。

压扁:

using C=System.Console;class B{static void Main(){int
x=0,y=int.Parse(C.ReadLine());while(x!=4)C.Write((x=y)+" is {0}.\n",x==4?"magic":""+(y=x==0?4:"03354435543668877988"[x<20?x:x%10]+"0066555766"[x/10]-96));}}

扩展:

using C=System.Console;
class B
{
    static void Main()
    {
        int x=0,y=int.Parse(C.ReadLine());
        while(x!=4)
            C.Write((x=y)+" is {0}.\n",
                x==4?
                     "magic":
                     ""+(y= x==0?
                                4:
                                "03354435543668877988"[x<20?x:x%10]+
                                "0066555766"[x/10]-96)
                   );
    }
}

这种方法使用的技巧:

  • 根据号码中出现的数字创建号码名称长度的查找表。
  • 对字符串使用字符数组查找,并使用字符算术而不是数值数组。
  • 使用类名别名来缩短Console.C.
  • 使用条件(三元)运算符 ( ?:) 代替if/else
  • 使用\nWrite转义码代替WriteLine
  • 使用 C# 具有定义的评估顺序这一事实,以允许在Write函数调用内进行分配
  • 使用赋值表达式来消除额外的语句,从而消除额外的大括号
于 2010-07-12T21:47:15.813 回答
6

蟒蛇,129133 137 148字符

作为热身,这是我的第一个版本(比以前最好的 Python 改进了几个字符)。

PS。经过几次编辑,现在它缩短了大约 20 个字符:

n=input()
while n-4:p=(922148248>>n/10*3&7)+(632179416>>n%10*3&7)+(737280>>n&1)+4*(n<1);print n,'is %d.'%p;n=p
print'4 is magic.'
于 2010-07-14T03:16:00.170 回答
5

JavaScript 1.8 (SpiderMonkey) - 153 个字符

l='4335443554366887798866555766'.split('')
for(b=readline();(a=+b)-4;print(a,'is '+b+'.'))b=a<20?l[a]:+l[18+a/10|0]+(a%10&&+l[a%10])
print('4 is magic.')

用法: echo 42 | js golf.js

输出:

42 is 8.
8 is 5.
5 is 4.
4 is magic.

有奖金 - 364 个字符

l='zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty thirty fourty fifty sixty seventy eighty ninety'.split(' ')
z=function(a)a<20?l[a]:l[18+a/10|0]+(a%10?' '+l[a%10]:'')
for(b=+readline();(a=b)-4;print(z(a),'is '+z(b)+'.'))b=z(a).replace(' ','').length
print('four is magic.')

输出:

九十九是十。
十是三。
三是五。
五是四。
四是魔法。
于 2010-07-13T03:13:34.497 回答
4

C++ Stdio 版本,缩小:196 个字符

#include <cstdio>
#define P;printf(
char*o="43354435543668877988";main(int p){scanf("%d",&p)P"%d",p);while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]P" is %d.\n%d",p,p);}P" is magic.\n");}

C++ Iostreams 版本,缩小:195 个字符

#include <iostream>
#define O;std::cout<<
char*o="43354435543668877988";main(int p){std::cin>>p;O p;while(p!=4){p=p<20?o[p]-48:"0366555966"[p/10]-96+o[p%10]O" is "<<p<<".\n"<<p;}O" is magic.\n";}

原始,未缩小:344 个字符

#include <cstdio>

int ones[] = { 4, 3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8 };
int tens[] = { 0, 3, 6, 6, 5, 5, 5, 9, 6, 6 };

int n(int n) {
    return n<20 ? ones[n] : tens[n/10] + ones[n%10];
}

int main(int p) {
    scanf("%d", &p);
    while(p!=4) {
        int q = n(p);
        printf("%i is %i\n", p, q);
        p = q;
    }
    printf("%i is magic\n", p);
}
于 2010-07-12T19:46:43.037 回答
4

Haskell,224 270 个字符

o="43354435543668877988"
x!i=read[x!!i]
n x|x<20=o!x|0<1="0066555766"!div x 10+o!mod x 10
f x=zipWith(\a b->a++" is "++b++".")l(tail l)where l=map show(takeWhile(/=4)$iterate n x)++["4","magic"]
main=readLn>>=mapM putStrLn.f

并且更具可读性 -

ones = [4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8]
tens = [0,0,6,6,5,5,5,7,6,6]

n x = if x < 20 then ones !! x else (tens !! div x 10) + (ones !! mod x 10)

f x = zipWith (\a b -> a ++ " is " ++ b ++ ".") l (tail l)
    where l = map show (takeWhile (/=4) (iterate n x)) ++ ["4", "magic"]
    
main = readLn >>= mapM putStrLn . f
于 2010-07-12T21:56:20.767 回答
3

C# 314 286 283 274 289 273 252 个字符。

压扁:

252 

普通的:

using C = System.Console;
class P
{
    static void Main()
    {
        var x = "4335443554366877798866555766";
        int m, o, v = int.Parse(C.ReadLine());
        do {
            C.Write("{0} is {1}.\n", o = v, v == 4 ? (object)"magic" : v = v < 20 ? x[v] - 48 : x[17 + v / 10] - 96 + ((m = v % 10) > 0 ? x[m] : 48));
        } while (o != 4);
        C.ReadLine();
    }
}

编辑 Dykam:做了一些仔细的插入和更改:

  • 将 l.ToString() 更改objectstring "magic".
  • 创建了一个临时变量o,所以我可以移动循环break外部for,即产生一个do-while.
  • 内联o赋值以及v赋值,继续在函数参数中完全插入计算l,消除对l. 还内联了m.
  • 删除了一个空格int[] xint[]x也是合法的。
  • 试图将数组转换为字符串转换,但是using System.Linq太多了,无法对此进行改进。

编辑 2 Dykam 将 int 数组更改为 char 数组/字符串,添加适当的算术来纠正此问题。

于 2010-07-12T21:39:30.433 回答
3

德尔福:329 个字符

单行版本:

program P;{$APPTYPE CONSOLE}uses SysUtils;const S=65;A='EDDFEEDFFEDGGIIHHJII';B='DGGFFFJGG';function Z(X:Byte):Byte;begin if X<20 then Z:=Ord(A[X+1])-S else Z:=(Ord(B[X DIV 10])-S)+Z(X MOD 10)end;var X,Y:Byte;begin Write('> ');ReadLn(X);repeat Y:=Z(X);WriteLn(Format('%d is %d.',[X,Y]));X:=Y;until X=4;WriteLn('4 is magic.');end.

形成:

program P;

{$APPTYPE CONSOLE}

uses
  SysUtils;

const
  S = 65;
  A = 'EDDFEEDFFEDGGIIHHJII';
  B = 'DGGFFFJGG';

function Z(X:Byte):Byte;
begin
  if X<20
  then Z := Ord(A[X+1])-S
  else Z := (Ord(B[X DIV 10])-S) + Z(X MOD 10);
end;

var
  X,Y: Byte;

begin
  Write('> ');
  ReadLn(X);

  repeat
    Y:=Z(X);
    WriteLn(Format('%d is %d.' , [X,Y]));
    X:=Y;
  until X=4;

  WriteLn('4 is magic.');
end.

可能还有更多的挤压空间...... :-P

于 2010-07-13T02:38:17.470 回答
3

C - 没有数字词

180 175 * 172 167 个字符

所有换行符都是为了便于阅读,可以删除:

i;V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}main(c){for(scanf("%d",&c);
c-4;)i=c,printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);puts(
"4 is magic.");}

略微未缩小:

i;
V(x){return"\3#,#6$:WOXB79B"[x/2]/(x%2?1:10)%10;}
main(c){
    for(scanf("%d",&c);c-4;)
        i=c,
        printf("%d is %d.\n",i,c=c?c>19?V(c/10+19)+V(c%10):V(c):4);
    puts("4 is magic.");
}

*以前的版本在规范的两个部分没有标记:它没有处理零,并且它在命令行而不是标准输入上输入。处理零添加的字符,但使用标准输入而不是命令行参数可以节省更多,从而实现净节省。

于 2010-07-13T05:58:31.627 回答
3

Lua,176 个字符

o={[0]=4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8}t={3,6,6,5,5,5,7,6,6}n=0+io.read()while n~=4 do a=o[n]or o[n%10]+t[(n-n%10)/10]print(n.." is "..a..".")n=a end print"4 is magic."

或者

  o={[0]=4,3,3,5,4,4
  ,3,5,5,4,3,6,6,8,8
  ,7,7,9,8,8}t={3,6,
   6,5,5,5,7,6,6}n=
   0+io.read()while
   n ~= 4 do a= o[n
   ]or o[n%10]+t[(n
   -n%10)/10]print(
n.." is "..a.."." )n=a
end print"4 is magic."
于 2010-07-16T16:13:57.173 回答
2

perl,123 122 个字符

刚刚意识到不需要输出到STDOUT,所以改为输出到STDERR并敲掉另一个字符。

@u='0335443554366887798866555766'=~/./g;$_+=<>;warn"$_ is ",$_=$_-4?$_<20?$u[$_]||4:$u[chop]+$u[$_+18]:magic,".\n"until/g/

并且,返回拼写数字的版本:

279 278 276 280 个字符

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2] $n[$n%10]":Zero}$p+=<>;warnt$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/

虽然符合规范,但它的格式不是 100%。它在以零结尾的数字后返回一个额外的空格。规范确实说:

“我不在乎你如何分隔单词标记,尽管它们应该分开”

不过,这有点狡猾。更正确的版本在

282 281 279 283 个字符

@p=(Thir,Four,Fif,Six,Seven,Eigh,Nine);@n=("\x8",One,Two,Three,Four,Five,@p[3..6],Ten,Eleven,Twelve,map$_.teen,@p);s/u//for@m=map$_.ty,Twen,@p;$n[8].=t;sub n{$n=shift;$n?$n<20?$n[$n]:"$m[$n/10-2]-$n[$n%10]":Zero}$p+=<>;warn$m=n($p)," is ",$_=$p-4?n$p=()=$m=~/\w/g:magic,".\n"until/c/
于 2010-07-20T23:14:26.113 回答
1

Python:

#!/usr/bin/env python

# Number of letters in each part, we don't count spaces
Decades = ( 0, 3, 6, 6, 6, 5, 5, 7, 6, 6, 0 )
Smalls  = ( 0, 3, 3, 5, 4, 4, 3, 5, 5, 4 )
Teens  =  ( 6, 6, 8, 8, 7, 7, 9, 8, 8 )

def Count(n):
    if n > 10 and n < 20: return Teens[n-11]
    return   Smalls[n % 10 ] + Decades [ n / 10 ]

N = input()

while N-4:
    Cnt = Count(N)
    print "%d is %d" % ( N, Cnt)
    N = Cnt

print "4 is magic"
于 2010-07-12T18:57:30.170 回答
1

红宝石,164 个字符

n=gets.to_i;s="03354435543668877987";if n==0;puts"0 is 4.";else;puts"#{n} is #{n=(n<20)?s[n]-48:"0066555766"[n/10]-48+s[n%10]-48}." until n==4;end;puts"4 is magic."

解码:

n = gets.to_i
s = "03354435543668877987"
if n == 0
  puts "0 is 4."
else
  puts "#{n} is #{n = (n < 20) ? s[n] - 48 : "0066555766"[n / 10] - 48 + s[n % 10] - 48}." until n == 4
end

puts "4 is magic."
于 2010-07-12T20:32:28.923 回答
1

C++,171 个字符(#include 省略)

void main(){char x,y,*a="03354435543668877988";scanf("%d",&x);for(;x-4;x=y)y=x?x<19?a[x]-48:"_466555766"[x/10]+a[x%10]-96:4,printf("%d is %d.\n",x,y);puts("4 is magic.");}
于 2010-07-12T21:27:40.980 回答
1

卢阿185 190 199

添加句点,添加 io.read,在最后一次打印时删除 ()

 n=io.read();while(n~=4)do m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;print(n,' is ',m,'.')n=m;end print'4 is magic.'

带换行符

 n=io.read()
 while (n~=4) do
    m=('43354435543668877988699;::9;;:699;::9;;:588:998::9588:998::9588:998::97::<;;:<<;699;::9;;:699;::9;;:'):sub(n+1):byte()-48;
    print(n,' is ',m,'.')
    n=m;
 end 
 print'4 is magic.'
于 2010-07-12T21:55:09.237 回答
0

PhP代码

function get_num_name($num){  
    switch($num){  
        case 1:return 'one';  
    case 2:return 'two';  
    case 3:return 'three';  
    case 4:return 'four';  
    case 5:return 'five';  
    case 6:return 'six';  
    case 7:return 'seven';  
    case 8:return 'eight';  
    case 9:return 'nine';  
    }  
}  

function num_to_words($number, $real_name, $decimal_digit, $decimal_name){  
    $res = '';  
    $real = 0;  
    $decimal = 0;  

    if($number == 0)  
        return 'Zero'.(($real_name == '')?'':' '.$real_name);  
    if($number >= 0){  
        $real = floor($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }else{  
        $real = ceil($number) * (-1);  
        $number = abs($number);  
        $decimal = number_format($number - $real, $decimal_digit, '.', ',');  
    }  
    $decimal = substr($decimal, strpos($decimal, '.') +1);  

    $unit_name[1] = 'thousand';  
    $unit_name[2] = 'million';  
    $unit_name[3] = 'billion';  
    $unit_name[4] = 'trillion';  

    $packet = array();    

    $number = strrev($real);  
    $packet = str_split($number,3);  

    for($i=0;$i<count($packet);$i++){  
        $tmp = strrev($packet[$i]);  
        $unit = $unit_name[$i];  
        if((int)$tmp == 0)  
            continue;  
        $tmp_res = '';  
        if(strlen($tmp) >= 2){  
            $tmp_proc = substr($tmp,-2);  
            switch($tmp_proc){  
                case '10':  
                    $tmp_res = 'ten';  
                    break;  
                case '11':  
                    $tmp_res = 'eleven';  
                    break;  
                case '12':  
                    $tmp_res = 'twelve';  
                    break;  
                case '13':  
                    $tmp_res = 'thirteen';  
                    break;  
                case '15':  
                    $tmp_res = 'fifteen';  
                    break;  
                case '20':  
                    $tmp_res = 'twenty';  
                    break;  
                case '30':  
                    $tmp_res = 'thirty';  
                    break;  
                case '40':  
                    $tmp_res = 'forty';  
                    break;  
                case '50':  
                    $tmp_res = 'fifty';  
                    break;  
                case '70':  
                    $tmp_res = 'seventy';  
                    break;  
                case '80':  
                    $tmp_res = 'eighty';  
                    break;  
                default:  
                    $tmp_begin = substr($tmp_proc,0,1);  
                    $tmp_end = substr($tmp_proc,1,1);  

                    if($tmp_begin == '1')  
                        $tmp_res = get_num_name($tmp_end).'teen';  
                    elseif($tmp_begin == '0')  
                        $tmp_res = get_num_name($tmp_end);  
                    elseif($tmp_end == '0')  
                        $tmp_res = get_num_name($tmp_begin).'ty';  
                    else{  
                        if($tmp_begin == '2')  
                            $tmp_res = 'twenty';  
                        elseif($tmp_begin == '3')  
                            $tmp_res = 'thirty';  
                        elseif($tmp_begin == '4')  
                            $tmp_res = 'forty';  
                        elseif($tmp_begin == '5')  
                            $tmp_res = 'fifty';  
                        elseif($tmp_begin == '6')  
                            $tmp_res = 'sixty';  
                        elseif($tmp_begin == '7')  
                            $tmp_res = 'seventy';  
                        elseif($tmp_begin == '8')  
                            $tmp_res = 'eighty';  
                        elseif($tmp_begin == '9')  
                            $tmp_res = 'ninety';  

                        $tmp_res = $tmp_res.' '.get_num_name($tmp_end);  
                    }  
                    break;  
            }  

            if(strlen($tmp) == 3){  
                $tmp_begin = substr($tmp,0,1);  

                $space = '';  
                if(substr($tmp_res,0,1) != ' ' && $tmp_res != '')  
                    $space = ' ';  

                if($tmp_begin != 0){  
                    if($tmp_begin != '0'){  
                        if($tmp_res != '')  
                            $tmp_res = 'and'.$space.$tmp_res;  
                    }  
                    $tmp_res = get_num_name($tmp_begin).' hundred'.$space.$tmp_res;  
                }  
            }  
        }else  
            $tmp_res = get_num_name($tmp);  
        $space = '';  
        if(substr($res,0,1) != ' ' && $res != '')  
            $space = ' ';  
        $res = $tmp_res.' '.$unit.$space.$res;  
    }  

    $space = '';  
    if(substr($res,-1) != ' ' && $res != '')  
        $space = ' ';  

    if($res)  
        $res .= $space.$real_name.(($real > 1 && $real_name != '')?'s':'');  

    if($decimal > 0)  
        $res .= ' '.num_to_words($decimal, '', 0, '').' '.$decimal_name.(($decimal > 1 && $decimal_name != '')?'s':'');  
    return ucfirst($res);  
}  

/////////// 测试 ///////////////

 $str2num = 12;
    while($str2num!=4){
        $str = num_to_words($str2num, '', 0, '');  
        $str2num = strlen($str)-1;
        echo $str . '=' . $str2num .'<br/>';
        if ($str2num == 4)
            echo 'four is magic';
    }

////// 结果 /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic
于 2010-07-12T21:27:27.220 回答
0

Perl - 130 个字符


5.12.1(130 个字符)121 123 132 136 140

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123

@u='4335443554366887798866555766'=~/./g;$_=pop;say"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,"."until/\D/


5.10.1(134 个字符)125 127 136 140 144

#        1         2         3         4         5         6         7         8         9        100        11        12        13       14    
#23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 1234

@u='4335443554366887798866555766'=~/./g;$_=pop;print"$_ is ",$_=$_-4?$_<20?$u[$_]:$u[$_/10+18]+(($_%=10)&&$u[$_]):magic,".\n"until/\D/


更改历史:

20100714:2223- 在mobrule的注意下恢复更改,但是($_%10&&$u[$_%10])(($_%=10)&&$u[$_]),这是相同的字符数,但我这样做是为了以防有人可能会看到改进它的方法

20100714:0041- split//,'...''...'=~/./g
20100714:0025- ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340- while$_until/\D/+ 去掉了不必要的括号
20100713:xxxx- $=<>;chop;$_=pop;-感谢 mobrule


注意:我厌倦了在评论中改进其他人的答案,所以现在我很贪心,可以在这里添加我的更改:) 这是从Platinum Azure的答案中分离出来的 - 部分归功于Hobbsmobrule铂金天青

于 2010-07-14T02:18:52.453 回答
0

带有数字单词的无耻 Perl(329 个字符)

相当直接地改编自 P Daddy 的 C 代码,并进行了一些调整以p()使其使用 Perl 原语而不是 C 原语来做同样的事情,以及一个大部分重写的主循环。请参阅他的解释。换行符都是可选的。

@t=(qw(zero 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 4SmagicT)," is ",".\n");
sub p{local$_=$t[pop];1while s/[0-Z]/$t[-48+ord$&]/e;
print;length}$_=<>;chop;while($_-4){
$_=($_>19?(p($_/10+18),$_&&print("-"),$_%=10)[0]:0)+p$_;
p 35;p$_;p 36}p 34

旁注:perlprint只返回 true/false 太糟糕了;如果它返回计数,它将为我节省 7 次。

于 2010-07-16T03:04:18.407 回答
0

红宝石,141 个字符:

n=gets.to_i;m="4335443554366887798866555766";loop{s=n;n=n>20?m[18+n/10]+m[n%10]-96: m[n]-48;puts"#{s} is #{n==s ? 'magic': n}.";n==s &&break}
于 2011-05-26T15:59:32.417 回答
-7
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
于 2010-07-14T14:55:49.197 回答