Code Golf: Vier ist Magie

88

Das Puzzle

Ein kleines Rätsel, das ich während meiner Schulzeit gehört habe, ging ungefähr so ​​...

  • Der Fragesteller würde mich bitten, ihm eine Nummer zu geben;
  • Wenn der Fragesteller die Zahl hört, führt er wiederholt eine Art Transformation durch (zum Beispiel könnte er sagen, zehn ist drei ), bis er schließlich die Zahl 4 erreicht (an diesem Punkt würde er mit vier abschließen, ist magisch ).
  • Jede Zahl scheint schließlich in vier umwandelbar zu sein, egal was passiert.

Ziel war es, die Transformationsfunktion herauszufinden und dieses Rätsel dann selbst zuverlässig zu lösen.

Die Lösung

Die Transformationsfunktion bei jedem Schritt war zu

  • Nehmen Sie die betreffende Nummer,
  • Zählen Sie die Anzahl der Buchstaben in der englischen Wortdarstellung, ignorieren Sie einen Bindestrich oder Leerzeichen oder "und" (z. B. "zehn" enthält 3 Buchstaben, "vierunddreißig" enthält 10 Buchstaben, "einhundertdreiundvierzig"). enthält 20 Buchstaben).
  • Geben Sie diese Anzahl von Buchstaben zurück.

Für alle Zahlen, die ich jemals testen wollte, konvergiert dies gegen 4. Da "vier" auch vier Buchstaben enthält, würde es hier eine Endlosschleife geben; Stattdessen wird es lediglich konventionell als Magie bezeichnet , um die Sequenz zu beenden.

Die Herausforderung

Ihre Herausforderung besteht darin, einen Code zu erstellen, der eine Zahl vom Benutzer liest und dann Zeilen druckt, in denen die Transformationsfunktion wiederholt angewendet wird, bis "Vier ist Magie" erreicht ist.

Speziell:

  1. Lösungen müssen vollständige Programme an und für sich sein. Sie können nicht nur Funktionen sein, die einen Zahlenfaktor in der Eingabe berücksichtigen.
  2. Die Eingabe muss von der Standardeingabe gelesen werden. (Piping von "Echo" oder die Verwendung der Eingangsumleitung ist in Ordnung, da dies auch von stdin geht)
  3. Die Eingabe sollte in numerischer Form erfolgen.
  4. Für jede Anwendung der Transformationsfunktion sollte eine Zeile gedruckt werden: a is b.wobei a und b numerische Formen der Zahlen in der Transformation sind.
  5. Punkte (Perioden) sind erforderlich!
  6. Die letzte Zeile sollte natürlich sagen , 4 is magic..
  7. Der Code sollte für alle Zahlen von 0 bis 99 eine korrekte Ausgabe erzeugen .

Beispiele:

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

Der Gewinner ist die kürzeste Einsendung nach Anzahl der Quellcodezeichen, was ebenfalls korrekt ist .

BONUS

Sie können auch versuchen, bei jeder Anwendung der Transformationsfunktion eine Version des Codes zu schreiben, die die ENGLISCHEN NAMEN für die Zahlen ausgibt. Die ursprüngliche Eingabe ist immer noch numerisch, aber die Ausgabezeilen sollten die Wortform der Zahl haben.

(Doppelter Bonus für das Zeichnen von Formen mit Ihrem Code)

(EDIT) Einige Klarstellungen:

  1. Ich möchte, dass das Wort in allen zutreffenden Fällen auf beiden Seiten erscheint, z Nine is four. Four is magic.
  2. Die Kapitalisierung ist mir jedoch egal. Und es ist mir egal, wie Sie die Wort-Token trennen, obwohl sie getrennt werden sollten: ninety-nineist in Ordnung, ninety nineist in Ordnung, ninetynineist nicht in Ordnung.

Ich betrachte diese Kategorie als separate Kategorie für den Bonuswettbewerb in Bezug auf die Herausforderung. Wenn Sie sich also dafür entscheiden, machen Sie sich keine Sorgen, dass Ihr Code länger als die numerische Version ist.

Sie können gerne eine Lösung für jede Version einreichen.

Platinum Azure
quelle
1
Wie hoch sollten wir mit einer Zahl umgehen? <100? <1000? <1000000? <2 ** 31?
P Daddy
1
Da dies nur von 0 auf 99 gehen muss, besteht eine schnelle und schnelle Lösung darin, die Werte, denen 0-99 zugeordnet ist, fest zu codieren und dann eine Schleife zu erstellen, bis Sie 4 erreichen. Danach beginnt die Mikroschwächung.
Beska
@P Daddy ... Teil 6 sagt nur 0-99.
Beska
14
4 ist nur Magie, weil es durch einen fairen Würfelwurf ausgewählt wurde.
VirtuosiMedia

Antworten:

57

GolfScript - 101 96 93 92 91 90 94 86 Bytes

90 → 94: Feste Ausgabe für Vielfache von 10 .
94 → 86: Umstrukturierter Code. Verwenden der Basis 100 zum Entfernen nicht druckbarer Zeichen.
86 → 85: Kürzere Besetzung der Saite.

{n+~."+#,#6$DWOXB79Bd")base`1/10/~{~2${~1$+}%(;+~}%++=" is "\".
"1$4$4-}do;;;"magic."
Nabb
quelle
Warum ist das so weit unten? Es ist kürzer als das Lisp und verwendet keine eingebaute Formatierungsfunktion
Claudiu
36
Mir gefällt, wie der Code endet "magic.", er fasst es ziemlich gut zusammen.
Aistina
@Aistina: Das ist bei dieser Herausforderung einfach, denke ich. :-)
Platinum Azure
9
@Aistina: haha, das ist irgendwie lustig. "mumbo jumbo yada yada..magic"
vol7ron
1
@P Daddy Das dwird vom )as extrahiert 100und als Radix für die Basisumwandlung verwendet.
Nabb
85

Perl, ungefähr 147 char

Locker basierend auf der Lösung von 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
Mob
quelle
1
@Platinum Azure Die Eingabe erfolgt über die Verwendung von popohne Argumente. Außerhalb eines Unterprogramms wird popentfernt und der letzte Wert, der @ARGVdie Liste der Argumente ist, an das Perl-Programm zurückgegeben. Es könnte genauso gut durch ersetzt werden shift, aber das fügt weitere 2 Zeichen hinzu. Siehe: p3rl.org/pop
Brad Gilbert
es sieht so aus, als ob Sie ein Zeilenumbruchzeichen benötigen '.', das 2 für \noder 1 ist, wenn Sie Leerzeichen im '. '(Leerzeichen ist das Zeilenumbruchliteral) zählen
vol7ron
Ein bisschen länger, aber Kreativität spielt in meinem Buch eine große Rolle.
Beska
@Platinum Azure et al.: Er erhält seinen Input von stdin. So geht das in Perl. (Vielleicht hat er es nach Ihrem Kommentar geändert?)
Frank
@P Papa: stöhnen aber +1 auf deinen Kommentar sowieso
Platinum Azure
30

Common Lisp 157 Zeichen

Neue konformere Version, die jetzt Formulareingaben liest und Leerzeichen und Bindestriche ignoriert:

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

In lesbarer Form:

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

Und einige Testläufe:

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

Und die Bonusversion mit 165 Zeichen:

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

Geben

>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.
user110763
quelle
5
Ich dachte "vierundzwanzig" hat nur 10 Buchstaben?
Kennytm
1
Die Zahlen nach "is" sollten ebenfalls Text sein.
Mike DeSimone
5
Warum ist das so hoch oben? andere verwenden keine eingebaute Formatfunktion und sie sind weniger Zeichen
Claudiu
3
@Claudiu Weil Common Lisp großartig ist.
Mornedhel
3
Es spielt keine Rolle, wie viele Schläge Sie ausführen, wenn Sie den Ball nicht ins Loch bekommen. Die Leute scheinen das zu vergessen, wenn sie falsche Lösungen befürworten.
Mark Peters
21

Python 2.x, 144 150 154 166 Zeichen

Dies trennt die Zahl in Zehner und Einsen und fasst sie zusammen. Die unerwünschte Eigenschaft des pseudo-ternären Operators a and b or c, cdie zurückgegeben wird, wenn b0 ist, wird hier missbraucht.

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

Die vorherige naive Version (150 Zeichen). Codieren Sie einfach alle Längen als Ganzzahl.

n=input()
while n-4:p=3+int('1yrof7i9b1lsi207bozyzg2m7sclycst0zsczde5oks6zt8pedmnup5omwfx56b29',36)/10**n%10;print n,"is %d."%p;n=p
print"4 is magic."
KennyTM
quelle
Entschuldigung, ich wollte speziell wegen solcher Dinge einen Punkt. :-) Guter Einstieg! (EDIT: Ich kenne Python nicht, aber könnten Sie n,"is",p,"."? Ich denke, Sie speichern noch einige Zeichen, wenn ich richtig zähle)
Platinum Azure
2
@Plat: Das würde einen zusätzlichen Platz vor dem ..
Kennytm
@KennyTM: Oh, duh, ich hätte das sogar aus dem Ausschnitt heraus bemerken sollen. Hoppla! Wie ich bereits sagte, wurden einige der Spezifikationen speziell entwickelt, um die Dinge ein wenig zu komplizieren. :-)
Platinum Azure
Können wir dies verkürzen, indem wir eine höhere Basis als 36 verwenden?
MikeD
@ MikeD: Nein. Aus den Python - Dokumentation: „Der Basisparameter gibt die Basis für die Umwandlung (die 10 ist standardmäßig) und eine beliebige ganze Zahl im Bereich sein kann , [2, 36], oder Null.“ Jetzt haben Sie vielleicht als eine andere Funktion nutzen zu können int(), sagt etwas aus der structoder base64Module ...
Mike DeSimone
20

C - mit Zahlenwörtern

445 431 427 421 399 386 371 359 * 356 354 348 347 Zeichen

Das ist es. Ich glaube nicht, dass ich das kürzer machen kann.

Alle Zeilenumbrüche dienen der Lesbarkeit und können entfernt werden:

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

Unten ist es etwas unminimiert, aber immer noch ziemlich schwer zu lesen. Weiter unten finden Sie eine besser lesbare Version.

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

Erweitert und kommentiert:

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

Über die codierte Zeichenfolge am Anfang

Die Namen der Zahlen werden nach einem sehr einfachen Schema komprimiert. Häufig verwendete Teilzeichenfolgen werden durch einstellige Indizes im Namensarray ersetzt. Eine "Nachschlagetabelle" mit zusätzlichen Namenseinträgen wird am Ende für Teilzeichenfolgen hinzugefügt, die im ersten Satz nicht vollständig verwendet wurden. Suchvorgänge sind rekursiv: Einträge können auf andere Einträge verweisen.

Der komprimierte Name für 11 lautet beispielsweise elM. Die print()Funktion gibt die Zeichen eund l(Kleinbuchstaben 'L', nicht Nummer '1') wörtlich aus, findet dann aber die Mund ruft sich selbst mit dem Index des 29. Eintrags auf (ASCII 'M' - ASCII '0'). in die Nachschlagetabelle. Diese Zeichenfolge wird evLalso ausgegeben eund vruft sich dann erneut mit dem Index des 28. Eintrags in der Nachschlagetabelle auf, der enwörtlich ausgegeben wird. Dies ist nützlich , weil enauch in verwendet wird , eLfür een(verwendet nach eightin eighteen), die verwendet wird , tOfür teen(verwendet für jeden anderen -teenNamen).

Dieses Schema führt zu einer ziemlich signifikanten Komprimierung der Nummernnamen, während zum Dekomprimieren nur eine geringe Menge Code erforderlich ist.

Die Kommas am Anfang und Ende der Zeichenfolge berücksichtigen die vereinfachte Art und Weise, wie Teilzeichenfolgen in dieser Zeichenfolge gefunden werden. Wenn Sie hier zwei Zeichen hinzufügen, werden später weitere Zeichen gespeichert.

Über den Missbrauch von main()

argvWird ignoriert (und daher in der komprimierten Version nicht deklariert), wird der Wert von argc ignoriert, aber der Speicher wird wiederverwendet, um die aktuelle Nummer zu speichern. Dies erspart mir nur die Deklaration einer zusätzlichen Variablen.

Über den Mangel an #include

Einige werden sich beschweren, dass das Weglassen #include <stdio.h>Betrug ist. Es ist überhaupt nicht. Das angegebene ist ein völlig legales C-Programm, das auf jedem mir bekannten C-Compiler korrekt kompiliert wird (allerdings mit Warnungen). Da keine Prototypen für die stdio-Funktionen vorhanden sind, geht der Compiler davon aus, dass es sich um zurückgegebene cdecl-Funktionen handelt int, und vertraut darauf, dass Sie wissen, welche Argumente übergeben werden müssen. Die Rückgabewerte werden in diesem Programm sowieso ignoriert und sind alle cdecl-Funktionen ("C" -Aufrufkonvention), und wir wissen tatsächlich, welche Argumente übergeben werden müssen.

Ausgabe

Die Ausgabe erfolgt wie erwartet:

0
Null ist vier.
Vier ist Magie.
1
eins ist drei.
drei ist fünf.
fünf ist vier.
Vier ist Magie.
4
Vier ist Magie.
20
zwanzig ist sechs.
sechs ist drei.
drei ist fünf.
fünf ist vier.
Vier ist Magie.
21
einundzwanzig ist neun.
neun ist vier.
Vier ist Magie.

* Die vorherige Version hat die Markierung in zwei Teilen der Spezifikation verfehlt: Sie hat keine Null verarbeitet und statt stdin Eingaben über die Befehlszeile vorgenommen. Durch die Behandlung von Nullen wurden Zeichen hinzugefügt, aber durch die Verwendung von stdin anstelle von Befehlszeilenargumenten sowie einiger anderer Optimierungen wurde die gleiche Anzahl von Zeichen gespeichert, was zu einer Wäsche führte.

Die Anforderungen wurden geändert, um zu verdeutlichen, dass das Zahlenwort auf beiden Seiten von "ist" gedruckt werden sollte. Diese neue Version erfüllt diese Anforderung und implementiert einige weitere Optimierungen, um die erforderliche zusätzliche Größe (mehr als) zu berücksichtigen.

P Papa
quelle
Dies ist leicht mein Favorit der Wortantworten ... Bravo, gut gemacht. +1 für Sie, und wenn ich zwei Häkchen setzen könnte, würde ich.
Platinum Azure
5
Es macht Spaß zu lesen, ich denke, ich werde diese Zahlen von nun an im täglichen Leben verwenden. Sechs, Sem, Acht, Neun, Tel, Elem, Zwölf, Enpee, Fourpee, Fifpee, Sixpee, Sevenpee, Eightoh, Ninepee, Twelkyu ... =)
Täuschung
10

J, 107 112 Zeichen

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

(Newline nur zur besseren Lesbarkeit)

Verwendung und Ausgabe:

    '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. 
David
quelle
15
Es ist in Chinesisch zusammengestellt
Dr. belisarius
3
Bitte wählen Sie einen nicht-chinesischen Schiedsrichter
Dr. belisarius
3
@beli: 멩, 겻, 곋, 멩 sind Koreaner.
Kennytm
1
Meine Frau (eine chinesische Muttersprachlerin) sagt, es sei eine Mischung aus Chinesisch und Koreanisch.
Loren Pechtel
3
@ Belisarius: 1) Sie kann kein Koreanisch. 2) Der Chinese ist Kauderwelsch.
Loren Pechtel
10

T-SQL, 413 451 499 Zeichen

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

(Nicht, dass ich ernsthaft vorschlage, dass Sie dies tun würden ... eigentlich wollte ich nur einen CTE schreiben)

Benutzen:

M 95

Kehrt zurück

p                n
----------- ---- -----------
95          is   10.
10          is   3.
3           is   5.
5           is   4.
4 is magic.
Leon Bambrick
quelle
Können Sie nicht einfach die einzelnen Ergebnisse drucken, anstatt eine Tabelle zurückzugeben? Das würde die Ausgabe schöner aussehen lassen.
Joey
1
Ich denke nicht, dass es richtig mit Null umgeht. Wie wäre es mit so etwas: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
9

Java (mit Boilerplate), 308 290 286 282 280 Zeichen

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

Ich bin sicher, Groovy würde viel davon loswerden.

Erläuterung und Formatierung (alle Kommentare, Zeilenumbrüche und führenden / nachfolgenden Leerzeichen wurden in der Anzahl entfernt):

Ziemlich einfach, aber

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

Bearbeiten: Verwenden Sie kein Hex mehr, dies sind weniger Tastenanschläge

Mark Peters
quelle
1
249 ohne Importe, Klasse def oder Hauptdef.
Mark Peters
1
Das ist teuflisch. Ich mag die Basis 16. (+1)
Platinum Azure
Sie können einen Platz sparen, indem Sie String[]aanstelle von verwenden String[] a.
BalusC
Vielen Dank an @Balus, der auch eine Menge eliminiert hat, indem er das Zeichen einfach rechnet, anstatt Hex-Parsing zu verwenden.
Mark Peters
@ Mark Peters: Noch böser. Ich fühle mich im Vergleich dazu so vanillig.
Platinum Azure
9

Windows PowerShell: 152 153 184 Byte

basierend auf der vorherigen Lösung, mit mehr Einfluss von anderen Lösungen

$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.'
.οеу
quelle
Behoben, um Vielfache von 10 zu unterstützen ("neunzig" statt "neunzig Null").
Gabe
Hey @Gabe :), danke; Ich hatte in letzter Zeit nicht viel Zeit zum Golfen. Die Anführungszeichen $inputmüssen jedoch erhalten bleiben, da Sie einen Enumerator nicht direkt aufrufen können int. es funktioniert, wenn man stringzuerst durchgeht :-)
Joey
8

C, 158 Zeichen

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

(Ursprünglich basierend auf Vlads Python-Code, hat er sich einen Trick aus Tom Sirgedas 'C ++ - Lösung geliehen, um ein paar weitere Zeichen herauszuquetschen.)

erweiterte Version:

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.");
}
Ferruccio
quelle
Scheint bei mir nicht zu funktionieren: ./magic 10 10 ist -27. Segmentierungsfehler
Casey
@Casey - der Aufruf von scanf () war etwas lückenhaft. Es las ein int in einen char. Ich kam unter OSX damit durch und unter Windows funktionierte es, stürzte aber beim Beenden ab. Also habe ich wieder n & c Ints gemacht. Ich erkannte, dass ich das Schlüsselwort int löschen konnte, indem ich sie mit der K & R-Notation zu Parametern machte. Das Ergebnis ist sicherer und ein Zeichen kürzer.
Ferruccio
Sie können 3 Zeichen speichern, indem Sie " 466555766" [n / 10] + d [n% 10] -96 durch d [n% 10] - " , +++) " [n / 10]
Tom Sirgedas
6

Python, 129 133 137 148 Zeichen

Zum Aufwärmen ist hier meine erste Version (verbessert einige Zeichen gegenüber dem vorherigen besten Python).

PS. Nach ein paar Redaktionen ist es jetzt ungefähr zwanzig Zeichen kürzer:

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.'
Nas Banov
quelle
6

C #: 210 Zeichen.

Gequetscht:

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

Erweitert:

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

Tricks, die dieser Ansatz verwendet:

  • Erstellen Sie eine Nachschlagetabelle für Nummernnamenlängen basierend auf den in der Nummer angezeigten Ziffern.
  • Verwenden Sie die Zeichenarray-Suche für eine Zeichenfolge und die Zeichenarithmetik anstelle eines numerischen Arrays.
  • Verwenden Sie Aliasing für Klassennamen, um einen Kurzschluss Console.zu erstellenC.
  • Verwenden Sie den bedingten (ternären) Operator ( ?:) anstelle von if/else.
  • Verwenden Sie die \nmit WriteEscape - Code stattWriteLine
  • Verwenden Sie die Tatsache, dass C # eine definierte Auswertungsreihenfolge hat, um Zuweisungen innerhalb des WriteFunktionsaufrufs zu ermöglichen
  • Verwenden Sie die Zuweisungsausdrücke, um zusätzliche Anweisungen und damit zusätzliche Klammern zu entfernen
LBushkin
quelle
int[] zwäre kürzer, da es das nicht brauchtnew[]
Joey
Überarbeitet, um Zeichenarithmetik anstelle der Array-Suche zu verwenden.
LBushkin
@ mdm20: Du hast recht. Ich hatte einen Fehler in der Nachschlagetabelle. Jetzt behoben.
LBushkin
Nun, das zwölfte Mal ist der Reiz: * D
LBushkin
Ein Quicky 5 Zeichen zu speichern: Shorter als Gießen "magic"zu object, wäre implizit rufen ToString()auf ydurch Zugabe "". Aber weil es +eine höhere Priorität hat als ?:, müssen Sie es in den wahren Teil anstatt in den falschen Teil setzen : x!=4?y+"":"magic".
P Daddy
6

Perl: 148 Zeichen

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

  • Ausnahme-Hash in Unit-Array verschoben. Dies führte dazu, dass ich viele Charaktere schneiden konnte :-)
  • Mobrule wies auf einen bösen Fehler hin. Die Schnellkorrektur fügt 31 Zeichen hinzu, autsch!
  • Überarbeitet für Null-Sonderfälle, auch mildes Golfen.
  • Direkter Listenzugriff zur einmaligen Verwendung anstatt zum Speichern in einem Array? Auf jedenfall!
  • SO VIEL REFACTORING für nur EINEN blutigen Charakter. Dies ist wirklich das Leben eines Golfspielers. :-(
  • Ups, einfache Whitespace-Korrektur. 198 jetzt.
  • Überarbeiteter redundanter Code.
  • Das letzte Schlüsselwort für die Rückgabe rist nicht erforderlich.
  • Massives Refactoring pro Kommentar; Leider konnte ich es nur auf 149 bringen, weil ich einen Fehler beheben musste, der sowohl in meinem früheren Code als auch in den Versionen der Kommentatoren vorhanden war.
  • Bareword "Magie" versuchen.

Lassen Sie uns diesen Ball mit einem bescheidenen Versuch in Perl ins Rollen bringen.

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

Tricks:

Zu viele!

Platinum Azure
quelle
ACK! Wie ich nie getestet habe, werde ich nie erfahren.
Platinum Azure
Haben Sie dort einen toten Code? Ich sehe nicht, wie der Sonderfall für Null notwendig ist, wenn $ u [0] 4 ist. Ich habe eine scheinbar funktionierende Version Ihres Codes mit 166 Zeichen, und ich denke, es hat Raum, etwas kürzer zu werden.
Hobbs
@hobbs: Guter Punkt, ich werde noch einmal schauen. Die Geschichte ist, dass ich nach der Hälfte einiger Revisionen die Dinge kaputt gemacht habe (ungefähr an dem Punkt, an dem ich 4 -> 0 gewählt habe). Ich denke, Sie haben an diesem Punkt Recht :-)
Platinum Azure
Ich betrachte mich nicht als großartigen Perl-Programmierer, aber Sie können einige Zeichen reduzieren: @u=split$x,'43350435543668877988';Ihre Kommas verwenden unnötige 19 Zeichen, die undefbei jedem Zeichen auf Teilungen aufgeteilt werden. Ich verwende sie $xals undefinierte Variable, um "undef" - total zu ersetzen Einsparungen: 11 Zeichen. Wenn Sie das mIn entfernen chomp, wird ein weiterer Charakter von Ihrer Punktzahl abgezogen.
Vol7ron
Besser machen, aber Sie können immer noch mehr sparen, indem Sie sub rganz verlieren - Sie verwenden es nur einmal und können alles durch ein einziges verschachteltes Ternär ohne Parens ersetzen. Meine Version ist derzeit
hobbs
5

JavaScript 1.8 (SpiderMonkey) - 153 Zeichen

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

Verwendung: echo 42 | js golf.js

Ausgabe:

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

Mit Bonus - 364 Zeichen

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

Ausgabe:

neunundneunzig ist zehn.
zehn ist drei.
drei ist fünf.
fünf ist vier.
Vier ist Magie.
Gnarf
quelle
4

Haskell, 224 270 Zeichen

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

Und wenig lesbarer -

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
Matajon
quelle
4

C ++ Stdio-Version, minimiert: 196 Zeichen

#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-Version, minimiert: 195 Zeichen

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

Original, nicht verkleinert: 344 Zeichen

#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);
}
Karl von Moor
quelle
Fest. Es machte es auch ein bisschen kürzer.
Mike DeSimone
Schön gemacht. (Ich habe viel über das 20-stellige Standard-Rätsel gelacht!)
Platinum Azure
Ja, das war ein echter Headbanger, bis mir klar wurde, dass #definedas noch kürzer sein würde, da es mehrere Token ersetzen könnte.
Mike DeSimone
printf("is magic".\n)=> puts. printf("%d",p)=> puts(atoi(p)). Nicht nur kürzer, sondern auch schneller.
Ben Voigt
2
@ Mike DeSimone: Ich denke, while(p!=4)könnte verkürzt werden auf while(p-4). Ein ganzer Charakter, ich weiß, aber immer noch. :-)
Platinum Azure
3

Delphi: 329 Zeichen

Einzeilige Version:

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.

Formiert:

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.

Wahrscheinlich Platz für etwas mehr Quetschen ... :-P

Jørn E. Angeltveit
quelle
3

C # 314 286 283 274 289 273 252 Zeichen.

Gequetscht:

252 

Normal:

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

Edit Dykam: Hat einige sorgfältige Einfügungen und Änderungen vorgenommen:

  • Der l.ToString () wurde in einen Cast objectvon geändert string "magic".
  • Erstellt eine temporäre Variable o, damit ich breakdie forSchleife außerhalb verschieben kann , was zu einer führt do-while.
  • Inline die oZuweisung sowie die vZuweisung, wobei weiterhin die Berechnung der lArgumente in die Funktionsargumente insgesamt eingefügt wird , wodurch die Notwendigkeit für l. Auch die Zuordnung von m.
  • Ein Leerzeichen entfernt int[] x, int[]xist auch legitim.
  • Es wurde versucht, das Array in eine Zeichenfolgentransformation umzuwandeln, aber das using System.Linqwar zu viel, um dies zu einer Verbesserung zu machen.

Bearbeiten 2 Dykam Das int-Array wurde in ein char-Array / einen char-String geändert und die richtigen Arithmetiken hinzugefügt, um dies zu korrigieren.

mdm20
quelle
Ja, habe es kürzer als die Java-Version.
Dykam
3

Lua, 176 Zeichen

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

oder

  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."
gut
quelle
3

C - ohne Zahlenwörter

180 175 * 172 167 Zeichen

Alle Zeilenumbrüche dienen der Lesbarkeit und können entfernt werden:

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

Etwas unminimiert:

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

* Die vorherige Version hat die Markierung in zwei Teilen der Spezifikation verfehlt: Sie hat keine Null verarbeitet und statt stdin Eingaben über die Befehlszeile vorgenommen. Der Umgang mit null hinzugefügten Zeichen, aber die Verwendung von stdin anstelle von Befehlszeilenargumenten spart noch mehr, was zu einer Nettoeinsparung führt.

P Papa
quelle
2

Perl, 123 122 Zeichen

Ich habe gerade festgestellt, dass es nicht erforderlich ist, in STDOUT auszugeben. Geben Sie stattdessen in STDERR aus und deaktivieren Sie ein anderes Zeichen.

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

Und eine Version, die buchstabierte Zahlen zurückgibt:

279 278 276 280 Zeichen

@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/

Dies entspricht zwar der Spezifikation, ist jedoch nicht zu 100% gut formatiert. Nach Zahlen, die mit Null enden, wird ein zusätzliches Leerzeichen zurückgegeben. Die Spezifikation sagt:

"Es ist mir egal, wie du die Wortmarken trennst, obwohl sie getrennt werden sollten."

Das ist allerdings irgendwie wieselhaft. Eine korrektere Version bei

282 281 279 283 Zeichen

@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/
user397369
quelle
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"
Vlad
quelle
4
Ich mag das. Sie könnten es aber wahrscheinlich etwas enger machen.
Josh K
@Vlad: Die Eingabe sollte aus stdin statt aus den Argumenten gelesen werden. Das heißt, Sie könnten das Zeug einfach benutzen N = input()(oder raw_input()) und eliminieren sys.
Kennytm
Sie könnten auch machen, dass kleine Teenager enthalten, dann wäre die if-Anweisung nur "wenn n <20: return Smalls [n]". Smalls würde wegen des Moduls von 10 immer noch für den Fall> = 20 funktionieren.
Jon Smock
5
Dies muss das erste Mal sein, dass ich das (völlig optional) she-bangin einer Code-Golf-Antwort sehe ;-)
ChristopheD
Sieht nach einem guten Start aus ... Ziehen Sie es auf jeden Fall fester an, selbst Python benötigt nicht ALLE diese Leerzeichen. :-) Wie Ferruccio betont, funktioniert 0 nicht, insbesondere scheint es in eine Endlosschleife zu gehen.
Platinum Azure
1

C ++, 171 Zeichen (#include weggelassen)

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.");}
Tom Sirgedas
quelle
Ich denke, wenn Sie dies als C betrachten, können Sie die Notwendigkeit für das vermeiden, #includeda angenommen wird, dass die Funktionen nur intParameter annehmen . Sie können sogar einen Schlaganfall speichern, indem Sie mainzurückkehren int.
Gabe
1

Ruby, 164 Zeichen

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

entschlüsselt:

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."
Jon Smock
quelle
Schöne Ruby-Lösung, die es einfach hält. :-) (+1)
Platinum Azure
Es einfach zu halten ist keine Entschuldigung dafür, es zu lange zu halten ;-)
Joey
Ich denke, Sie können 'if n == 0' durch 'if! N' ersetzen
Vincent
2
In Ruby? Ich habe immer gedacht, dass alle Werte außer false und nil als true ausgewertet werden :-(
Platinum Azure
1

Lua 185 190 199

Perioden hinzugefügt, io.read hinzugefügt, () beim letzten Druck entfernt

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

mit Zeilenumbrüchen

 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.'
Nick
quelle
Benötigt ein n=io.read()(+11 Zeichen), um die Regel zum Lesen der Nummer von der Standardeingabe zu erfüllen. Wenn Sie print('4 is magic.')zu ändern , print'4 is magic.'werden 2 Zeichen gespeichert. Durch Entfernen ;nach )wird 1 Zeichen gespeichert. Die printVerwendung von Kommas scheint zu schummeln, aber die Spezifikation ist unklar. Könnte es auch ändern print(n,'is',m,'.'), um 2 Zeichen zu sparen.
Gwell
Werden Kommas als Zeilenumbrüche in Lua eigenständig gerendert? Es ist schon eine Weile her, seit ich es benutzt habe.
Nick Van Brunt
Die Kommas werden als Tabulatoren gerendert.
Gwell
0

PHP-Code

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

//////////// testen ////////////////

 $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';
    }

////// Ergebnisse /////////

Twelve =6
Six =3
Three =5
Five =4
four is magic
Entwickler
quelle
4
@wallacoloo: Eine miese Lösung für eine miese Sprache: D
Thomas Eding
5
Oder viel kürzere 178 Zeichen:$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
Guter Witz. :-D So gut programmiert.
Tom Pažourek
0

Perl - 130 Zeichen


5.12.1 (130 Zeichen) 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 Zeichen) 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/


Geschichte verändern:

20100714:2223- Änderung auf Aufmerksamkeit von Mobrule zurückgesetzt , aber ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]), das ist die gleiche Anzahl von Zeichen, aber ich habe es getan, falls jemand einen Weg sehen könnte, es zu verbessern

20100714:0041- split//,'...''...'=~/./g
20100714:0025- ($_%10&&$u[$_%10])$u[$_%10]
20100713:2340- while$_until/\D/+ unnötige Klammern entfernt
20100713:xxxx- $=<>;chop;$_=pop;- mit freundlicher Genehmigung von mobrule


Hinweis: Ich war es leid, die Antworten anderer in Kommentaren zu verbessern, daher bin ich jetzt gierig und kann hier nur meine Änderungen hinzufügen :) Dies ist eine Abspaltung von Platinum Azures Antwort - zum Teil Hobbs , Mobrule und Platinum Azure .

vol7ron
quelle
Als Sie das $_%10&&...Konstrukt losgeworden sind , haben Sie die Spezifikation für Eingaben 20,30,40, ...
Mob
+1 Gut gemacht. Sie haben sich jedoch nicht mehr mit Argumenten befasst :-(
Platinum Azure
Richtig, ersetzt durch ARGV, STDINecho bar | xargs perl foo.pl
gefüllt
0

Schamloses Perl mit Zahlenwörtern (329 Zeichen)

Ziemlich direkt aus dem C-Code von P Daddy angepasst, mit einigen Verbesserungen, p()um das Gleiche mit Perl-Primitiven anstelle von C-Primitiven und einem meist neu geschriebenen Mainloop zu erreichen. Siehe seine für eine Erklärung. Zeilenumbrüche sind alle optional.

@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

Randnotiz: Es ist schade, dass Perl printnur true / false zurückgibt. Wenn es eine Zählung zurückgeben würde, würde es mir 7 Schläge ersparen.

Hobbs
quelle
0

Ruby, 141 Zeichen:

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}
Krzysztof
quelle
-7
while(true)
{
    string a;
    ReadLine(a)
    WriteLine(4);

}
Benutzer368038
quelle