88

パズル

高校時代に聞いたちょっとしたパズルはこんな感じでした…

  • 質問者は私に番号を教えてくれるように頼むでしょう。
  • 数字を聞いた質問者は、最終的に数字の 4 にたどり着くまで(たとえば、 10 は 3と言うかもしれません)、何らかの変換を繰り返し行います(この時点で、彼は4 は魔法です)。
  • どんな数でも、最終的には 4 に変換できるようです。

目標は、変換関数を理解し、このパズルを自分で確実に監督できるようにすることでした。

ソリューション

任意のステップでの変換関数は、

  • 問題の番号を取って、
  • ハイフン、スペース、または「and」を無視して、英単語表現の文字数を数えます (たとえば、「ten」には 3 文字、「thirty-four」には 10 文字、「one43」) 20文字あります)。
  • その文字数を返します。

これまでテストしたすべての数について、これは 4 に収束します。「four」にも 4 つの文字が含まれているため、ここで無限ループが発生します。代わりに、慣例により、シーケンスを終了することは単に魔法と呼ばれます。

チャレンジ

あなたの課題は、ユーザーから数値を読み取り、「4 は魔法」に到達するまで繰り返し適用される変換関数を示す行を出力するコードを作成することです。

具体的には:

  1. ソリューションは、それ自体が完全なプログラムでなければなりません。それらは、単に数値を受け取る関数ではありません。入力の因数です。
  2. 入力は標準入力から読み取る必要があります。(「エコー」からのパイプまたは入力リダイレクトの使用は、標準入力からも送信されるため問題ありません)
  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.

勝者は、ソース コードの文字数が最も短い投稿で、これも正解です。

ボーナス

また、変換関数を適用するたびに数字の ENGLISH NAMES を出力するバージョンのコードを作成することもできます。元の入力は数値のままですが、出力行には数値の単語形式が必要です。

(コードで図形を描くとダブル ボーナス)

(編集)いくつかの説明:

  1. 該当するすべてのケースで、単語を両側に表示したい。Nine is four. Four is magic.
  2. ただし、大文字は気にしません。そして、単語トークンをどのように分離するかは気にしませんが、分離する必要があります。大丈夫です、大丈夫ですninety-nineninety nine大丈夫でninetynineはありません。

チャレンジに関しては、これらは別のカテゴリーのボーナス競争だと考えているので、これを選択する場合は、コードが数値バージョンよりも長くなる心配はありません。

バージョンごとに 1 つのソリューションを提出してください。

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: コードを再構築しました。基数 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

パイソン 2.x、144150 154 166文字

これは数を 10 と 1 に分けて合計します。is 0の場合に返されるa and b or c疑似三項演算子の望ましくない特性が、ここで悪用されています。cb

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

冒頭付近のエンコード文字列について

番号の名前は、非常に単純なスキームを使用して圧縮されます。頻繁に使用される部分文字列は、name 配列への 1 文字のインデックスに置き換えられます。最初のセットで完全に使用されていない部分文字列の最後に、追加の名前エントリの「ルックアップ テーブル」が追加されます。検索は再帰的です。エントリは他のエントリを参照できます。

たとえば、11 の圧縮名はelM. このprint()関数は、文字el(数字の '1' ではなく小文字の 'L') を逐語的に出力しますが、 を見つけるMので、29 番目のエントリのインデックス (ASCII 'M' - ASCII '0') でそれ自体を呼び出します。ルックアップ テーブルに。この文字列はevLであるため、 および を出力ev、ルックアップ テーブルの 28 番目のエントリのインデックス ( ) を使用して自分自身を再度呼び出し、enそのまま出力します。これはeneLfor (のeeneightに使用eighteen) で使用され、tOfor teen(他のすべての-teen名前に使用) で使用されるため、便利です。

このスキームにより、数字の名前がかなり大幅に圧縮されますが、解凍に必要なコードはわずかです。

文字列の先頭と末尾のコンマは、この文字列内で部分文字列を見つける簡単な方法を説明しています。ここに 2 文字を追加すると、後でさらに文字を節約できます。

の悪用についてmain()

argvが無視される (したがって圧縮バージョンでは宣言されない) 場合、argc の値は無視されますが、ストレージは現在の数値を保持するために再利用されます。これにより、余分な変数を宣言する必要がなくなります。

不足について#include

#include <stdio.h>省略することは不正行為であると不平を言う人もいます。それはまったくありません。与えられたのは、私が知っているすべての C コンパイラで正しくコンパイルされる完全に合法的な C プログラムです (警告はありますが)。stdio 関数のプロトタイプがないため、コンパイラはそれらが を返す cdecl 関数であると想定し、int渡すべき引数がわかっていることを信頼します。いずれにせよ、戻り値はこのプログラムでは無視され、それらはすべて cdecl ("C" 呼び出し規則) 関数であり、どの引数を渡すかは実際にわかっています。

出力

出力は期待どおりです。

0
ゼロは 4 です。
4は魔法です。
1
1は3です。
3 は 5 です。
5 は 4 です。
4は魔法です。
4
4は魔法です。
20
20 は 6 です。
6 は 3 です。
3 は 5 です。
5 は 4 です。
4は魔法です。
21
21 は 9 です。
9 は 4 です。
4は魔法です。

*以前のバージョンでは、仕様の 2 つの部分でマークがありませんでした: ゼロを処理しなかったことと、標準入力ではなくコマンド ラインで入力を受け取ったことです。ゼロを処理すると文字が追加されましたが、コマンド ライン引数の代わりに stdin を使用したり、他のいくつかの最適化によって同じ数の文字が保存され、ウォッシュが発生しました。

「 is 」の両側に数字を印刷する必要があることを明確にするために、要件が変更されました。この新しいバージョンはその要件を満たし、必要な余分なサイズを考慮して (それ以上の) いくつかの最適化を実装しています。

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

編集:16進数を使用しなくなりました。これにより、キーストロークが少なくなります

于 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

パール: 148 文字

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

  • 例外ハッシュをユニット配列に移動しました。これにより、多くの文字をカットできるようになりました:-)
  • mobrule は厄介なバグを指摘しました。クイックフィックスで 31 キャラクターが追加されます。
  • 特別なケースがゼロになるようにリファクタリングされ、マイルドなゴルフも行われました。
  • 配列に格納するのではなく、単一使用のための直接リストアクセス? もちろん!
  • たった1人の血まみれのキャラクターのための非常に多くのリファクタリング。これがまさにゴルファーの人生です。:-(
  • おっと、簡単な空白修正。現在198。
  • 冗長なコードをリファクタリングしました。
  • 最後の return キーワード inrは不要で、さらに削りました。
  • コメントごとの大規模なリファクタリング。残念ながら、以前のコードとコメント投稿者のバージョンの両方に存在するバグを修正する必要があったため、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)
                   );
    }
}

このアプローチが使用するトリック:

  • 番号に表示される数字に基づいて、番号名の長さのルックアップ テーブルを作成します。
  • 文字列に対して文字配列ルックアップを使用し、数値配列の代わりに char 演算を使用します。
  • クラス名のエイリアスを使用して短縮Console.するC.
  • ?:の代わりに条件 (三項) 演算子 ( ) を使用しif/elseます。
  • \nの代わりにwithWriteエスケープ コードを使用します。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.')

出力:

九十九は十です。
10 は 3 です。
3 は 5 です。
5 は 4 です。
4は魔法です。
于 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移動できました。つまり、 .breakfordo-while
  • o割り当てと同様に割り当てをインライン化して、関数の引数にvの計算を挿入し続け、lの必要性を取り除きましたl。の代入もインライン化しmます。
  • のスペースを削除したint[] xint[]x合法です。
  • 配列を文字列変換に変換しようとしましたが、using System.Linqこれを改善するには多すぎました。

編集 2 Dykam int 配列を char 配列/文字列に変更し、これを修正するために適切な演算を追加しました。

于 2010-07-12T21:39:30.433 に答える
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.");
}

*以前のバージョンでは、仕様の 2 つの部分でマークがありませんでした: ゼロを処理しなかったことと、標準入力ではなくコマンド ラインで入力を受け取ったことです。追加された文字をゼロで処理しますが、コマンド ライン引数の代わりに stdin を使用すると、さらに節約され、正味の節約になります。

于 2010-07-13T05:58:31.627 に答える
3

ルア、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 に答える
3

Delphi: 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 に答える
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

恥知らずな Perl with Number Words (329 文字)

C の代わりに Perl プリミティブを使用して同じことを行うようにいくつかの調整を加えて、P Daddy の C コードからかなり直接的に適応さp()せ、メインループをほとんど書き直しました。彼の説明を参照してください。改行はすべてオプションです。

@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 に答える
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

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 に答える
-7
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
于 2010-07-14T14:55:49.197 に答える