Code Golf:Vier ist Magie
-
14-09-2020 - |
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:
- 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.
- 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.)
- Die Eingabe sollte in numerischer Form erfolgen.
- 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. - Punkte (Punkte) SIND erforderlich!
- Die letzte Zeile sollte natürlich lauten:
4 is magic.
. - 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:
- Ich möchte, dass das Wort in allen zutreffenden Fällen auf beiden Seiten erscheint, z.
Nine is four. Four is magic.
- 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.
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.
ZuC.
- Verwenden Sie den bedingten (ternären) Operator (
?:
) anstattif/else
. - Benutzen Sie die
\n
mitWrite
Escape-Code stattWriteLine
- 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
desstring
"magic"
. - Eine temporäre Variable erstellt
o
, damit ich das verschieben konntebreak
außerhalb vonfor
Schleife, das heißt, was zu einer führtdo-while
. - Inline die
o
Aufgabe, sowie diev
Zuweisung, weiterhin Einfügen der Berechnung vonl
in den Funktionsargumenten insgesamt, wodurch die Notwendigkeit entfälltl
.Außerdem ist die Zuweisung von eingefügtm
. - 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);
}