Plus grand diviseur commun

40

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 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
Mike Shlanta
la source
1
Si nous permettons à asm d'avoir des entrées dans tous les registres qui conviennent, et si le résultat dans n'importe quel reg est pratique, nous devrions absolument permettre des fonctions, voire des fragments de code (c'est-à-dire un corps de fonction). Faire de ma réponse une fonction complète ajouterait environ 4B avec une convention d'appel de registre telle que l'appel de vecteur 32 bits de MS (un xchg eax, un mov et un ret), ou davantage avec une convention d'appel de pile.
Peter Cordes
@PeterCordes Désolé, j'aurais dû être plus précis. Vous pouvez tout simplement écrire le code nécessaire à l'ours, mais si vous aviez l'amabilité d'inclure un moyen d'exécuter ledit code, ce serait bien.
Mike Shlanta
Donc, ne comptez que le code gcd, mais fournissez le code environnant afin que les gens puissent vérifier / expérimenter / améliorer? BTW, vos cas de test avec zéro comme l’une des deux entrées cassent nos réponses de code machine x86. div par zéro déclenche une exception matérielle. Sous Linux, votre processus obtient a SIGFPE.
Peter Cordes
3
@CodesInChaos Les limitations de mémoire et de temps sont généralement ignorées tant que l'algorithme lui-même peut en principe gérer toutes les entrées. La règle vise uniquement à éviter le codage en dur des limites arbitraires pour les boucles qui limitent artificiellement l'algorithme à une plage d'entrées inférieure. Je ne vois pas trop comment l'immutabilité entre en jeu?
Martin Ender
1
gcd (0, n) is error not n
RosLuP

Réponses:

37

Rétine , 16 ans

^(.+)\1* \1+$
$1

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

\d+
$*
^(.+)\1* \1+$
$1
1+
$.&

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.

Trauma numérique
la source
2
Je voudrais voter pour cela plus
MickyT
Devrait être bon avec la plage de numéros maintenant. J'ai modifié la spécification (avec la permission OPs) pour n'exiger que la plage de nombres naturelle de la langue (ou [0,255] si c'est plus). Vous devrez cependant supporter les zéros, bien que je pense que changer votre +s en *s devrait faire. Et vous pouvez raccourcir considérablement la dernière étape du code long en le réduisant à 1.
Martin Ender
2
Pour référence ultérieure, je viens de trouver une solution de 16 octets alternatif qui fonctionne pour un nombre quelconque d'entrées (dont un) de sorte qu'il pourrait être plus utile dans d' autres contextes: retina.tryitonline.net/...
Martin Ender
1
Je viens de remarquer que ni vos solutions ni celle de mon commentaire ci-dessus n’ont besoin de la ^, car il est impossible que la correspondance échoue à partir de la position de départ.
Martin Ender
28

Code machine i386 (x86-32), 8 octets (9 b pour non signé)

+ 1B si nous devons gérer b = 0les entrées.

amd64 (x86-64) code machine, 9 octets (10B pour non signé, ou 14B 13B pour des entiers non signés 64b signés ou)

10 9B pour unsigned sur amd64 qui rompt avec l'une des entrées = 0


Les entrées sont des entiers signés 32 bits non nuls dans eaxet ecx. Sortie en eax.

## 32bit code, signed integers:  eax, ecx
08048420 <gcd0>:
 8048420:       99                      cdq               ; shorter than xor edx,edx
 8048421:       f7 f9                   idiv   ecx
 8048423:       92                      xchg   edx,eax    ; there's a one-byte encoding for xchg eax,r32.  So this is shorter but slower than a mov
 8048424:       91                      xchg   ecx,eax    ; eax = divisor(from ecx), ecx = remainder(from edx), edx = quotient(from eax) which we discard
    ; loop entry point if we need to handle ecx = 0
 8048425:       41                      inc    ecx        ; saves 1B vs. test/jnz in 32bit mode
 8048426:       e2 f8                   loop   8048420 <gcd0>
08048428 <gcd0_end>:
 ; 8B total
 ; result in eax: gcd(a,0) = a

Cette structure de boucle échoue dans le cas de test où ecx = 0. ( divprovoque une #DEexécution matérielle lors d'une division par zéro. (Sous Linux, le noyau fournit une SIGFPE(exception de virgule flottante)). Si le point d'entrée de la boucle était juste avant le inc, 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 cdqest un octet plus court que xor 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 ( xchg3 uops sur les processeurs Intel et looptrè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,edxau lieu de cdqcoûterait un octet. divest de la même taille que idiv, et tout le reste peut rester identique ( xchgpour le transfert de données et inc/loopfonctionne toujours).

Fait intéressant, pour les opérandes de taille 64 bits ( raxet rcx), les versions signée et non signée ont la même taille. La version signée nécessite un préfixe REX pour cqo(2B), mais la version non signée peut toujours utiliser 2B xor edx,edx.

Dans le code 64 bits, inc ecxcorrespond à 2B: le code sur un octet inc r32et les dec r32codes opération ont été réaffectés en tant que préfixes REX. inc/loopn'enregistre aucune taille de code en mode 64 bits, donc vous pourriez aussi bien test/jnz. Opérer sur des entiers 64 bits ajoute un octet supplémentaire par instruction dans les préfixes REX, à l'exception de loopou jnz. Il est possible que le reste ait tous les zéros dans le bas 32b (par exemple gcd((2^32), (2^32 + 1))), nous avons donc besoin de tester tout le rcx et nous ne pouvons pas sauvegarder un octet avec test ecx,ecx. Cependant, l’ jrcxzinsn le plus lent n’est que 2B, et nous pouvons le placer en haut de la boucle pour gérer ecx=0en entrée :

## 64bit code, unsigned 64 integers:  rax, rcx
0000000000400630 <gcd_u64>:
  400630:       e3 0b                   jrcxz  40063d <gcd_u64_end>   ; handles rcx=0 on input, and smaller than test rcx,rcx/jnz
  400632:       31 d2                   xor    edx,edx                ; same length as cqo
  400634:       48 f7 f1                div    rcx                      ; REX prefixes needed on three insns
  400637:       48 92                   xchg   rdx,rax
  400639:       48 91                   xchg   rcx,rax
  40063b:       eb f3                   jmp    400630 <gcd_u64>
000000000040063d <gcd_u64_end>:
## 0xD = 13 bytes of code
## result in rax: gcd(a,0) = a

Programme de test complet exécutable, y compris un programme mainqui printf("...", 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 subproduit 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)

int gcd(int a, int b) {
    asm (// ".intel_syntax noprefix\n"
        // "jmp  .Lentry%=\n" // Uncomment to handle div-by-zero, by entering the loop in the middle.  Better: `jecxz / jmp` loop structure like the 64b version
        ".p2align 4\n"                  // align to make size-counting easier
         "gcd0:   cdq\n\t"              // sign extend eax into edx:eax.  One byte shorter than xor edx,edx
         "        idiv    ecx\n"
         "        xchg    eax, edx\n"   // there's a one-byte encoding for xchg eax,r32.  So this is shorter but slower than a mov
         "        xchg    eax, ecx\n"   // eax = divisor(ecx), ecx = remainder(edx), edx = garbage that we will clear later
         ".Lentry%=:\n"
         "        inc     ecx\n"        // saves 1B vs. test/jnz in 32bit mode, none in 64b mode
         "        loop    gcd0\n"
        "gcd0_end:\n"
         : /* outputs */  "+a" (a), "+c"(b)
         : /* inputs */   // given as read-write outputs
         : /* clobbers */ "edx"
        );
    return a;
}

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 noprefixmode, parce que toutes les insns utilisées sont simples ou sans opérande ou xchg. Ce n'est pas vraiment une observation utile.

Peter Cordes
la source
2
@ MikeSlanta: Merci. Si vous aimez optimiser asm, consultez certaines de mes réponses sur stackoverflow. :)
Peter Cordes
2
@MikeShlanta: J'ai trouvé une utilisation jrcxzaprè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.
Peter Cordes
Pourquoi ne pourriez-vous pas utiliser jecxzla version 32 bits avec le même effet?
Cody Grey
1
@CodyGray: inc/loop3 octets dans la version 32 bits, mais 4B dans la version 64 bits. Cela signifie que dans la version 64 bits uniquement, l'utilisation jrcxzet la jmpsubstitution d' octets supplémentaires ne coûtent rien inc / loop.
Peter Cordes
Ne pouvez-vous pas indiquer le milieu comme une entrée?
l4m2
14

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:

enter image description here

Voici le diagramme de flux de contrôle:

enter image description here

Le flux de contrôle commence sur le chemin gris avec un bit linéaire court pour l'entrée:

?    Read first integer into memory edge A.
'    Move MP backwards onto edge B.
?    Read second integer into B.

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:

{    Move MP forward onto edge C.
'}   Move to A and back to C. Taken together this is a no-op.
=    Reverse the direction of the MP so that it now points at A and B. 
%    Compute A % B and store it in C.
)(   Increment, decrement. Taken together this is a no-op, but it's
     necessary to ensure that IP wraps to the bottom row instead of
     the top row.

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 Aet Bavec Bet A % 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:

}    Move MP to edge B.
!    Print its value as an integer.
@    Terminate the program.
Martin Ender
la source
9

Code machine x86 little-endian 32 bits, 14 octets

Généré en utilisant nasm -f bin

d231 f3f7 d889 d389 db85 f475

    gcd0:   xor     edx,edx
            div     ebx
            mov     eax,ebx
            mov     ebx,edx
            test    ebx,ebx
            jnz     gcd0
Mike Shlanta
la source
4
Je l'ai réduit à 8 octets en utilisant cdqet signé idiv, et un octet xchg eax, r32au lieu de mov. Pour le code 32 bits: inc/loopau lieu de test/jnz(je ne voyais pas comment utiliser jecxz, et il n'y en avait pas jecxnz). J'ai posté ma version finale en tant que nouvelle réponse car je pense que les changements sont suffisamment importants pour le justifier.
Peter Cordes
9

T-SQL, 153 169 octets

Quelqu'un a parlé de la pire langue pour jouer au golf?

CREATE FUNCTION G(@ INT,@B INT)RETURNS TABLE RETURN WITH R AS(SELECT 1D,0R UNION ALL SELECT D+1,@%(D+1)+@B%(D+1)FROM R WHERE D<@ and D<@b)SELECT MAX(D)D FROM R WHERE 0=R

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

SELECT * 
FROM (VALUES
        (15,45),
        (45,15),
        (99,7),
        (4,38)
    ) TestSet(A, B)
    CROSS APPLY (SELECT * FROM G(A,B))GCD

A           B           D
----------- ----------- -----------
15          45          15
45          15          15
99          7           1
4           38          2

(4 row(s) affected)
MickyT
la source
1
Jésus qui est verbeux.
Cyoce
9

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

ṛß%ðḷṛ?  Main link. Arguments: a, b

   ð     Convert the chain to the left into a link; start a new, dyadic chain.
 ß       Recursively call the main link...
ṛ %        with b and a % b as arguments.
     ṛ?  If the right argument (b) is non-zero, execute the link.
    ḷ    Else, yield the left argument (a).
Dennis
la source
Cela ressemble presque à tricher haha, je dois préciser que les réponses ne peuvent pas utiliser de butlins ...
Mike Shlanta
13
Si vous décidez de le faire, vous devriez le faire rapidement. Cela invaliderait actuellement trois des réponses.
Dennis
Notez que la longueur spécifiée est en octets - ces caractères sont généralement> 1 octet en UTF8.
cortices
8
@cortices Oui, tous les concours de golf de code sont marqués en octets par défaut. Cependant, Jelly n'utilise pas UTF-8, mais une page de code personnalisée qui code chacun des 256 caractères compris en tant qu'octet unique.
Dennis
@ Dennis ah, intelligent.
cortices
7

Haskell, 19 octets

a#0=a
a#b=b#rem a b

Exemple d'utilisation: 45 # 35-> 5.

Euclid, encore.

PS: bien sûr, il y a aussi une fonction intégrée gcd.

nimi
la source
vous devez expliquer le truc qui inverse l'ordre d'entrée pour éviter le contrôle conditionnel
fier haskeller
@proudhaskeller: quel tour? Tout le monde utilise cet algorithme, c’est-à-dire s’arrêtant 0ou continuant avec le module.
Nimi
Peu importe, tout le monde utilise le truc
fier haskeller
Ceci, moins joué au golf, est presque exactement ce qu'il y a à fairePrelude
Michael Klein
6

Python 3, 31

Sauvegardé 3 octets grâce à Sp3000.

g=lambda a,b:b and g(b,a%b)or a
Morgan Thrapp
la source
3
En Python 3.5+:from math import*;gcd
Sp3000 le
@ Sp3000 Nice, je ne savais pas qu'ils l'avaient déplacé en maths.
Morgan Thrapp
1
Tant que vous y êtes:g=lambda a,b:b and g(b,a%b)or a
Sp3000 le
@ Sp3000 Merci! Je viens de terminer une solution récursive, mais c'est encore mieux que ce que j'avais.
Morgan Thrapp
Les fonctions intégrées pour GCD et LCM ne sont pas autorisées. La deuxième solution ne serait donc pas valide.
mbomb007
6

MATL , 11 à 9 octets

Personne ne semble avoir utilisé la force brute jusqu'à présent, alors la voici.

ts:\a~f0)

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

t     % Take input [a;b] implicitly. Duplicate
s     % Sum. Gives a+b
:     % Array [1,2,...,a+b]
\     % Modulo operation with broadcast. Gives a 2×(a+b) array
a~    % 1×(a+b) array that contains true if the two modulo operations gave 0
f0)   % Index of last true value. Implicitly display
Luis Mendo
la source
5

C, 38 octets

g(x,y){while(x^=y^=x^=y%=x);return y;}
Comment Chen
la source
1
Vous devez inclure la définition de la fonction dans votre décompte.
Rɪᴋᴇʀ
1
@Riker désolé pour cela, j'ai ajouté la définition et mis à jour le décompte
How Chen
Vous pouvez enregistrer deux octets en nommant la fonction au glieu de gcd.
Steadybox
@Steadybox ok, oui, pour la première fois, rejoignez cette communauté :)
How Chen
1
Bienvenue chez PPCG!
Rɪᴋᴇʀ
4

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.

g(a,b){return b?g(b,a%b):a;}

Si on écrit un petit wrapper principal

int main(int argc, char **argv)
{
  printf("gcd(%d, %d) = %d\n", atoi(argv[1]), atoi(argv[2]), g(atoi(argv[1]), atoi(argv[2])));
}

alors on peut tester quelques valeurs:

$ ./gcd 6 21
gcd (6, 21) = 3
$ ./gcd 21 6
gcd (21, 6) = 3
$ ./gcd 6 8
gcd (6, 8) = 2
$ ./gcd 1 1
gcd (1, 1) = 1
$ ./gcd 6 16
gcd (6, 16) = 2
27 244 $
gcd (27, 244) = 1
CL-
la source
4

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.

?    Read first integer from STDIN and push onto main stack.
}    Move the integer over to the auxiliary stack.
     The IP now hits a dead end so it turns around.
?    Read the second integer.
     The IP hits a corner and follows the bend, so it goes south.
:    Duplicate the second integer.
)    Increment.
     The IP is now at a junction. The top of the stack is guaranteed to be
     positive, so the IP turns left, to go east.
"    No-op.
%    Modulo. Since `n % (n+1) == n`, we end up with the second input on the stack.

Nous entrons maintenant dans une sorte de boucle while-do qui calcule l’algorithme euclidien. Les sommets des piles contiennent aet b(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:

    Main     Auxiliary
[ ... 0 a  |  b 0 ... ]

La boucle se termine une fois aest zéro. Une itération de boucle fonctionne comme suit:

=    Swap a and b.           [ ... 0 b  |  a 0 ... ]
{    Pull a from aux.        [ ... 0 b a  |  0 ... ]
:    Duplicate.              [ ... 0 b a a  |  0 ... ]
}    Move a to aux.          [ ... 0 b a  |  a 0 ... ]
()   Increment, decrement, together a no-op.
%    Modulo.                 [ ... 0 (b%a)  |  a 0 ... ]

Vous pouvez voir, nous avons remplacé aet bavec b%aet arespectivement.

Enfin, une fois b%aégal à zéro, l’IP continue de se déplacer vers l’est et exécute:

{    Pull the non-zero value, i.e. the GCD, over from aux.
!    Print it.
     The IP hits a dead end and turns around.
{    Pull a zero from aux.
%    Attempt modulo. This fails due to division by 0 and the program terminates.
Martin Ender
la source
4

Julia, 21 15 octets

a\b=a>0?b%a\a:b

Implé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

a\b=             Redefine the binary operator \ as follows:
    a>0?     :       If a > 0:
        b%a\a        Resursively apply \ to b%a and a. Return the result.
              b      Else, return b.
Dennis
la source
4

Cubix , 10 12 octets

?v%uII/;O@

Essayez-le ici

Cela enveloppe le cube comme suit:

    ? v
    % u
I I / ; O @ . .
. . . . . . . .
    . .
    . .

Utilise la méthode euclidienne.

IIDeux 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 à droite
vSinon 0 puis rediriger vers le bas et utourner à droite à deux reprises sur le mod
/Si 0 go autour du cube au réflecteur
;chute TOS, Osortie TOS et @fin

MickyT
la source
Je viens d'écrire une réponse Cubix sur 12 octets, puis j'ai commencé à faire défiler les réponses pour voir si je devais gérer les deux 0,xet x,0... alors je suis tombé sur cette question. Joli!
ETHproductions
4

C #, 24 octets

x=(a,b)=>b<1?a:x(b,a%b);
Morgan Thrapp
la source
3

Lot Windows, 76 octets

Fonction récursive. Appelez ça comme GCD a bavec un nom de fichier gcd.

:g
if %2 equ 0 (set f=%1
goto d)
set/a r=%1 %% %2
call :g %2 %r%
:d
echo %f%
Timtech
la source
3

MATL, 7 octets

pG1$Zm/

Essayez-le en ligne!

Explication

Comme nous ne pouvons pas utiliser explicitement la fonction GCD intégrée ( Zddans MATL), j'ai exploité le fait que le plus petit commun multiple de aet bparfois le plus grand dénominateur commun de aet best égal au produit de aet b.

p       % Grab the input implicitly and multiply the two elements
G       % Grab the input again, explicitly this time
1$Zm    % Compute the least-common multiple
/       % Divide the two to get the greatest common denominator
Suever
la source
Vous pouvez enregistrer un octet avec deux entrées distinctes:*1MZm/
Luis Mendo
3

Raquette (schéma), 44 octets

Implémentation Euclid dans Racket (Scheme)

(define(g a b)(if(= 0 b)a(g b(modulo a b))))

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

kronicmage
la source
Est-ce que cela fonctionne dans les deux?
NoOneIsHere
@NoOneIsHere ouais ça marche à la fois
kronicmage
3

> <> , 32 octets

::{::}@(?\=?v{:}-
.!09}}${{/;n/>

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 !

Aaron
la source
1
J'ai trouvé une nouvelle langue aujourd'hui :)
nsane
3

ReRegex , 23 octets

Fonctionne de la même manière que la réponse Retina.

^(_*)\1* \1*$/$1/#input

Essayez-le en ligne!

ATaco
la source
2

GML, 57 octets

a=argument0
b=argument1
while b{t=b;b=a mod b;a=t}return a
Timtech
la source
2

Delphes 7, 148

Eh bien, je pense avoir trouvé la nouvelle pire langue pour le golf.

unit a;interface function g(a,b:integer):integer;implementation function g(a,b:integer):integer;begin if b=0then g:=a else g:=g(b,a mod b);end;end.
Morgan Thrapp
la source
Oh, je ne sais pas, la parenthèse est assez médiocre pour le golf
MickyT
2

Hoon, 20 octets

|=
{@ @}
d:(egcd +<)

-

Hoon # 2, 39 octets

|=
{a/@ b/@}
?~
b
a
$(a b, b (mod a b))

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 qued de la sortie.

L'autre implémentation est simplement la définition GCD récursive par défaut.

RenderSettings
la source
2

Python 3.5, 70 82 73 octets:

lambda*a:max([i for i in range(1,max(*a)+1)if not sum(g%i for g in[*a])])

Le notdans ce cas s'assurera que la somme de tous les nombres de *argsmodulo iest é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 >=2identique, contrairement à la gcdfonction du module mathématique. Par exemple, il peut prendre les valeurs 2,4,6,8,10et renvoyer le GCD correct de 2.

R. Kap
la source
1
Vous êtes en état d'arrestation pour des noms de variable multichar. (Ou arguments de fonction, mais peu importe)
CalculatorFeline
2

Ruby, 23 octets

g=->a,b{b>0?a:g[b,a%b]}

rappelez-vous que les blocs de rubis sont appelés avec g [...] ou g.call (...), au lieu de g (...)

crédits partiels à voidpigeon

Luis Masuelli
la source
2
Au lieu de g.call(a,b)vous pouvez utiliser g[a,b]. Au lieu de proc{|a,b|, vous pouvez utiliser ->a,b{.
lunaire
1
Vous pouvez également enregistrer un octet en utilisant à la b>0place b<=0et en inversant l'ordre des autres opérandes.
déplacement le
2

Code machine ARM, 12 octets:

Assemblée:

gcd: cmp r0, r1
     sublt r0, r0, r1
     bne gcd

Actuellement, je ne peux pas compiler cela, mais chaque instruction dans ARM prend 4 octets. Il pourrait probablement être joué en mode THUMB-2.

mouche en polystyrène
la source
Bon boulot tout homme qui fait ça dans le code machine obtient de moi des accessoires sérieux.
Mike Shlanta
Cela semble être une tentative de l’algorithme d’Euclide d’utiliser uniquement la soustraction , mais je ne pense pas que cela fonctionne. Si r0 > r1alors subltne fera rien (le ltprédicat est faux) et bnesera une boucle infinie. Je pense que vous avez besoin d'un échange sinon lt, donc la même boucle peut faire b-=aou a-=bselon les besoins. Ou une négation si le sous-produit porter (aka emprunter).
Peter Cordes
Ce guide de jeu d’instructions ARM utilise en fait un algorithme GCD de soustraction comme exemple de prédiction. (p. 25). Ils utilisent 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?
Peter Cordes
1
Sur x86, j'ai géré 9 octets avec: 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. ( addne fera pas la jnesortie 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: /)
Peter Cordes
Pour Thumb2, il existe une iteinstruction: if-then-else. Devrait être parfait pour cmp / sous un sens / sous l’autre.
Peter Cordes
2

TI-Basic, 10 octets

Prompt A,B:gcd(A,B

Non-competing due to new rule forbidding gcd built-ins


Solution de 17 octets sansgcd( built-in

Prompt A,B:abs(AB)/lcm(A,B

Non-competing due to new rule forbidding lcm built-ins


27 byte solution without gcd( or lcm( built-in:

Prompt A,B:While B:B→T:BfPart(A/B→B:T→A:End:A

35 byte recursive solution without gcd( or lcm( built-ins (requires 2.53 MP operating system or higher, must be named prgmG):

If Ans(2:Then:{Ans(2),remainder(Ans(1),Ans(2:prgmG:Else:Disp Ans(1:End

You would pass arguments to the recursive variant as {A,B} so for example {1071, 462}:prgmG would yield 21.

Timtech
la source
Color me impressed.
Mike Shlanta
You should probably mention that the last one needs to be saved as prgmG.
a spaghetto
2

05AB1E, 10 bytes

Code:

EàF¹N%O>iN

Try it online!


With built-ins:

¿

Explanation:

¿   # Implicit input, computes the greatest common divisor.
    # Input can be in the form a \n b, which computes gcd(a, b)
    # Input can also be a list in the form [a, b, c, ...], which computes the gcd of
      multiple numbers.

Try it online! or Try with multiple numbers.

Adnan
la source
2

Oracle SQL 11.2, 104 118 bytes

SELECT MAX(:1+:2-LEVEL+1)FROM DUAL WHERE(MOD(:1,:1+:2-LEVEL+1)+MOD(:2,:1+:2-LEVEL+1))*:1*:2=0 CONNECT BY LEVEL<=:1+:2;

Fixed for input of 0

Jeto
la source
Does not work correctly if one of inputs is zero.
Egor Skriptunoff
This should save you a few SELECT MAX(LEVEL)FROM DUAL WHERE MOD(:1,LEVEL)+MOD(:2,LEVEL)=0 CONNECT BY LEVEL<=:1+:2;
MickyT
2

><>, 12+3 = 15 bytes

:?!\:}%
;n~/

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.

Sok
la source