Frage

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;
  • Beim Hören der Zahl würde der Fragesteller wiederholt eine Art Transformation daran vornehmen (z. B. könnte er sagen zehn ist drei), bis er schließlich bei der Nummer 4 ankam (an diesem Punkt endete er mit Vier ist Magie).
  • Jede Zahl scheint irgendwann in vier umgewandelt werden zu können, egal was passiert.

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

Die Lösung

Die Transformationsfunktion war bei jedem Schritt zu

  • Nehmen Sie die betreffende Nummer,
  • Zählen Sie die Anzahl der Buchstaben in der englischen Wortdarstellung und ignorieren Sie dabei Bindestriche, Leerzeichen oder „und“ (z. B. „ten“ enthält drei Buchstaben, „thirty-four“ enthält zehn Buchstaben, „one hundert forty three“ enthält 20 Buchstaben).
  • Geben Sie diese Anzahl an Buchstaben zurück.

Für alle Zahlen, die ich jemals testen wollte, konvergiert dies gegen 4.Da „vier“ auch vier Buchstaben enthält, gäbe es hier eine Endlosschleife;Stattdessen wird es lediglich als bezeichnet Magie per Konvention, um die Sequenz zu beenden.

Die Herausforderung

Ihre Herausforderung besteht darin, einen Code zu erstellen, der eine Zahl vom Benutzer liest und dann Zeilen ausgibt, die zeigen, wie die Transformationsfunktion wiederholt angewendet wird, bis „vier ist magisch“ erreicht ist.

Speziell:

  1. Lösungen müssen vollständige Programme für sich sein.Es kann sich nicht einfach um Funktionen handeln, die einen Zahlenfaktor in die Eingabe aufnehmen.
  2. Die Eingabe muss von der Standardeingabe gelesen werden.(Das Weiterleiten von „echo“ oder die Verwendung der Eingabeumleitung ist in Ordnung, da dies auch von stdin aus erfolgt.)
  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 (Punkte) SIND erforderlich!
  6. Die letzte Zeile sollte natürlich lauten: 4 is magic..
  7. Der Code sollte für alle Zahlen von eine korrekte Ausgabe erzeugen 0 bis 99.

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 der Kürzeste Übermittlung nach Anzahl der Quellcode-Zeichen was auch ist richtig.

BONUS

Sie können auch versuchen, eine Version des Codes zu schreiben, die bei jeder Anwendung der Transformationsfunktion 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)

(BEARBEITEN) 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. Allerdings ist mir die Groß- und Kleinschreibung egal.Und es ist mir egal, wie Sie die Wort-Tokens trennen, obwohl sie getrennt werden sollten: ninety-nine es ist okay, ninety nine es ist okay, ninetynine ist nicht in Ordnung.

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

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

War es hilfreich?

Lösung

GolfScript - 101 96 93 92 91 90 94 86 Byte

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

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

Andere Tipps

Perl, ca. 147 Zeichen

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

Common Lisp 157 Zeichen

Neue, konformere Version, die jetzt die Standardeingabe 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 menschenlesbarer 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.

Python 2.x, 144 150 154 166 Zeichen

Dadurch wird die Zahl in Zehner und Einer unterteilt und diese zusammengefasst.Die unerwünschte Eigenschaft des pseudoternären Operators a and b or c Das c wird zurückgegeben, wenn b ist 0 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."

C – mit Zahlwörtern

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

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

Alle Zeilenumbrüche dienen der besseren 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.Eine besser lesbare Version finden Sie weiter unten.

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.Für Teilzeichenfolgen, die im ersten Satz nicht vollständig verwendet werden, wird am Ende eine „Nachschlagetabelle“ mit zusätzlichen Namenseinträgen hinzugefügt.Suchvorgänge sind rekursiv:Einträge können auf andere Einträge verweisen.

Der komprimierte Name für 11 lautet beispielsweise elM.Der print() Funktion gibt die Zeichen aus e Und l (Kleinbuchstabe „L“, nicht Zahl „1“) wörtlich, aber dann findet es das M, ruft sich also mit dem Index des 29. Eintrags (ASCII 'M' - ASCII '0') in die Nachschlagetabelle auf.Diese Zeichenfolge ist evL, also wird es ausgegeben e Und v, ruft sich dann erneut mit dem Index des 28. Eintrags in der Nachschlagetabelle auf, also en, und wird wörtlich ausgegeben.Das ist nützlich, weil en wird auch verwendet in eL für een (verwendet nach eight In eighteen), das in verwendet wird tO für teen (wird für jeden anderen verwendet -teen Name).

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

Die Kommas am Anfang und am Ende der Zeichenfolge dienen dazu, die Teilzeichenfolgen in dieser Zeichenfolge auf einfache Weise zu finden.Wenn Sie hier zwei Zeichen hinzufügen, werden später weitere Zeichen eingespart.

Über den Missbrauch von main()

argv ignoriert (und daher in der komprimierten Version nicht deklariert) wird, wird der Wert von argc ignoriert, aber der Speicher wird wiederverwendet, um die aktuelle Zahl aufzunehmen.Dies erspart mir lediglich die Deklaration einer zusätzlichen Variablen.

Über den Mangel an #include

Einige werden sich über das Unterlassen beschweren #include <stdio.h> betrügt.Das ist es überhaupt nicht.Das Gegebene ist ein völlig legales C-Programm, das auf jedem mir bekannten C-Compiler korrekt kompiliert werden kann (wenn auch mit Warnungen).Da Prototypen für die stdio-Funktionen fehlen, geht der Compiler davon aus, dass es sich um zurückkehrende cdecl-Funktionen handelt int, und wird darauf vertrauen, dass Sie wissen, welche Argumente Sie vorbringen müssen.Die Rückgabewerte werden in diesem Programm ohnehin ignoriert und es handelt sich bei allen um cdecl-Funktionen („C“-Aufrufkonvention), und wir wissen tatsächlich, welche Argumente wir übergeben müssen.

Ausgabe

Die Ausgabe ist wie erwartet:

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

* Die vorherige Version hat in zwei Teilen der Spezifikation das Ziel verfehlt:Es verarbeitete keine Null und nahm Eingaben über die Befehlszeile statt über stdin entgegen.Durch den Umgang mit Nullen wurden Zeichen hinzugefügt, aber die Verwendung von stdin anstelle von Befehlszeilenargumenten sowie einige andere Optimierungen sparten die gleiche Anzahl von Zeichen, was zu einem Wash führte.

Die Anforderungen wurden geändert, um klarzustellen, dass das Zahlenwort auf beiden Seiten von „is“ gedruckt werden muss.Diese neue Version erfüllt diese Anforderung und implementiert einige weitere Optimierungen, um der erforderlichen zusätzlichen Größe (mehr als) Rechnung zu tragen.

J, 107 112 Figuren

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

(Neue Zeile nur zur besseren Lesbarkeit)

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

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 Ihnen ernsthaft vorschlagen würde, dies zu tun ...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.

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 mir sicher, dass Groovy vieles davon loswerden würde.

Erklärung und Formatierung (Alle Kommentare, Zeilenumbrüche und führenden/nachgestellten Leerzeichen wurden in count entfernt):

Ziemlich unkompliziert, 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, da dies weniger Tastenanschläge erfordert

Windows PowerShell:152 153 184 Bytes

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

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

(basiert ursprünglich auf Vlads Python-Code, hat sich einen Trick aus der C++-Lösung von Tom Sirgedas ausgeliehen, 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.");
}

Python, 129 133 137 148 Zeichen

Zum Aufwärmen hier meine erste Version (verbessert einige Zeichen im Vergleich zum vorherigen besten Python).

PS.Nach ein paar Redaktionen ist es jetzt etwa 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.'

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 die Länge von Nummernnamen basierend auf den Ziffern, die in der Nummer vorkommen.
  • Verwenden Sie die Zeichen-Array-Suche für eine Zeichenfolge und char-Arithmetik anstelle eines numerischen Arrays.
  • Verwenden Sie das Aliasing des Klassennamens, um es zu verkürzen Console. Zu C.
  • Verwenden Sie den bedingten (ternären) Operator (?:) anstatt if/else.
  • Benutzen Sie die \n mit Write Escape-Code statt WriteLine
  • Nutzen Sie die Tatsache, dass C# über eine definierte Auswertungsreihenfolge verfügt, um Zuweisungen innerhalb der zu ermöglichen Write Funktionsaufruf
  • Verwenden Sie die Zuweisungsausdrücke, um zusätzliche Anweisungen und damit zusätzliche geschweifte Klammern zu eliminieren

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 hat auf einen bösen Fehler hingewiesen.Schnellkorrektur fügt 31 Zeichen hinzu, autsch!
  • Für keinen Sonderfall umgestaltet, auch leichtes Golfen durchgeführt.
  • Direkter Listenzugriff für den einmaligen Gebrauch statt Speicherung im Array?Auf jedenfall!
  • SO VIEL REFACTORING für nur EINEN verdammten Charakter.Das ist wirklich das Leben eines Golfspielers.:-(
  • Hoppla, einfache Fehlerbehebung für Leerzeichen.198 jetzt.
  • Etwas überflüssiger Code wurde überarbeitet.
  • Letztes zurückgegebenes Schlüsselwort in r ist unnötig, etwas mehr abrasiert.
  • 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.
  • Versuchen Sie es mit bloßem Wort „Magie“.

Lassen Sie uns diesen Stein 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!

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:

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

Haskell, 224 270 Figuren

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

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

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.

Formatiert:

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 ist noch Platz für etwas mehr Quetschen ...:-P

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:Habe einige sorgfältige Einfügungen und Änderungen vorgenommen:

  • l.ToString() wurde in eine Umwandlung in geändert object des string "magic".
  • Eine temporäre Variable erstellt o, damit ich das verschieben konnte break außerhalb von for Schleife, das heißt, was zu einer führt do-while.
  • Inline die o Aufgabe, sowie die v Zuweisung, weiterhin Einfügen der Berechnung von l in den Funktionsargumenten insgesamt, wodurch die Notwendigkeit entfällt l.Außerdem ist die Zuweisung von eingefügt m.
  • Ein Leerzeichen wurde entfernt int[] x, int[]x ist auch echt.
  • Versucht, das Array in eine String-Transformation umzuwandeln, aber das using System.Linq war zu viel, um daraus eine Verbesserung zu machen.

Bearbeiten Sie 2 DykamDas int-Array wurde in ein char-Array/eine char-Zeichenfolge geändert und die richtige Arithmik hinzugefügt, um dies zu korrigieren.

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

C – ohne Zahlwörter

180 175* 172 167 Zeichen

Alle Zeilenumbrüche dienen der besseren 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 ungekürzt:

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 in zwei Teilen der Spezifikation das Ziel verfehlt:Es verarbeitete keine Null und nahm Eingaben über die Befehlszeile statt über stdin entgegen.Durch die Handhabung von null hinzugefügten Zeichen, aber durch die Verwendung von stdin anstelle von Befehlszeilenargumenten wurden noch mehr Einsparungen erzielt, was zu Nettoeinsparungen führte.

Perl, 123 122 Zeichen

Ich habe gerade festgestellt, dass es nicht erforderlich ist, auf STDOUT auszugeben. Geben Sie es stattdessen auf STDERR aus und entfernen 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/

Das entspricht zwar den Spezifikationen, ist aber nicht zu 100 % gut formatiert.Es gibt ein zusätzliches Leerzeichen nach Zahlen zurück, die auf Null enden.Die Spezifikation sagt:

„Es ist mir egal, wie Sie die Wortmarken trennen, obwohl sie getrennt werden sollten.“

Das ist aber irgendwie komisch.Eine korrektere Version unter

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/

Python:

#!/usr/bin/env python

# Number of letters in each part, we don't count spaces
Decades = ( 0, 3, 6, 6, 6, 5, 5, 7, 6, 6, 0 )
Smalls  = ( 0, 3, 3, 5, 4, 4, 3, 5, 5, 4 )
Teens  =  ( 6, 6, 8, 8, 7, 7, 9, 8, 8 )

def Count(n):
    if n > 10 and n < 20: return Teens[n-11]
    return   Smalls[n % 10 ] + Decades [ n / 10 ]

N = input()

while N-4:
    Cnt = Count(N)
    print "%d is %d" % ( N, Cnt)
    N = Cnt

print "4 is magic"

C++, 171 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.");}

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

Lua 185 190 199

Punkte hinzugefügt, io.read hinzugefügt, ()s 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.'

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

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 - Rückgängig gemachte Änderung zu Händen von Herrschaft des Pöbels, Aber ($_%10&&$u[$_%10])(($_%=10)&&$u[$_]), was der gleichen Anzahl an Zeichen entspricht, aber ich habe es getan, für den Fall, dass jemand eine Möglichkeit sieht, 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 Herrschaft des Pöbels


Notiz: Ich hatte es satt, die Antworten anderer in Kommentaren zu verbessern, also bin ich jetzt gierig und kann meine Änderungen einfach hier hinzufügen :) Dies ist eine Abspaltung von Platin Azure's Antwort - Teilweise Dank an Hobbs, Herrschaft des Pöbels, Und Platin Azure.

Schamloses Perl mit Zahlenwörtern (329 Zeichen)

Ziemlich direkt an den C-Code von P Daddy angelehnt, mit einigen Änderungen daran p() Damit es das Gleiche tut, werden Perl-Primitive anstelle von C-Primitiven und eine größtenteils neu geschriebene Hauptschleife verwendet.Eine Erklärung finden Sie hier.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 print gibt nur wahr/falsch zurück;Wenn es eine Zählung zurückgeben würde, würde es mir 7 Schläge ersparen.

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

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top