Votre tâche consiste à calculer le plus grand commun diviseur (GCD) de deux entiers donnés dans le moins d'octets de code possible.
Vous pouvez écrire un programme ou une fonction, prendre des entrées et renvoyer des sorties via l’une de nos méthodes standard acceptées (y compris STDIN / STDOUT, paramètres de fonction / valeurs de retour, arguments de ligne de commande, etc.).
L'entrée sera deux entiers non négatifs. Vous devriez pouvoir gérer soit la plage complète prise en charge par le type entier par défaut de votre langue, soit la plage [0,255]
, selon la valeur la plus élevée. Vous avez la garantie qu'au moins une des entrées sera non nulle.
Vous n'êtes pas autorisé à utiliser les fonctions intégrées qui calculent le GCD ou le LCM (multiple le plus petit commun).
Les règles standard de code-golf s'appliquent.
Cas de test
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
la source
SIGFPE
.Réponses:
Rétine , 16 ans
Cela n'utilise pas du tout l'algorithme d'Euclid - il trouve plutôt le GCD en utilisant des groupes de correspondance de regex.
Essayez-le en ligne. - Cet exemple calcule GCD (8,12).
Entrez 2 entiers séparés par des espaces. Notez que les E / S sont unaires. Si cela n'est pas acceptable, alors nous pouvons le faire:
Rétine, 30
Essayez-le en ligne.
Comme @ MartinBüttner le fait remarquer, cela s’efface pour les grands nombres (comme c’est généralement le cas pour tout ce qui est unaire). Au minimum, une entrée de INT_MAX nécessitera l'allocation d'une chaîne de 2 Go.
la source
+
s en*
s devrait faire. Et vous pouvez raccourcir considérablement la dernière étape du code long en le réduisant à1
.^
, car il est impossible que la correspondance échoue à partir de la position de départ.Code machine i386 (x86-32), 8 octets (9 b pour non signé)
+ 1B si nous devons gérer
b = 0
les entrées.amd64 (x86-64) code machine, 9 octets (10B pour non signé, ou
14B13B pour des entiers non signés 64b signés ou)109B pour unsigned sur amd64 qui rompt avec l'une des entrées = 0Les entrées sont des entiers signés 32 bits non nuls dans
eax
etecx
. Sortie eneax
.Cette structure de boucle échoue dans le cas de test où
ecx = 0
. (div
provoque une#DE
exécution matérielle lors d'une division par zéro. (Sous Linux, le noyau fournit uneSIGFPE
(exception de virgule flottante)). Si le point d'entrée de la boucle était juste avant leinc
, nous éviterions le problème. La version x86-64 peut le gérer. gratuitement, voir ci-dessous.La réponse de Mike Shlanta a été le point de départ pour cela . Ma boucle fait la même chose que la sienne, mais pour les entiers signés car
cdq
est un octet plus court quexor edx,edx
. Et oui, cela fonctionne correctement avec une ou les deux entrées négatives. La version de Mike fonctionnera plus rapidement et prendra moins d’espace dans le cache uop (xchg
3 uops sur les processeurs Intel etloop
très lente sur la plupart des processeurs ), mais cette version gagne à la taille du code machine.Je n'avais pas remarqué au début que la question demandait 32 bits non signés . Retourner à
xor edx,edx
au lieu decdq
coûterait un octet.div
est de la même taille queidiv
, et tout le reste peut rester identique (xchg
pour le transfert de données etinc/loop
fonctionne toujours).Fait intéressant, pour les opérandes de taille 64 bits (
rax
etrcx
), les versions signée et non signée ont la même taille. La version signée nécessite un préfixe REX pourcqo
(2B), mais la version non signée peut toujours utiliser 2Bxor edx,edx
.Dans le code 64 bits,
inc ecx
correspond à 2B: le code sur un octetinc r32
et lesdec r32
codes opération ont été réaffectés en tant que préfixes REX.inc/loop
n'enregistre aucune taille de code en mode 64 bits, donc vous pourriez aussi bientest/jnz
. Opérer sur des entiers 64 bits ajoute un octet supplémentaire par instruction dans les préfixes REX, à l'exception deloop
oujnz
. Il est possible que le reste ait tous les zéros dans le bas 32b (par exemplegcd((2^32), (2^32 + 1))
), nous avons donc besoin de tester tout le rcx et nous ne pouvons pas sauvegarder un octet avectest ecx,ecx
. Cependant, l’jrcxz
insn le plus lent n’est que 2B, et nous pouvons le placer en haut de la boucle pour gérerecx=0
en entrée :Programme de test complet exécutable, y compris un programme
main
quiprintf("...", gcd(atoi(argv[1]), atoi(argv[2])) );
utilise les sources et les sorties asm sur Godbolt Compiler Explorer , pour les versions 32 et 64b. Testé et fonctionnant pour 32bit (-m32
), 64bit (-m64
) et x32 ABI (-mx32
) .Sont également inclus: une version utilisant uniquement la soustraction répétée , soit 9B pour le type non signé, même en mode x86-64, et peut prendre l’une de ses entrées dans un registre arbitraire. Cependant, il ne peut gérer aucune entrée étant 0 à l'entrée (il détecte quand
sub
produit un zéro, ce que x-0 ne fait jamais).GNU C inline asm source pour la version 32 bits (compiler avec
gcc -m32 -masm=intel
)Normalement, j’écrirais toute une fonction dans asm, mais GNU C inline asm semble être le meilleur moyen d’inclure un extrait de code pouvant avoir des entrées / sorties dans toutes les règles de notre choix. Comme vous pouvez le constater, la syntaxe asm en ligne de GNU C rend asm laid et bruyant. C'est aussi un moyen très difficile d' apprendre asm .
Cela compilerait et fonctionnerait en
.att_syntax noprefix
mode, parce que toutes les insns utilisées sont simples ou sans opérande ouxchg
. Ce n'est pas vraiment une observation utile.la source
jrcxz
après tout dans la version uint64_t :). De plus, je n’ai pas remarqué que vous aviez spécifié non signé, alors j’ai inclus le nombre d’octets pour cela aussi.jecxz
la version 32 bits avec le même effet?inc/loop
3 octets dans la version 32 bits, mais 4B dans la version 64 bits. Cela signifie que dans la version 64 bits uniquement, l'utilisationjrcxz
et lajmp
substitution d' octets supplémentaires ne coûtent rieninc / loop
.Hexagonie , 17 octets
Déplié:
Essayez-le en ligne!
Le montage dans la longueur de côté 3 était un jeu d'enfant. Réduire ces deux octets à la fin n'était pas ... Je ne suis pas non plus convaincu que c'est optimal, mais je suis sûr que je pense que c'est proche.
Explication
Une autre implémentation d'algorithme euclidien.
Le programme utilise trois bords de mémoire, que j'appellerai A , B et C , avec le pointeur de mémoire (MP) commençant comme suit:
Voici le diagramme de flux de contrôle:
Le flux de contrôle commence sur le chemin gris avec un bit linéaire court pour l'entrée:
Notez que le code entoure maintenant les bords
<
dans le coin gauche. Cela<
agit comme une branche. Si le front actuel est égal à zéro (c'est-à-dire que l'algorithme euclidien se termine), l'adresse IP est déviée vers la gauche et prend le chemin rouge. Sinon, une itération de l'algorithme euclidien est calculée sur le chemin vert.Nous allons d'abord considérer le chemin vert. Notez que
>
et\
tout agit comme un miroir qui dévie simplement le pointeur d’instruction. Notez également que le flux de contrôle enveloppe les bords trois fois, une fois du bas vers le haut, une fois du coin droit vers la rangée inférieure et enfin du coin inférieur droit vers le coin gauche pour vérifier à nouveau la situation. Notez également que ce.
ne sont pas des opérations.Cela laisse le code linéaire suivant pour une seule itération:
Nous sommes maintenant de retour là où nous avons commencé, sauf que les trois arêtes ont changé de rôle de manière cyclique (le C d' origine prend maintenant le rôle de B et le B d' origine le rôle de A ...). En effet, nous avons repoussé les entrées
A
etB
avecB
etA % B
, respectivement.Une fois
A % B
(sur le bord C ) est égal à zéro, le GCD se trouve sur le bord B . Encore une fois, le>
juste dévie l'adresse IP, donc sur le chemin rouge nous exécutons:la source
Code machine x86 little-endian 32 bits, 14 octets
Généré en utilisant
nasm -f bin
d231 f3f7 d889 d389 db85 f475
la source
cdq
et signéidiv
, et un octetxchg eax, r32
au lieu demov
. Pour le code 32 bits:inc/loop
au lieu detest/jnz
(je ne voyais pas comment utiliserjecxz
, et il n'y en avait pasjecxnz
). J'ai posté ma version finale en tant que nouvelle réponse car je pense que les changements sont suffisamment importants pour le justifier.T-SQL, 153
169octetsQuelqu'un a parlé de la pire langue pour jouer au golf?
Crée une fonction table
qui utilise une requête récursive pour élaborer les diviseurs communs. Ensuite, il renvoie le maximum. Utilise maintenant l'algorithme euclidien pour déterminer le GCD dérivé de ma réponse ici .Exemple d'utilisation
la source
Gelée, 7 octets
Implémentation récursive de l'algorithme euclidien. Essayez-le en ligne!
Si les fonctions intégrées n'étaient pas interdites,
g
(1 octet, GCD intégré) obtiendrait un meilleur score.Comment ça marche
la source
Haskell, 19 octets
Exemple d'utilisation:
45 # 35
->5
.Euclid, encore.
PS: bien sûr, il y a aussi une fonction intégrée
gcd
.la source
0
ou continuant avec le module.Prelude
Python 3, 31
Sauvegardé 3 octets grâce à Sp3000.
la source
from math import*;gcd
g=lambda a,b:b and g(b,a%b)or a
MATL ,
11 à9 octetsPersonne ne semble avoir utilisé la force brute jusqu'à présent, alors la voici.
L'entrée est un tableau de colonnes avec les deux nombres (en utilisant
;
comme séparateur).Essayez-le en ligne! ou vérifier tous les cas de test .
Explication
la source
C, 38 octets
la source
g
lieu degcd
.C, 28 octets
Une fonction assez simple implémentant l'algorithme d'Euclid. Peut-être que l'on peut être plus court en utilisant un autre algorithme.
Si on écrit un petit wrapper principal
alors on peut tester quelques valeurs:
la source
Labyrinthe , 18 octets
Se termine avec une erreur, mais le message d'erreur passe à STDERR.
Essayez-le en ligne!
Cela ne semble pas encore optimal, mais je ne vois pas de moyen de compresser la boucle en dessous de 3x3 pour le moment.
Explication
Ceci utilise l'algorithme euclidien.
Tout d'abord, il y a un bit linéaire pour lire l'entrée et entrer dans la boucle principale. Le pointeur d'instruction (IP) commence dans le coin supérieur gauche, en allant vers l'est.
Nous entrons maintenant dans une sorte de boucle while-do qui calcule l’algorithme euclidien. Les sommets des piles contiennent
a
etb
(au-dessus d'une quantité implicite infinie de zéros, mais nous n'en aurons pas besoin). Nous allons représenter les piles d'un côté à l'autre, en grandissant les unes vers les autres:La boucle se termine une fois
a
est zéro. Une itération de boucle fonctionne comme suit:Vous pouvez voir, nous avons remplacé
a
etb
avecb%a
eta
respectivement.Enfin, une fois
b%a
égal à zéro, l’IP continue de se déplacer vers l’est et exécute:la source
Julia,
2115 octetsImplémentation récursive de l'algorithme euclidien. Essayez-le en ligne!
Si les fonctions intégrées n'étaient pas interdites,
gcd
(3 octets, GCD intégré) obtiendrait un meilleur score.Comment ça marche
la source
Cubix , 10
12octetsEssayez-le ici
Cela enveloppe le cube comme suit:
Utilise la méthode euclidienne.
II
Deux nombres sont saisis à partir de STDIN et mis sur la pile. Le/
flux reflète%
le haut de la pile. Le reste à gauche sur le dessus de la pile?
Si TOS 0 puis effectuez le, sinon tourner à droitev
Sinon 0 puis rediriger vers le bas etu
tourner à droite à deux reprises sur le mod/
Si 0 go autour du cube au réflecteur;
chute TOS,O
sortie TOS et@
finla source
0,x
etx,0
... alors je suis tombé sur cette question. Joli!C #, 24 octets
la source
Lot Windows, 76 octets
Fonction récursive. Appelez ça comme
GCD a b
avec un nom de fichiergcd
.la source
MATL, 7 octets
Essayez-le en ligne!
Explication
Comme nous ne pouvons pas utiliser explicitement la fonction GCD intégrée (
Zd
dans MATL), j'ai exploité le fait que le plus petit commun multiple dea
etb
parfois le plus grand dénominateur commun dea
etb
est égal au produit dea
etb
.la source
*1MZm/
Raquette (schéma), 44 octets
Implémentation Euclid dans Racket (Scheme)
Edit: Je n'ai pas vu la solution de @Numeri lol. D'une manière ou d'une autre, nous avons obtenu exactement le même code indépendamment
la source
> <> , 32 octets
Accepte deux valeurs de la pile et applique l'algorithme euclidien pour produire leur GCD.
Vous pouvez l'essayer ici !
Pour une réponse bien meilleure dans> <>, jetez un coup d' œil à Sok !
la source
ReRegex , 23 octets
Fonctionne de la même manière que la réponse Retina.
Essayez-le en ligne!
la source
GML, 57 octets
la source
Delphes 7, 148
Eh bien, je pense avoir trouvé la nouvelle pire langue pour le golf.
la source
Hoon, 20 octets
-
Hoon # 2, 39 octets
Bizarrement, la seule implémentation dans stdlib de Hoon pour GCD est celle utilisée pour son crypto RSA, qui renvoie également d'autres valeurs. Je dois l'envelopper dans une fonction qui ne prend que
d
de la sortie.L'autre implémentation est simplement la définition GCD récursive par défaut.
la source
Python 3.5,
708273 octets:Le
not
dans ce cas s'assurera que la somme de tous les nombres de*args
moduloi
est égale à zéro.De plus, cette fonction lambda peut maintenant prendre autant de valeurs que vous le souhaitez, à condition que le nombre de valeurs soit
>=2
identique, contrairement à lagcd
fonction du module mathématique. Par exemple, il peut prendre les valeurs2,4,6,8,10
et renvoyer le GCD correct de 2.la source
Ruby, 23 octets
rappelez-vous que les blocs de rubis sont appelés avec g [...] ou g.call (...), au lieu de g (...)
crédits partiels à voidpigeon
la source
g.call(a,b)
vous pouvez utiliserg[a,b]
. Au lieu deproc{|a,b|
, vous pouvez utiliser->a,b{
.b>0
placeb<=0
et en inversant l'ordre des autres opérandes.Code machine ARM, 12 octets:
Assemblée:
Actuellement, je ne peux pas compiler cela, mais chaque instruction dans ARM prend 4 octets. Il pourrait probablement être joué en mode THUMB-2.
la source
r0 > r1
alorssublt
ne fera rien (lelt
prédicat est faux) etbne
sera une boucle infinie. Je pense que vous avez besoin d'un échange sinonlt
, donc la même boucle peut faireb-=a
oua-=b
selon les besoins. Ou une négation si le sous-produit porter (aka emprunter).cmp r0, r1
/subgt r0, r0, r1
/sublt r1, r1, r0
/bne gcd
. C'est 16B dans les instructions ARM, peut-être 12 dans les instructions thumb2?sub ecx, eax
/jae .no_swap
/add ecx,eax
/xchg ecx,eax
/jne
. Donc, au lieu d'un cmp, je viens de sous, puis annulez et échangez si le sous aurait dû aller dans l'autre sens. J'ai testé cela et ça marche. (add
ne fera pas lajne
sortie au mauvais moment, car elle ne peut produire un zéro que si l'une des entrées était zéro pour commencer, et nous ne le supportons pas. Mise à jour: nous devons supporter l'une ou l'autre des entrées étant zéro: /)ite
instruction: if-then-else. Devrait être parfait pour cmp / sous un sens / sous l’autre.TI-Basic, 10 octets
Non-competing due to new rule forbidding gcd built-ins
Solution de 17 octets sans
gcd(
built-inNon-competing due to new rule forbidding lcm built-ins
27 byte solution without
gcd(
orlcm(
built-in:35 byte recursive solution without
gcd(
orlcm(
built-ins (requires 2.53 MP operating system or higher, must be namedprgmG
):You would pass arguments to the recursive variant as
{A,B}
so for example{1071, 462}:prgmG
would yield21
.la source
prgmG
.05AB1E, 10 bytes
Code:
Try it online!
With built-ins:
Explanation:
Try it online! or Try with multiple numbers.
la source
Oracle SQL 11.2,
104118 bytesFixed for input of 0
la source
SELECT MAX(LEVEL)FROM DUAL WHERE MOD(:1,LEVEL)+MOD(:2,LEVEL)=0 CONNECT BY LEVEL<=:1+:2;
><>, 12+3 = 15 bytes
Expects the input numbers to be present on the stack, so +3 bytes for the
-v
flag. Try it online!Another implementation of the Euclidean algorithm.
la source