代码高尔夫:四是魔术

时间:2010-07-12 18:11:55

标签: language-agnostic code-golf rosetta-stone

谜题

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

  • 提问者会要求我给他一个号码;
  • 在听到号码时,提问者会反复对其进行某种改造(例如,他可能会说十是三个),直到最终到达4号(此时他会完成四是魔法)。
  • 无论如何,任何数字最终都可以转化为四种。

目标是试图找出转换功能,然后能够自己可靠地监督这个难题。

解决方案

任何一步的转换功能都是

  • 拿相关号码,
  • 计算英文单词表示中的字母数,忽略连字符或空格或“和”(例如,“ten”中有3个字母,“三十四”中有10个字母,“一百四十” - 三个“里面有20个字母。”
  • 返回那个字母数。

对于我曾经考虑过的所有数字,这会收敛到4.由于“四”也有四个字母,所以这里会有一个无限循环;相反,按惯例,它仅被称为 magic 以结束序列。

挑战

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

具体做法是:

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

    > 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.
    

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

    奖金

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

    (Double bonus for drawing shapes with your code)

    (编辑)一些澄清:

    1. 我确实希望在所有适用的情况下双方都出现这个词,例如: Nine is four. Four is magic.
    2. 我不关心大写。而且我不在乎你如何分开单词代币,尽管它们应该是分开的:ninety-nine没关系,ninety nine没问题,ninetynine不合适。
    3. 我认为这是针对挑战的奖金竞赛的单独类别,所以如果你这样做,不要担心你的代码比数字版本更长。

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

30 个答案:

答案 0 :(得分:86)

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

答案 1 :(得分:57)

GolfScript - 101 96 93 92 91 90 < / s> 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."

答案 2 :(得分:30)

Common Lisp 157 Chars

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

(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.

答案 3 :(得分:21)

Python 2.x,144 150 154 166 chars

这将数字分成数十和一,并将它们相加。如果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."

答案 4 :(得分: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"*/);
}

关于开头附近的编码字符串

使用非常简单的方案压缩数字的名称。经常使用的子字符串被一个字符的索引替换为name数组。对于未在第一组中完整使用的子串,将额外名称条目的“查找表”添加到末尾。查找是递归的:条目可以引用其他条目。

例如,11的压缩名称为elMprint()函数逐字输出字符el(小写'L',而不是数字'1'),但随后它会找到M,所以它使用第29个条目的索引(ASCII“M” - ASCII“0”)将自身调用到查找表中。此字符串为evL,因此输出ev,然后使用查找表中第28个条目的索引再次调用自身,即en,并且输出逐字。这很有用,因为en eL也用于een(在eight eighteen之后使用),tO中使用了teen -teen(用于所有其他main()名称)。

此方案导致数字名称压缩相当显着,而只需要少量代码进行解压缩。

字符串开头和结尾的逗号表示在此字符串中找到子字符串的简单方式。这里添加两个字符可以在以后保存更多字符。

关于滥用argv

#include被忽略(因此未在压缩版本中声明),argc的值被忽略,但存储被重用以保存当前数字。这样就省去了我必须声明一个额外的变量。

关于缺少#include <stdio.h>

有些人会抱怨忽略int是作弊。它完全没有。给定的是一个完全合法的C程序,可以在我知道的任何C编译器上正确编译(尽管有警告)。缺少stdio函数的原型,编译器会假设它们是返回{{1}}的cdecl函数,并且相信你知道要传递什么参数。无论如何,在这个程序中忽略返回值,它们都是cdecl(“C”调用约定)函数,我们确实知道要传递的参数。

输出

输出符合预期:

0
zero is four.
four is magic.
1
one is three.
three is five.
five is four.
four is magic.
4
four is magic.
20
twenty is six.
six is three.
three is five.
five is four.
four is magic.
21
twenty-one is nine.
nine is four.
four is magic.

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

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

答案 5 :(得分: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. 

答案 6 :(得分:10)

T-SQL,413 451 499 chars

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.

答案 7 :(得分: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");
   }
}

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

答案 8 :(得分:9)

Windows PowerShell:152 153 184 bytes

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

$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.'

答案 9 :(得分: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.");
}

答案 10 :(得分: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)
                   );
    }
}

这种方法使用的技巧:

  • 根据数字中显示的数字为数字名称长度创建查找表。
  • 对字符串使用字符数组查找,使用char算术而不是数字数组。
  • 使用班级名称别名将Console.缩短为C.
  • 使用条件(三元)运算符(?:)代替if/else
  • \nWrite转义码代替WriteLine
  • 使用C#具有已定义的评估顺序以允许在Write函数调用中进行分配的事实
  • 使用赋值表达式来消除额外的语句,从而消除额外的大括号

答案 11 :(得分:6)

Python,129 133 137 148 chars

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

PS。经过几次修改后,现在约有二十个字符更短:

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.'

答案 12 :(得分:6)

Perl:148个字符

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

  • 将异常哈希移动到单元数组中。这导致我能够剪掉很多角色: - )
  • mobrule指出了一个讨厌的bug。快速修复添加31个字符,哎哟!
  • 零特殊情况下的重构,也进行了轻度高尔夫。
  • 直接列表访问一次性使用而不是存储到数组?见到了!
  • 对于一个血腥的角色进行了大量的改造。这确实是高尔夫球手的生活。 : - (
  • 哎呀,容易修复空格。 198现在。
  • 重构了一些冗余代码。
  • r中的最后一个返回关键字是不必要的,还有一些关闭。
  • 每条评论的大规模重构;不幸的是我只能得到149,因为我必须修复我早期代码和评论者版本中出现的错误。
  • 尝试赤字“魔法”。

让我们在Perl中进行一次适度的尝试。

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

技巧:

太多了!

答案 13 :(得分:5)

JavaScript 1.8(SpiderMonkey) - 153 Chars

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.')

<强>输出:

ninety nine is ten.
ten is three.
three is five.
five is four.
four is magic.

答案 14 :(得分: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

答案 15 :(得分: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);
}

答案 16 :(得分: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()更改为object string的{​​{1}}。
  • 创建了一个临时变量"magic",因此我可以将o移到break循环之外,即导致for
  • 内联do-while作业以及o作业,继续完全在函数参数中插入v的计算,从而无需l。还内联了l
  • 的分配
  • 删除了m中的空格,int[] x也是合法的。
  • 尝试将数组转换为字符串转换,但int[]x太多了,无法使其成为一种改进。

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

答案 17 :(得分: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."

答案 18 :(得分: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

答案 19 :(得分: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.");
}

* 以前的版本错过了规范的两个部分:它没有处理零,并且它在命令行而不是stdin上输入。处理零添加字符,但使用stdin而不是命令行args可以节省更多,从而节省净额。

答案 20 :(得分: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/

答案 21 :(得分: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"

答案 22 :(得分:1)

Lua 185 190 199

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

 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.'

答案 23 :(得分:1)

C ++,171个字符(#include ignored)

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.");}

答案 24 :(得分:1)

Ruby,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."

答案 25 :(得分: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分离出来的答案 - 部分归功于HobbsmobrulePlatinum Azure

答案 26 :(得分: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

旁注:perl print只返回true / false太糟糕了;如果它返回一个计数,它将节省我7笔。

答案 27 :(得分: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

答案 28 :(得分:0)

Ruby,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}

答案 29 :(得分:-7)

while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}