高尔夫守则:四是魔术


88

难题

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

  • 发问者会请我给他一个电话。
  • 听到数字后,发问者会反复对它进行某种转换(例如,他可能会说十是三),直到最终得出数字4(此时他以结束便是魔术)。
  • 无论如何,任何数字似乎最终都可以转换为四个。

目的是尝试找出转换函数,然后自己可靠地促成此难题。

解决方案

任何步骤的转换功能都是

  • 拿有问题的号码,
  • 计算英文单词表示形式中字母的数量,忽略连字符或空格或“和”(例如,“十”中包含3个字母,“三十四”中包含10个字母,“一百四十三”里面有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不能。

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

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


1
我们应该处理多少数字?<100?<1000?<1000000?<2 ** 31?
P爸爸

1
由于这只需要从0到99,所以我怀疑一种快速,简短的解决方案是对0-99映射到的值进行硬编码,然后循环直到达到4。然后,开始进行微调整。
Beska

@P Daddy ...第6部分只说0-99。
Beska


14
4只是魔术,因为它是由公平骰子选择的。
VirtuosiMedia

Answers:


57

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

为什么这么远?它比lisp短,并且不使用内置的格式化功能
Claudiu 2010年

36
我喜欢代码的结尾"magic.",几乎可以总结一下。
阿斯蒂娜

@Aistina:在这个挑战中,这很容易做到。:-)
白金Azure

9
@Aistina:哈哈,真是有趣。“ mumbo jumbo yada yada..magic”
vol7ron

1
@P Daddy d)as 提取,100并用作基本转换的基数。
Nabb

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

1
@Platinum Azure获取输入信息的方式是使用pop,不带任何参数。子例程外部pop将删除,并返回其最后一个值@ARGV是Perl程序的参数列表。可以很容易地将其替换为shift,但这又增加了2个字符。参见:p3rl.org/pop
Brad Gilbert

似乎需要in的换行符'.'\n如果要在'. '(空格为换行文字)中计算空格,则为2 或1
vol7ron 2010年

更长一点,但是创造力在我的书中走了很长一段路。
Beska

@Platinum Azure等:他正在从stdin那里获取输入。这就是在Perl中实现的方式。(也许他在您发表评论后将其更改了?)
弗兰克(Frank

@P爸爸:吟,但您的评论还是+1
白金Azure

30

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

5
我以为“二十四”只有10个字母?
肯尼

1
“ is”之后的数字也应为文本。
Mike DeSimone

5
为什么这么高?其他人则不使用内置格式功能,而且字符较少
Claudiu

3
@Claudiu因为Common Lisp很棒。
Mornedhel

3
如果您没有将球打入洞中,则无论打了几杆都没关系。人们似乎忘记了当他们提出错误的解决方案时。
马克·彼得斯

21

Python 2.x,144 150 154 166 字符

这会将数字分为十个和一个,然后将它们相加。伪三元运算符的不想要的性质a and b or cc,如果返回b值为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."

抱歉,正是因为这样的事情,我才特别想要句号。:-)很好的入门!(编辑:我不懂Python,但是可以吗n,"is",p,"."?如果我计算正确的话,我想您仍然可以保存一些特征)
Platinum Azure

2
@Plat:会在之前引起额外的空间.
kennytm 2010年

@KennyTM:哦,嗯,即使是摘录,我也应该注意到这一点。糟糕!嗯,无论如何,正如我所说的,某些规范是专门为使事情复杂化而设计的。:-)
白金Azure

我们可以通过使用高于36的基数来缩短它吗?
MikeD 2010年

@MikeD:不。来自Python文档:“ base参数给出了转换的基础(默认为10),可以是[2,36]范围内的任何整数,也可以是零。” 现在,你可能能够使用比其他的功能int(),想说什么了的structbase64模块...
迈克·德西蒙

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函数的原型,编译器会假定它们是return的cdecl函数int,并相信您知道要传递的参数。无论如何,返回值在该程序中都会被忽略,它们都是cdecl(“ C”调用约定)函数,我们确实知道要传递哪些参数。

输出量

输出是预期的:

0
零是四。
四是魔术。
1个
一是三。
三是五。
五是四。
四是魔术。
4
四是魔术。
20
二十点是六点。
六是三。
三是五。
五是四。
四是魔术。
21
二十一就是九。
九点四。
四是魔术。

*以前的版本在规范的两个部分上没有标记:它没有处理零,并且在命令行而不是stdin上接受了输入。处理零会添加字符,但是使用stdin而不是命令行args以及其他一些优化可以节省相同数量的字符,从而导致冲洗。

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


这很容易成为我最喜欢的答案一词...太好了。+1,如果我能给我两个勾号,我会的。
白金天蓝色

5
读起来很有趣,我想从现在开始我将使用这些数字。六,sem,八,九,tel,elem,十二,enpee,fourpee,fifpee,sixpee,sevenpee,octoh,ninepee,twelkyu ... =)
deceze

10

J,107112 字符

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

15
它用中文编译
belisarius博士,2010年

3
请选择一名非中文裁判
belisarius博士2010年

3
@beli:멩,겻,곋,멩是韩语。
kennytm 2010年

1
我的妻子(说中文)说的是中文和韩文的混合体。
罗兰·佩希特尔

3
@belisarius:1)她不懂韩语。2)中国人胡言乱语。
洛伦·佩希特尔

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.

您不能只打印单个结果而不返回表格吗?这样可以使输出看起来更好。
乔伊(Joey)2010年

1
我认为它不能正确处理零。这样的事情怎么样:CREATE FUNCTION d(@ int) RETURNS int AS BEGIN Declare @l char(9),@s char(50) Select @l='066555766',@s='03354435543668877987' if @=0 return 4 if @<20 return 0+substring(@s,@+1,1)return 0+substring(@l,@/10,1)+substring(@s,@%10+1,1)END
加布(Gabe)2010年

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

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


1
249(不带进口),class def或main def。
马克·彼得斯

1
那是恶魔。我喜欢基数16。(+ 1)
白金Azure

您可以使用String[]a代替来节省一个空间String[] a
BalusC

感谢@Balus,还通过对字符执行简单算术而不是使用十六进制解析来消除了一些麻烦。
马克·彼得斯

@马克·彼得斯:甚至更讨厌。相比之下,我感觉太香草了。
白金Azure

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

固定为支持10的倍数(“ 90”而不是“ ninetyzero”)。
加布

嘿@Gabe :),谢谢;最近没有太多时间打高尔夫球。不过,$input由于您不能直接将枚举数强制转换为int; ,因此必须保留引号。它会在string第一次通过时起作用:-)
Joey

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

似乎对我不起作用:./ magic 10 10是-27。分段错误
凯西2010年

@Casey-scanf()调用有点粗略。它正在将一个int读取为char。我在OSX和Windows上都无法使用它,但是它在退出时崩溃了。所以,我又做了n&c ints。我意识到我可以通过使用K&R表示法使它们成为参数来删除int关键字。结果更安全,一个字符短。
Ferruccio 2010年

您可以保存3个字符,方法是将“ 466555766” [n / 10] + d [n%10] -96替换为d [n%10]-“+++) ” [n / 10]
Tom Sirgedas

6

蟒蛇,129 133 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.'

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
  • 使用\nwith Write转义代码代替WriteLine
  • 利用C#具有定义的求值顺序这一事实,以允许在Write函数调用内进行赋值
  • 使用赋值表达式消除多余的语句,从而消除多余的花括号

int[] z会更短,因为它不需要new[]
Joey

修改为使用字符算术而不是数组查找。
LBushkin

@ mdm20:你是对的。我在查询表中犯了一个错误。立即修复。
LBushkin

好吧,第十二时间是魅力:* D
LBushkin

一个quicky保存5个字符:比铸造短"magic"object,将隐式调用ToString()y加入""。但是,由于+优先级高于?:,因此您必须将其放在真实部分中,而不是错误部分中: x!=4?y+"":"magic"
P爸爸

6

Perl:148个字符

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

  • 将异常哈希移到单位数组中。这导致我能够剪切很多字符:-)
  • mobrule指出了一个令人讨厌的错误。快速修复,添加31个字符,哎呀!
  • 重构为零特例,也进行了轻度打高尔夫球。
  • 直接使用列表访问而不是存储到数组?当然好!
  • 仅需一个血腥字符就可以进行如此多的重新处理。这确实是高尔夫球手的生活。:-(
  • 糟糕,简单的空格修复。现在198。
  • 重构了一些冗余代码。
  • r不需要输入最后一个return关键字,节省了更多。
  • 每个评论的大规模重构;不幸的是,我只能将其提高到149,因为我必须修复早期代码和评论者版本中都存在的错误。
  • 尝试裸字“魔术”。

让我们在Perl中进行适度的尝试来使此球滚动。

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

技巧:

太多!


ACK!我从未测试过我永远不会知道的方式。
白金天蓝色

你那里有死代码吗?我没有看到当$ u [0]为4时零的特殊情况是怎么必要的。我的代码@ 166个字符看似工作正常,我认为它的空间比这短。
霍布斯

@hobbs:好点,我再看一遍。故事是我经历了几次修订,但突然间事情就破裂了(大约在我选择4-> 0的时候)。我认为您现在是对的,但:-)
Platinum Azure

我认为自己不是一个出色的Perl程序员,但是您可以减少一些字符:@u=split$x,'43350435543668877988';您的逗号使用了不必要的19个字符,undef每个字符都会分割$x成两半,我用作未定义变量来代替`undef`-total节省:11个字符。另外,删除min chomp,您会得到另一个字符,您的分数被削减了。
vol7ron

做得更好,但是您仍然可以通过sub r完全丢失来节省更多-您只需要使用一次,就可以用一个嵌套的三元数替换所有内容,而无需使用括号。我的版本是144个字符现在:gist.github.com/473289
霍布斯

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

输出:

九十九是十。
十是三。
三是五。
五是四。
四是魔术。

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

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

固定。它也缩短了时间。
Mike DeSimone 2010年

做得很好。(我对20个字符的std难题大笑!)
Platinum Azure

是的,那确实是个危险,直到我意识到这#define可能会更短,因为它可以替换多个令牌。
Mike DeSimone 2010年

printf("is magic".\n)=> putsprintf("%d",p)=> puts(atoi(p))。不仅更短,而且更快。
Ben Voigt 2010年

2
@Mike DeSimone:我认为while(p!=4)可以缩短为while(p-4)。我知道整个角色,但仍然如此。:-)
白金Azure

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


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 "magic"
  • 创建了一个临时变量o,因此我可以将break外部for循环,即导致do-while
  • 内联o分配以及v分配,继续将l函数的计算完全插入函数自变量中,从而消除了对l。还内联了的分配m
  • 删除了一个空格 int[] xint[]x是合法的了。
  • 试图将数组转换为字符串转换,但是这样using System.Linq做不足以进行改进。

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


是的,它比Java版本短。
Dykam,2010年

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

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可以节省更多,从而节省了净额。


2

Perl, 123122个字符

刚刚意识到不需要输出到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/

1

蟒蛇:

#!/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"

4
我喜欢。您可能会收紧它。
乔什·K

@Vlad:应该从标准输入而不是参数中读取输入。这意味着您可以只使用N = input()(或raw_input())并消除这些sys东西。
kennytm 2010年

另外,您可以使Smalls包括十几岁的孩子,那么if语句将仅为“如果n <20:return Smalls [n]”。小件,仍然由10为> = 20的情况下工作,这是因为模量
乔恩工作服

5
这一定是我第一次she-bang在代码高尔夫球答案中看到(完全可选);-)
ChristopheD 2010年

看起来是个不错的开始……绝对可以收紧它,即使Python也不需要所有这些空格。:-)而且,正如Ferruccio指出的那样,0不起作用,特别是它似乎陷入了无限循环。
白金Azure

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

我认为,如果您认为这是C,则可以避免使用,#include因为这些功能仅假定采用int参数。您甚至可以通过main返回来保存笔画int
加布

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

好的Ruby解决方案,保持简单。:
白金Azure

不过,保持简单绝不是让它过长的借口;-)
Joey

我想你可以替换“如果n == 0”与“如果n!”
文森特

2
在Ruby中?我一直认为除false和nil之外的所有值都评估为true :-(
Platinum Azure

1

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

需要一个n=io.read()(+11个字符)以符合从标准输入中读取数字的规则。更改print('4 is magic.')print'4 is magic.'将节省2个字符。删除;后将)节省1个字符。在print使用逗号似乎是欺骗,但规格还不清楚。最好将其更改print(n,'is',m,'.')为节省2个字符。
gwell 2010年

在Lua中逗号是否作为换行符单独显示?自从我使用它已经有一段时间了。
尼克·范布伦特

逗号呈现为选项卡。
gwell

0

邮递区号

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

4
@wallacoloo:一种针对粗俗语言的粗俗解决方案:D
Thomas Eding

5
或更短的178个字符:$l='4335443554366887798866555766';for($b=(int)fgets(fopen('php://stdin','r'));($a=$b)-4;){$b=$a<20?$l[$a]:$l[18+$a/10]+($a%10?$l[$a%10]:0);echo"$a is $b.\n";}echo"4 is magic.\n";
gnarf

不错的笑话。:-D编程很好。
汤姆·帕索里克(TomPažourek),2010年

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-恢复了注意的变化,但是($_%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白金Azure


摆脱$_%10&&...构造后,您破坏了输入20,30,40,...的规范
暴民

+1做得好。您虽然已脱离标准输入(stdin)进入了args :-(
白金Azure

右,用替换为ARGV,它由STDIN:)或.. 代替,echo bar | xargs perl foo.pl从技术上讲是从echo 通过管道
传递

0

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

直接从P Daddy的C代码改编而来,并进行了一些调整,p()使其使用Perl原语(而不是C语言)和一个主要重写的mainloop来执行相同的操作。请参阅他的解释。换行符都是可选的。

@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招。


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}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.