谜题

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

  • 提问者会要求我给他一个电话号码;
  • 听到这个数字后,提问者会反复对其进行某种转换(例如,他可能会说 十等于三)直到最终到达数字 4(此时他将以 四是魔法).
  • 无论如何,任何数字最终似乎都可以转化为四。

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

解决方案

任意一步的变换函数是

  • 拿有问题的号码,
  • 计算其英文单词表示形式中的字母数量,忽略连字符或空格或“和”(例如,“ten”有 3 个字母,“thirty-four”有 10 个字母,“一百四十三”)里面有20个字母)。
  • 返回该字母数。

对于我曾经想测试的所有数字,这个值都收敛到 4。由于“four”也有四个字母,所以这里会出现无限循环;相反,它仅被称为 魔法 按照惯例结束序列。

挑战

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

具体来说:

  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 不行。

我正在考虑将这些作为与挑战有关的奖金竞赛的单独类别,因此,如果您愿意这样做,请不要担心您的代码比数字版本长。

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

有帮助吗?

解决方案

高尔夫脚本 - 101 96 93 92 91 90 94 86字节

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

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."

其他提示

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

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.

Python 2.x,144 150 154 166 字符

这将数字分成十和个,然后将它们相加。伪三元运算符的不良性质 a and b or cc 如果返回 b is 0 在这里被滥用了。

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

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 也用于 eL 为了 een (之后使用 eighteighteen),它用在 tO 为了 teen (用于其他所有 -teen 姓名)。

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

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

关于滥用 main()

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

关于缺乏 #include

有些人会抱怨省略 #include <stdio.h> 是作弊。根本不是。给出的是一个完全合法的 C 程序,可以在我知道的任何 C 编译器上正确编译(尽管有警告)。由于缺少 stdio 函数的原型,编译器将假定它们是返回的 cdecl 函数 int, ,并且相信您知道要传递哪些参数。无论如何,在这个程序中返回值被忽略,它们都是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 而不是命令行参数,以及其他一些优化保存了相同数量的字符,导致清洗。

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

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. 

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.

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

编辑:不再使用十六进制,这样可以减少击键次数

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

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

蟒蛇,129 133 137 148 字符

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

附言。经过一些编辑后,现在大约短了二十个字符:

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

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 函数调用
  • 使用赋值表达式消除额外的语句,从而消除额外的大括号

珀尔:148 个字符

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

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

让我们用 Perl 进行一点小小的尝试来开始这个项目。

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

技巧:

太多!

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

输出:

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

哈斯克尔,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

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

德尔福: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

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();
    }
}

编辑戴卡姆:做了一些仔细的插入和更改:

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

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

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

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 而不是命令行参数可以节省更多,从而实现净节省。

珀尔, 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/

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"

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

红宝石,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."

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

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

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 - 恢复了引起注意的更改 莫布鲁莱, , 但 ($_%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; - 礼貌地 莫布鲁莱


笔记: 我厌倦了在评论中改进其他人的答案,所以现在我很贪心,可以在这里添加我的更改:)这是从 白金蔚蓝的回答 - 部分归功于 霍布斯, 莫布鲁莱, , 和 白金蔚蓝.

无耻的 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 只返回真/假;如果它返回一个计数,我将节省 7 杆。

红宝石,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}
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top