Ihre Aufgabe ist es, den größten gemeinsamen Divisor (GCD) von zwei gegebenen ganzen Zahlen in so wenigen Byte Code wie möglich zu berechnen .
Sie können ein Programm oder eine Funktion schreiben, indem Sie Eingaben vornehmen und Ausgaben mit einer unserer anerkannten Standardmethoden zurückgeben (einschließlich STDIN / STDOUT, Funktionsparameter / Rückgabewerte, Befehlszeilenargumente usw.).
Die Eingabe erfolgt über zwei nicht negative Ganzzahlen. Sie sollten in der Lage sein, entweder den gesamten Bereich zu verarbeiten, der vom Integer-Standardtyp Ihrer Sprache unterstützt wird, oder den Bereich [0,255]
, der größer ist. Es ist garantiert, dass mindestens einer der Eingänge ungleich Null ist.
Sie dürfen keine integrierten Funktionen verwenden, die entweder die GCD oder die LCM (Least Common Multiple) berechnen.
Es gelten die Standardregeln für Code-Golf .
Testfälle
0 2 => 2
6 0 => 6
30 42 => 6
15 14 => 1
7 7 => 7
69 25 => 1
21 12 => 3
169 123 => 1
20 142 => 2
101 202 => 101
quelle
SIGFPE
.Antworten:
Retina , 16
Hierbei wird der Algorithmus von Euclid überhaupt nicht verwendet. Stattdessen wird die GCD mithilfe von Regex-Übereinstimmungsgruppen gefunden.
Probieren Sie es online aus. - In diesem Beispiel wird GCD (8,12) berechnet.
Eingabe als 2 durch Leerzeichen getrennte Ganzzahlen. Beachten Sie, dass die E / A unär ist. Wenn das nicht akzeptabel ist, können wir dies tun:
Netzhaut, 30
Probieren Sie es online aus.
Wie @ MartinBüttner feststellt, fällt dies bei großen Zahlen auseinander (wie dies im Allgemeinen für alles Unäre der Fall ist). Mindestens eine Eingabe von INT_MAX erfordert die Zuweisung einer Zeichenfolge von 2 GB.
quelle
+
s zu*
s tun sollte. Und Sie können die letzte Stufe des langen Codes erheblich verkürzen, indem Sie ihn auf reduzieren1
.^
, da es unmöglich ist, dass das Match von der Startposition aus fehlschlägt.Maschinencode i386 (x86-32), 8 Byte (9 Byte für vorzeichenlose Zeichen)
+ 1B, wenn wir mit
b = 0
Eingaben umgehen müssen .Computercode amd64 (x86-64), 9 Byte (10B für vorzeichenlose oder
14B13B für vorzeichenlose 64B-Ganzzahlen)109B für unsigned auf amd64, das mit beiden Eingängen = 0 abbrichtDie Eingänge sind 32 - Bit - Nicht-Null unterzeichnete ganze Zahlen in
eax
undecx
. Ausgabe ineax
.Diese Schleifenstruktur besteht den Testfall wo nicht
ecx = 0
. (div
Verursacht eine#DE
Hardwareausführung beim Teilen durch Null. (Unter Linux liefert der Kernel eineSIGFPE
(Gleitkomma-Ausnahme).) Wenn der Loop-Einstiegspunkt direkt vor dem liegtinc
, vermeiden wir das Problem. Die x86-64-Version kann damit umgehen kostenlos, siehe unten.Die Antwort von Mike Shlanta war der Ausgangspunkt dafür . Meine Schleife macht dasselbe wie seine, aber für vorzeichenbehaftete ganze Zahlen, weil
cdq
ein Byte kürzer ist alsxor edx,edx
. Und ja, es funktioniert korrekt mit einem oder beiden negativen Eingängen. Mikes Version wird schneller laufen und weniger Platz im UOP-Cache beanspruchen (xchg
3 UOPs auf Intel-CPUs undloop
auf den meisten CPUs sehr langsam ), aber diese Version gewinnt bei der Größe des Maschinencodes.Ich habe zunächst nicht bemerkt, dass die Frage 32bit ohne Vorzeichen erfordert . Ein Zurück zu
xor edx,edx
anstattcdq
würde ein Byte kosten.div
hat die gleiche Größe wieidiv
und alles andere kann gleich bleiben (xchg
für die Datenübertragung undinc/loop
funktioniert immer noch).Interessanterweise haben für 64-Bit-Operanden (
rax
undrcx
) vorzeichenbehaftete und vorzeichenlose Versionen dieselbe Größe. Die signierte Version benötigt ein REX-Präfix fürcqo
(2B), die nicht signierte Version kann jedoch weiterhin 2B verwendenxor edx,edx
.Im 64-Bit-Code
inc ecx
ist 2B: Die Einzelbyte-inc r32
unddec r32
Opcodes wurden als REX-Präfixe neu verwendet.inc/loop
speichert keine Codegröße im 64-Bit-Modus, also könnten Sie es auchtest/jnz
. Bei 64-Bit-Ganzzahlen wird ein weiteres Byte pro Befehl in REX-Präfixen hinzugefügt, mit Ausnahme vonloop
oderjnz
. Es ist möglich, dass der Rest alle Nullen in den niedrigen 32b hat (zBgcd((2^32), (2^32 + 1))
), also müssen wir den gesamten RCX testen und können kein Byte mit speicherntest ecx,ecx
. Das langsamerejrcxz
INSN ist jedoch nur 2B, und wir können es oben in die Schleifeecx=0
einfügen, um es bei der Eingabe zu behandeln :Vollständig lauffähiges Testprogramm, einschließlich eines Programms
main
, mit demprintf("...", gcd(atoi(argv[1]), atoi(argv[2])) );
Quell- und Asm-Ausgabe im Godbolt Compiler Explorer für die Versionen 32 und 64b ausgeführt werden. Getestet und lauffähig für 32bit (-m32
), 64bit (-m64
) und x32 ABI (-mx32
) .Ebenfalls enthalten: eine Version, bei der nur die wiederholte Subtraktion verwendet wird. Dies ist 9B für den Modus ohne Vorzeichen, auch für den x86-64-Modus, und kann einen seiner Eingänge in einem beliebigen Register annehmen. Es kann jedoch keine der Eingaben verarbeiten, die bei der Eingabe 0 sind (es erkennt, wenn
sub
eine Null erzeugt wird, was x - 0 niemals tut).GNU C Inline Asm Source für die 32bit Version (kompilieren mit
gcc -m32 -masm=intel
)Normalerweise würde ich eine ganze Funktion in asm schreiben, aber GNU C inline asm scheint der beste Weg zu sein, um ein Snippet einzubeziehen, das Ein- / Ausgänge in den von uns gewählten Regs haben kann. Wie Sie sehen, macht die GNU C-Inline-asm-Syntax asm hässlich und laut. Es ist auch ein sehr schwieriger Weg , asm zu lernen .
Es würde tatsächlich kompilieren und im
.att_syntax noprefix
Modus arbeiten, da alle verwendeten Insns entweder Single / No Operand oder sindxchg
. Keine wirklich nützliche Beobachtung.quelle
jrcxz
in der uint64_t-Version eine Verwendung gefunden :). Ich habe auch nicht bemerkt, dass Sie unsigniert angegeben haben, also habe ich auch die Anzahl der Bytes eingeschlossen.jecxz
in der 32-Bit-Version nicht den gleichen Effekt erzielen?inc/loop
In der 32-Bit-Version sind es 3 Byte, in der 64-Bit-Version 4 Byte. Das bedeutet , dass in der 64-Bit - Version, ist es nicht zusätzliches Bytes kostet zu verwendenjrcxz
undjmp
stattinc / loop
.Hexagony , 17 Bytes
Entfaltet:
Probieren Sie es online!
Es war ein Kinderspiel, es in Seitenlänge 3 einzubauen. Das Abschalten dieser zwei Bytes am Ende war nicht ... Ich bin auch nicht überzeugt, dass es optimal ist, aber ich bin mir sicher, dass es nahe ist.
Erläuterung
Eine weitere Implementierung des euklidischen Algorithmus.
Das Programm verwendet drei Speicherflanken, die ich als A , B und C bezeichne , wobei der Speicherzeiger (MP) wie folgt beginnt:
Hier ist das Kontrollflussdiagramm:
Der Kontrollfluss beginnt auf dem grauen Pfad mit einem kurzen linearen Bit für die Eingabe:
Beachten Sie, dass der Code jetzt an den Kanten
<
in der linken Ecke umbrochen wird. Dies<
wirkt als Zweig. Wenn die aktuelle Flanke Null ist (dh der euklidische Algorithmus endet), wird die IP nach links abgelenkt und nimmt den roten Pfad. Andernfalls wird auf dem grünen Pfad eine Iteration des euklidischen Algorithmus berechnet.Wir betrachten zuerst den grünen Weg. Beachten Sie, dass
>
und\
alle als Spiegel fungieren, die den Befehlszeiger einfach ablenken. Beachten Sie auch, dass der Kontrollfluss dreimal um die Kanten verläuft, einmal von unten nach oben, einmal von der rechten Ecke zur unteren Reihe und schließlich von der rechten unteren Ecke zur linken Ecke, um den Zustand erneut zu überprüfen. Beachten Sie auch, dass.
No-Ops sind.Damit bleibt der folgende lineare Code für eine einzelne Iteration übrig:
Jetzt sind wir wieder da, wo wir angefangen haben, mit der Ausnahme, dass die drei Kanten ihre Rollen zyklisch geändert haben (das ursprüngliche C übernimmt jetzt die Rolle von B und das ursprüngliche B die Rolle von A ...). Tatsächlich haben wir die Eingaben
A
undB
mitB
bzw. verschobenA % B
.Sobald
A % B
(an Kante C ) Null ist, kann die GCD an Kante B gefunden werden . Wieder>
lenkt der Just die IP ab, also auf dem roten Pfad, den wir ausführen:quelle
32-Bit-Little-Endian-x86-Maschinencode, 14 Byte
Generiert mit
nasm -f bin
d231 f3f7 d889 d389 db85 f475
quelle
cdq
und signiertidiv
und ein Bytexchg eax, r32
stattmov
. Für 32-Bit-Code:inc/loop
statttest/jnz
(ich konnte keinen Weg finden, ihn zu verwendenjecxz
, und es gibt keinenjecxnz
). Ich habe meine endgültige Version als neue Antwort veröffentlicht, da ich denke, dass die Änderungen groß genug sind, um dies zu rechtfertigen.T-SQL, 153
169BytesJemand hat die schlechteste Sprache zum Golfen erwähnt?
Erstellt eine Tabellenwertfunktion
, die eine rekursive Abfrage verwendet, um die gemeinsamen Teiler zu ermitteln. Dann gibt es das Maximum zurück. Nun nutzt den euklidischen Algorithmus die GCD zu bestimmen , aus meiner Antwort abgeleitet hier .Anwendungsbeispiel
quelle
Gelee, 7 Bytes
Rekursive Implementierung des euklidischen Algorithmus. Probieren Sie es online!
Wenn die Verwendung von integrierten Funktionen nicht verboten wäre
g
(1 Byte, integrierte GCD), würde dies zu einer besseren Bewertung führen.Wie es funktioniert
quelle
Haskell, 19 Bytes
Anwendungsbeispiel:
45 # 35
->5
.Wieder Euklid.
PS: Natürlich gibt es auch eine eingebaute
gcd
.quelle
0
oder fährt mit dem Modul fort.Prelude
Python 3, 31
3 Bytes gespart dank Sp3000.
quelle
from math import*;gcd
g=lambda a,b:b and g(b,a%b)or a
MATL ,
119 BytesBisher scheint noch niemand rohe Gewalt angewendet zu haben, also hier ist es.
Die Eingabe ist ein Spaltenarray mit den beiden Zahlen (
;
als Trennzeichen).Probieren Sie es online! oder überprüfen Sie alle Testfälle .
Erläuterung
quelle
C 38 Bytes
quelle
g
anstelle von benennengcd
.C 28 Bytes
Eine ziemlich einfache Funktion, die den Euclid-Algorithmus implementiert. Vielleicht kann man mit einem alternativen Algorithmus kürzer werden.
Wenn man eine kleine Hauptverpackung schreibt
dann kann man ein paar werte testen:
quelle
Labyrinth , 18 Bytes
Beendet mit einem Fehler, aber die Fehlermeldung geht an STDERR.
Probieren Sie es online!
Das fühlt sich noch nicht optimal an, aber ich sehe derzeit keine Möglichkeit, die Schleife unter 3x3 zu komprimieren.
Erläuterung
Dies verwendet den euklidischen Algorithmus.
Erstens gibt es ein lineares Bit, um die Eingabe zu lesen und in die Hauptschleife zu gelangen. Der Anweisungszeiger (IP) beginnt in der oberen linken Ecke und geht nach Osten.
Wir betreten nun eine Art while-do-Schleife, die den euklidischen Algorithmus berechnet. Die Stapeloberseiten enthalten
a
undb
(zusätzlich zu einer impliziten unendlichen Anzahl von Nullen, die wir jedoch nicht benötigen). Wir werden die Stapel von Seite zu Seite darstellen und aufeinander zuwachsen:Die Schleife endet, sobald
a
Null ist. Eine Schleifeniteration funktioniert wie folgt:Sie können sehen, wir haben ersetzt
a
undb
mitb%a
unda
jeweils.Wenn einmal
b%a
Null ist, bewegt sich die IP weiter nach Osten und führt Folgendes aus:quelle
Julia,
21-15BytesRekursive Implementierung des euklidischen Algorithmus. Probieren Sie es online!
Wenn die Verwendung von integrierten Funktionen nicht verboten wäre
gcd
(3 Byte, integrierte GCD), würde dies zu einer besseren Bewertung führen.Wie es funktioniert
quelle
Cubix , 10
12BytesProbieren Sie es hier aus
Dies wird wie folgt auf den Würfel gewickelt:
Verwendet die euklidische Methode.
II
Zwei Zahlen sind aus STDIN packen und auf dem Stapel/
Fluss reflektierte bis%
Mod die Oberseite des Stapels. Rest links oben auf Stapel?
Wenn TOS 0 dann weitermachen, sonst rechts abbiegenv
Wenn nicht 0 , dann umleiten nach unten undu
nach rechts abbiegen zweimal wieder auf die mod/
Wenn 0 geht um den Würfel zu dem Reflektor;
Drop TOS,O
Ausgang TOS und@
Endequelle
0,x
undx,0
... dann bin ich auf diese Antwort gestoßen . Schön!C #, 24 Bytes
quelle
Windows Batch, 76 Bytes
Rekursive Funktion. Nennen Sie es wie
GCD a b
mit Dateinamengcd
.quelle
MATL, 7 Bytes
Probieren Sie es online!
Erläuterung
Da wir die eingebaute GCD-Funktion (
Zd
in MATL) nicht explizit verwenden können , habe ich die Tatsache ausgenutzt, dass das kleinste gemeinsame Vielfache vona
undb
der größte gemeinsame Nenner vona
undb
gleich dem Produkt vona
und istb
.quelle
*1MZm/
Racket (Schema), 44 Bytes
Euklid-Implementierung in Racket (Schema)
Edit: @Numeris Lösung nicht gesehen lol. Irgendwie haben wir unabhängig voneinander genau den gleichen Code
quelle
> <> 32 Bytes
Akzeptiert zwei Werte aus dem Stapel und wendet den euklidischen Algorithmus an, um ihre GCD zu erzeugen.
Sie können es hier ausprobieren !
Für eine viel bessere Antwort in> <>, schauen Sie sich Sok's an !
quelle
ReRegex , 23 Bytes
Funktioniert identisch mit der Retina-Antwort.
Probieren Sie es online!
quelle
GML, 57 Bytes
quelle
Delphi 7, 148
Nun, ich denke, ich habe die neue schlechteste Sprache zum Golfen gefunden.
quelle
Hoon, 20 Bytes
-
Hoon # 2, 39 Bytes
Seltsamerweise ist die einzige Implementierung in Hoons stdlib for GCD diejenige, die für die RSA-Krypto verwendet wird, die auch einige andere Werte zurückgibt. Ich muss es in eine Funktion packen, die nur
d
von der Ausgabe nimmt.Die andere Implementierung ist nur die standardmäßige rekursive GCD-Definition.
quelle
Python 3.5,
708273 Bytes:In
not
diesem Fall wird sichergestellt, dass die Summe aller Zahlen in*args
Moduloi
Null ist.Außerdem kann diese Lambda-Funktion jetzt so viele Werte aufnehmen, wie Sie möchten, solange die Anzahl der Werte
>=2
dergcd
Funktion des Mathematikmoduls nicht entspricht. Zum Beispiel kann es die Werte aufnehmen2,4,6,8,10
und den korrekten GCD von 2 zurückgeben.quelle
Ruby, 23 Bytes
Denken Sie daran, dass Ruby-Blöcke mit g [...] oder g.call (...) anstelle von g (...) aufgerufen werden.
Teilgutschriften für die Voidpigeon
quelle
g.call(a,b)
Ihnen können verwendeng[a,b]
. Stattdessenproc{|a,b|
können Sie verwenden->a,b{
.b>0
anstelleb<=0
der anderen Operanden die Reihenfolge ändern.ARM-Maschinencode, 12 Byte:
Versammlung:
Derzeit kann dies nicht kompiliert werden, aber jede Anweisung in ARM benötigt 4 Bytes. Wahrscheinlich könnte es mit dem THUMB-2-Modus abgespielt werden.
quelle
r0 > r1
dannsublt
nichts tun wird (lt
Prädikat ist falsch) undbne
wird eine Endlosschleife sein. Ich denke, Sie brauchen einen Swap, wenn nichtlt
, so dass die gleiche Schleife tun kannb-=a
odera-=b
wie benötigt. Oder eine Verneinung, wenn das Sub produziert (aka ausleihen).cmp r0, r1
/subgt r0, r0, r1
/sublt r1, r1, r0
/bne gcd
. Das sind 16B in ARM-Anweisungen, vielleicht 12 in thumb2-Anweisungen?sub ecx, eax
/jae .no_swap
/add ecx,eax
/xchg ecx,eax
/jne
. Anstelle eines cmp setze ich also einfach ein Sub, mache es dann rückgängig und tausche es aus, wenn das Sub in die andere Richtung hätte gehen sollen. Ich habe das getestet und es funktioniert. (add
Beendet dasjne
Programm nicht zur falschen Zeit, da es keine Null erzeugen kann, es sei denn, eine der Eingaben war anfangs Null, und wir unterstützen das nicht. Update: Wir müssen beide Eingaben als Null unterstützen: /)ite
Anweisung: if-then-else. Sollte perfekt für cmp / sub in eine Richtung / sub in die andere Richtung sein.TI-Basic, 10 Bytes
Nicht konkurrierend aufgrund der neuen Regel, die verbietet, dass gcd eingebaut ist
17-Byte- Lösung ohne
gcd(
eingebautesNicht konkurrierend wegen neuer Regel, die lcm-Einbauten verbietet
27-Byte- Lösung ohne
gcd(
oderlcm(
eingebaut:35 Byte rekursive Lösung ohne
gcd(
oder mitlcm(
integrierten Funktionen (erfordert ein 2,53 MP-Betriebssystem oder höher, muss benannt werdenprgmG
):Sie würden Argumente an die rekursive Variante übergeben, wie
{A,B}
dies beispielsweise{1071, 462}:prgmG
der Fall wäre21
.quelle
prgmG
.05AB1E , 10 Bytes
Code:
Probieren Sie es online!
Mit eingebauten:
Erläuterung:
Probieren Sie es online! oder Versuchen Sie es mit mehreren Nummern .
quelle
Oracle SQL 11.2,
104118 BytesBei Eingabe von 0 behoben
quelle
SELECT MAX(LEVEL)FROM DUAL WHERE MOD(:1,LEVEL)+MOD(:2,LEVEL)=0 CONNECT BY LEVEL<=:1+:2;
> <> , 12 + 3 = 15 Bytes
Erwartet, dass die Eingabenummern auf dem Stapel vorhanden sind, also +3 Byte für das
-v
Flag. Probieren Sie es online!Eine weitere Implementierung des Euklidischen Algorithmus.
quelle