Maior Divisor Comum


40

Sua tarefa é calcular o maior divisor comum (GCD) de dois inteiros dados no menor número de bytes de código possível.

Você pode escrever um programa ou função, recebendo entrada e retornando saída através de qualquer um dos nossos métodos padrão aceitos (incluindo STDIN / STDOUT, parâmetros de função / valores de retorno, argumentos de linha de comando, etc.).

A entrada será dois números inteiros não negativos. Você deve conseguir lidar com o intervalo completo suportado pelo tipo inteiro padrão do seu idioma ou com o intervalo [0,255], o que for maior. Você tem a garantia de que pelo menos uma das entradas será diferente de zero.

Você não tem permissão para usar os componentes internos que computam o GCD ou o LCM (mínimo múltiplo comum).

Aplicam-se as regras padrão de .

Casos de teste

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

11
Se estamos permitindo que o asm tenha entradas em quaisquer registros convenientes e o resultado em qualquer registro conveniente, devemos definitivamente permitir funções, ou mesmo fragmentos de código (ou seja, apenas um corpo de função). Tornar minha resposta uma função completa adicionaria cerca de 4B a uma convenção de chamada de registro, como a chamada de vetor de 32 bits da MS (uma xchg eax, uma mov e uma ret) ou mais com uma convenção de chamada de pilha.
Peter Cordes

@ PeterCordes Desculpe, eu deveria ter sido mais específico. Você pode simplesmente escrever o código necessário do urso, mas se você tiver a gentileza de incluir uma maneira de executar o código, seria bom.
Mike Shlanta

Portanto, conte apenas o código gcd, mas forneça o código ao redor para que as pessoas possam verificar / experimentar / melhorar? BTW, seus casos de teste com zero, como uma das duas entradas, quebram nossas respostas ao código de máquina x86. div por zero gera uma exceção de hardware. No Linux, seu processo recebe um SIGFPE.
Peter Cordes

3
@CodesInChaos As limitações de memória e tempo são geralmente ignoradas, desde que o próprio algoritmo possa, em princípio, lidar com todas as entradas. A regra visa apenas evitar que as pessoas codifiquem limites arbitrários para loops que limitam artificialmente o algoritmo a um intervalo menor de entradas. Não vejo bem como a imutabilidade entra nisso?
10138 Martin Ender

11
mcd (0, n) é erro não n
RosLuP 18/03

Respostas:


37

Retina , 16

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

Isso não usa o algoritmo de Euclid - em vez disso, encontra o GCD usando grupos correspondentes a expressões regulares.

Experimente online. - Este exemplo calcula o MDC (8,12).

Entrada como 2 números inteiros separados por espaço. Observe que a E / S está unária. Se isso não for aceitável, podemos fazer o seguinte:

Retina, 30

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

Experimente online.

Como @ MartinBüttner aponta, isso se desfaz de grandes números (como geralmente é o caso de algo unário). No mínimo, uma entrada de INT_MAX exigirá a alocação de uma sequência de 2 GB.


2
Eu gostaria de votar mais neste
tópico

Agora deve estar bem com o intervalo de números. Alterei a especificação (com a permissão do OP) para exigir apenas o intervalo de número natural do idioma (ou [0,255], se houver mais). Você terá que suportar zeros, embora eu ache que mudar seus +s para *s deve fazer. E você pode reduzir significativamente o último estágio do código longo, reduzindo-o para 1.
Martin Ender

2
Para referência futura, acabei de encontrar uma solução alternativa de 16 bytes que funciona para um número arbitrário de entradas (incluindo uma), para que possa ser mais útil em outros contextos: retina.tryitonline.net/…
Martin Ender

11
Só notei que nem as suas soluções nem a do meu comentário acima precisam disso ^, porque é impossível a partida falhar da posição inicial.
Martin Ender

28

código da máquina i386 (x86-32), 8 bytes (9B para não assinado)

+ 1B se precisarmos lidar b = 0com a entrada.

código de máquina amd64 (x86-64), 9 bytes (10B para não assinado ou 14B 13B para números inteiros de 64b assinados ou não)

10 9B para não assinado em amd64 que quebra com a entrada = 0


As entradas são de 32 bits zero não assinados inteiros eaxe ecx. Saída em 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

Essa estrutura de loop falha no caso de teste em que ecx = 0. ( divcausa uma #DEexecução de hardware na divisão por zero. (No Linux, o kernel fornece uma SIGFPE(exceção de ponto flutuante)). Se o ponto de entrada do loop estivesse logo antes do inc, evitaríamos o problema. A versão x86-64 pode lidar com isso gratuitamente, veja abaixo.

A resposta de Mike Shlanta foi o ponto de partida para isso . Meu loop faz a mesma coisa que o dele, mas para números inteiros assinados porque cdqé um byter menor que xor edx,edx. E sim, ele funciona corretamente com uma ou ambas as entradas negativas. A versão de Mike será mais rápida e ocupará menos espaço no cache uop ( xchgsão 3 uops nas CPUs Intel e loopé realmente lenta na maioria das CPUs ), mas essa versão vence no tamanho de código de máquina.

Inicialmente, não percebi que a pergunta exigia 32 bits não assinados . Voltar para em xor edx,edxvez de cdqcustaria um byte. divé do mesmo tamanho idive tudo o mais pode permanecer o mesmo ( xchgpara movimentação de dados e inc/loopainda funciona).

Curiosamente, para operandos de 64 bits ( raxe rcx), as versões assinadas e não assinadas têm o mesmo tamanho. A versão assinada precisa de um prefixo REX para cqo(2B), mas a versão não assinada ainda pode usar 2B xor edx,edx.

No código de 64 bits, inc ecxé 2B: o byte único inc r32e os dec r32códigos de operação foram redirecionados como prefixos REX. inc/loopnão salva nenhum tamanho de código no modo de 64 bits, então você também pode test/jnz. Operar em números inteiros de 64 bits adiciona outro byte por instrução nos prefixos REX, exceto para loopou jnz. É possível que o restante tenha todos os zeros em 32b baixo (por exemplo gcd((2^32), (2^32 + 1))), portanto, precisamos testar todo o rcx e não podemos salvar um byte test ecx,ecx. No entanto, o jrcxzinsn mais lento é apenas 2B, e podemos colocá-lo no topo do loop para lidar ecx=0com a entrada :

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

Programa de teste executável completo, incluindo um mainque executa printf("...", gcd(atoi(argv[1]), atoi(argv[2])) ); saída de origem e asm no Godbolt Compiler Explorer , para as versões 32 e 64b. Testado e funcionando para 32 bits ( -m32), 64 bits ( -m64) e x32 ABI ( -mx32) .

Também incluído: uma versão usando apenas subtração repetida , que é 9B para o sinal não assinado, mesmo para o modo x86-64, e pode receber uma de suas entradas em um registro arbitrário. No entanto, ele não pode manipular nenhuma entrada sendo 0 na entrada (ele detecta quando subproduz um zero, o que x - 0 nunca faz).

Fonte em linha GNU C asm para a versão de 32 bits (compilação com 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;
}

Normalmente eu escreveria uma função inteira no asm, mas o GNU C inline asm parece ser a melhor maneira de incluir um trecho que pode ter in / outputs em quaisquer regs que escolhermos. Como você pode ver, a sintaxe do GNU C inline asm torna asm feia e barulhenta. Também é uma maneira realmente difícil de aprender asm .

Na verdade, ele compilaria e funcionaria no .att_syntax noprefixmodo, porque todos os insns usados ​​são únicos / sem operando ou xchg. Não é realmente uma observação útil.


2
@ MikeShlanta: Obrigado. Se você gosta de otimizar o asm, dê uma olhada em algumas das minhas respostas no stackoverflow. :)
Peter Cordes

2
@ MikeShlanta: Encontrei um uso para jrcxzafinal na versão uint64_t :). Além disso, não percebi que você havia especificado como não assinado, então eu incluí contagens de bytes para isso também.
Peter Cordes

Por que você não poderia usar jecxzna versão de 32 bits para o mesmo efeito?
Cody Grey

11
@CodyGray: inc/loopsão 3 bytes na versão de 32 bits, mas 4B na versão de 64 bits. Isso significa que apenas na versão de 64 bits, não custa bytes extras para usar jrcxze em jmpvez de inc / loop.
Peter Cordes

Você não pode apontar para o meio como entrada?
l4m2

14

Hexagonia , 17 bytes

?'?>}!@<\=%)>{\.(

Desdobrado:

  ? ' ?
 > } ! @
< \ = % )
 > { \ .
  ( . .

Experimente online!

Colocá-lo na lateral 3 foi uma brisa. Raspar esses dois bytes no final não foi ... Também não estou convencido de que é o ideal, mas tenho certeza que acho que está próximo.

Explicação

Outra implementação do algoritmo euclidiano.

O programa usa três bordas da memória, que chamarei de A , B e C , com o ponteiro da memória (MP) começando como mostrado:

insira a descrição da imagem aqui

Aqui está o diagrama de fluxo de controle:

insira a descrição da imagem aqui

O fluxo de controle começa no caminho cinza com um pequeno bit linear para entrada:

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

Observe que o código agora envolve as bordas até o <canto esquerdo. Isso <atua como um ramo. Se a borda atual for zero (ou seja, o algoritmo euclidiano termina), o IP é desviado para a esquerda e segue o caminho vermelho. Caso contrário, uma iteração do algoritmo euclidiano é computada no caminho verde.

Primeiro, consideraremos o caminho verde. Observe que >e \todos atuam como espelhos que simplesmente desviam o ponteiro da instrução. Observe também que o fluxo de controle envolve as bordas três vezes, uma vez de baixo para cima, uma vez do canto direito para a linha inferior e, finalmente, do canto inferior direito para o canto esquerdo para verificar novamente a condição. Observe também que .não há operações.

Isso deixa o seguinte código linear para uma única iteração:

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

Agora estamos de volta onde começamos, exceto que as três arestas mudaram seus papéis ciclicamente (o C original agora assume o papel de B e o B original o papel de A ...). De fato, realocamos as entradas Ae Bcom Be A % B, respectivamente.

Uma vez que A % B(na extremidade C ) é zero, o MDC pode ser encontrado na borda B . Novamente o >just desvia o IP, então no caminho vermelho nós executamos:

}    Move MP to edge B.
!    Print its value as an integer.
@    Terminate the program.

9

Código de máquina x86 little-endian de 32 bits, 14 bytes

Gerado usando 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

4
Eu reduzi isso para 8 bytes usando cdqe assinado idiv, e um byte em xchg eax, r32vez de mov. Para código de 32 bits: em inc/loopvez de test/jnz(eu não conseguia ver uma maneira de usar jecxz, e não há jecxnz). Postei minha versão final como uma nova resposta, pois acho que as mudanças são grandes o suficiente para justificá-la.
Peter Cordes

9

T-SQL, 153 169 bytes

Alguém mencionou a pior linguagem para jogar golfe?

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

Cria uma função com valor de tabela que usa uma consulta recursiva para calcular os divisores comuns. Então ele retorna o máximo . Agora usa o algoritmo euclidiano para determinar o GCD derivado da minha resposta aqui .

Exemplo de uso

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)

11
Jesus que é detalhado.
Cyoce

9

Geléia, 7 bytes

ṛß%ðḷṛ?

Implementação recursiva do algoritmo euclidiano. Experimente online!

Se os embutidos não fossem proibidos, g(1 byte, GCD embutido) obteria uma pontuação melhor.

Como funciona

ṛß%ðḷṛ?  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).

Que quase se sente como enganar haha, eu possa ter de especificar que respostas não podem usar butlins ...
Mike Shlanta

13
Se você decidir fazer isso, deve fazê-lo rapidamente. No momento, invalidaria três das respostas.
7896 Dennis

Observe que o comprimento especificado está em bytes - esses caracteres são na maioria> 1 byte em UTF8.
Cortices

8
@cortices Sim, todos os concursos de código de golfe são pontuados em bytes por padrão. No entanto, o Jelly não usa UTF-8, mas uma página de código personalizada que codifica cada um dos 256 caracteres que entende como um único byte.
Dennis

@Dennis ah, inteligente.
Cortices

7

Haskell, 19 bytes

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

Exemplo de uso: 45 # 35-> 5.

Euclides, novamente.

PS: é claro que também há um built-in gcd.


você deve explicar o truque que inverte a ordem de entrada para evitar a verificação condicional
haskeller orgulhoso

@proudhaskeller: que truque? Todo mundo usa esse algoritmo, ou seja, parando 0ou continuando com o módulo.
nimi

Nevrmind, todo mundo está usando o truque
proud haskeller

Este, menos golfed, é quase exatamente o que está emPrelude
Michael Klein

6

Python 3, 31

Economizou 3 bytes graças ao Sp3000.

g=lambda a,b:b and g(b,a%b)or a

3
Em Python 3.5+:from math import*;gcd
Sp3000 7/16

@ Sp3000 Bom, eu não sabia que eles haviam mudado para matemática.
Morgan Thrapp

11
Enquanto você está nisso:g=lambda a,b:b and g(b,a%b)or a
Sp3000 07/04

@ Sp3000 Obrigado! Acabei de terminar uma solução recursiva, mas isso é ainda melhor do que eu tinha.
Morgan Thrapp

Os internos para GCD e LCM não são permitidos, portanto, a segunda solução não seria válida.
mbomb007

6

MATL , 11 9 bytes

Ninguém parece ter usado força bruta até agora, então aqui está.

ts:\a~f0)

Entrada é uma matriz de colunas com os dois números (usando ;como separador).

Experimente online! ou verifique todos os casos de teste .

Explicação

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

5

C, 38 bytes

g(x,y){while(x^=y^=x^=y%=x);return y;}

11
Você precisa incluir a definição da função no seu número de bytes.
Rɪᴋᴇʀ

11
@Riker desculpe por isso, eu adiciono a definição e atualizo a contagem
How Chen

Você pode salvar dois bytes nomeando a função apenas em gvez de gcd.
Steadybox

@Steadybox ok, sim, participe pela primeira vez desta comunidade :)
How Chen

11
Bem-vindo ao PPCG!
Rɪᴋᴇʀ

4

C, 28 bytes

Uma função bastante direta que implementa o algoritmo de Euclides. Talvez alguém possa ficar mais curto usando um algoritmo alternativo.

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

Se alguém escreve um pequeno invólucro 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])));
}

então pode-se testar alguns valores:

$ ./gcd 6 21
mcd (6, 21) = 3
$ ./gcd 21 6
mcd (21, 6) = 3
$ ./gcd 6 8
mcd (6, 8) = 2
$ ./gcd 1 1
mcd (1, 1) = 1
$ ./gcd 6 16
mcd (6, 16) = 2
$ ./gcd 27 244
mcd (27, 244) = 1

4

Labirinto , 18 bytes

?}
:
)"%{!
( =
}:{

Termina com um erro, mas a mensagem de erro vai para STDERR.

Experimente online!

Ainda não parece ótimo, mas neste momento não estou vendo uma maneira de comprimir o loop abaixo de 3x3.

Explicação

Isso usa o algoritmo euclidiano.

Primeiro, há um bit linear para ler a entrada e entrar no loop principal. O ponteiro de instrução (IP) começa no canto superior esquerdo, indo para o leste.

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

Agora entramos em uma espécie de loop while-do que calcula o algoritmo euclidiano. Os topos das pilhas contêm ae b(em cima de uma quantidade infinita implícita de zeros, mas não precisaremos deles). Representaremos as pilhas lado a lado, crescendo uma em relação à outra:

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

O loop termina quando aé zero. Uma iteração de loop funciona da seguinte maneira:

=    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 ... ]

Você pode ver, substituímos ae bpor b%ae arespectivamente.

Finalmente, uma vez que b%aé zero, o IP continua se movendo para o leste e executa:

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

4

Julia, 21 15 bytes

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

Implementação recursiva do algoritmo euclidiano. Experimente online!

Se os embutidos não fossem proibidos, gcd(3 bytes, GCD interno) obteriam uma pontuação melhor.

Como funciona

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.

4

Cubix , 10 12 bytes

?v%uII/;O@

Experimente aqui

Isso envolve o cubo da seguinte maneira:

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

Usa o método euclidiano.

IIDois números são retirados do STDIN e colocados na pilha
/Fluxo refletido
%no topo da pilha. Restante deixado no topo da pilha
?Se TOS 0, em seguida, seguir em frente, caso contrário, vire à direita
vSe não for 0, em seguida, redirecionar para baixo e uvire à direita duas vezes de volta para o mod
/Se 0 Vá ao redor do cubo para o refletor
;TOS gota, Osaída TOS e @final


Acabei de escrever uma resposta de 12 bytes do Cubix e comecei a rolar as respostas para ver se precisava lidar com ambas 0,xe x,0... então me deparei com isso. Agradável!
ETHproductions


3

Lote do Windows, 76 bytes

Função recursiva. Chame-o como GCD a bcom o nome do arquivo gcd.

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

3

MATL, 7 bytes

pG1$Zm/

Experimente Online!

Explicação

Como não podemos usar explicitamente a função GCD incorporada ( Zdem MATL), explorei o fato de que o mínimo múltiplo comum de ae bvezes o maior denominador comum de ae bé igual ao produto de ae 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

Você pode salvar um byte com duas entradas separadas:*1MZm/
Luis Mendo

3

Raquete (esquema), 44 bytes

Implementação de Euclides em Raquete (Esquema)

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

Edit: Não viu a solução de @Numeri lol. De alguma forma, obtivemos exatamente o mesmo código independentemente


Isso funciona nos dois?
NoOneIsHere

@NoOneIsHere sim ele funciona em ambos
kronicmage

3

> <> , 32 bytes

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

Aceita dois valores da pilha e aplica o algoritmo euclidiano para produzir seu GCD.

Você pode tentar aqui !

Para uma resposta muito melhor em> <>, consulte Sok's !


11
Eu encontrei uma nova linguagem de hoje :)
nSane


2

GML, 57 bytes

a=argument0
b=argument1
while b{t=b;b=a mod b;a=t}return a

2

Delfos 7, 148

Bem, acho que encontrei a nova pior linguagem para o golfe.

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.

Oh eu não sei, parentética é muito pobre para o golfe
MickyT

2

Hoon, 20 bytes

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

-

Hoon # 2, 39 bytes

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

Estranhamente, a única implementação no stdlib de Hoon para o GCD é a usada em seu criptografia RSA, que também retorna alguns outros valores. Eu tenho que envolvê-lo em uma função que leva apenas da saída.

A outra implementação é apenas a definição padrão do GCD recursivo.


2

Python 3.5, 70 82 73 bytes:

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

A not, neste caso, certifique-se a soma de todos os números no *argsmodulo isão zero.

Além disso, agora essa função lambda pode receber quantos valores você desejar, desde que a quantidade de valores seja >=2diferente da gcdfunção do módulo matemático. Por exemplo, ele pode receber os valores 2,4,6,8,10e retornar o GCD correto de 2.


11
Você está preso por nomes de variáveis ​​multichar. (Ou argumentos função, mas qualquer que seja)
CalculatorFeline

2

Ruby, 23 bytes

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

lembre-se de que blocos de rubi são chamados com g [...] ou g.call (...), em vez de g (...)

créditos parciais a voidpigeon


2
Em vez de g.call(a,b)você pode usar g[a,b]. Em vez de proc{|a,b|, você pode usar ->a,b{.
afuous

11
Você também pode salvar um byte usando em b>0vez de b<=0e alternando a ordem dos outros operandos.
afuous

2

Código da máquina ARM, 12 bytes:

montagem:

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

Atualmente não é possível compilar isso, mas cada instrução no ARM leva 4 bytes. Provavelmente, poderia ser jogado para baixo usando o modo THUMB-2.


Bom trabalho, alguém que faz isso em código de máquina recebe adereços sérios de mim.
Mike Shlanta

Parece ser uma tentativa de algo de Euclides usando apenas subtração , mas não acho que funcione. Se r0 > r1então subltnão fará nada (o ltpredicado é falso) e bneserá um loop infinito. Eu acho que você precisa de uma troca, se não lt, então o mesmo loop pode fazer b-=aou a-=bconforme necessário. Ou negar se o subproduto for transportado (também conhecido como empréstimo).
Peter Cordes

Este guia do conjunto de instruções do ARM realmente usa um algoritmo GCD de subtração como um exemplo de predicação. (página 25). Eles usam cmp r0, r1/ subgt r0, r0, r1/ sublt r1, r1, r0/ bne gcd. Isso é 16B em instruções ARM, talvez 12 em instruções thumb2?
Peter Cordes

11
No x86, gerenciei 9 bytes com: sub ecx, eax/ jae .no_swap/ add ecx,eax/ xchg ecx,eax/ jne. Então, em vez de um cmp, eu apenas sub, desfaz e troco se o sub deveria ter ido para o outro lado. Eu testei isso e funciona. ( addnão jnesairá no momento errado, porque não pode produzir um zero, a menos que uma das entradas seja zero para começar, e não apoiamos isso. Atualização: precisamos apoiar a entrada sendo zero: /)
Peter Cordes

Para o Thumb2, há uma iteinstrução: if-then-else. Deve ser perfeito para cmp / sub de uma maneira / sub de outra maneira.
Peter Cordes

2

TI-Basic, 10 bytes

Prompt A,B:gcd(A,B

Não-concorrente devido à nova regra que proíbe os integrados do gcd


Solução de 17 bytes sem gcd(built-in

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

Não-concorrente devido à nova regra que proíbe embutidos lcm


Solução de 27 bytes sem gcd(ou lcm(embutida:

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

Solução recursiva de 35 bytes sem gcd(ou lcm(embutida (requer sistema operacional de 2,53 MP ou superior, deve ser nomeado prgmG ):

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

Você passaria argumentos para a variante recursiva, como {A,B}por exemplo {1071, 462}:prgmGrenderia 21.


Pinte-me impressionado.
Mike Shlanta

Você provavelmente deve mencionar que o último precisa ser salvo como prgmG.
a spaghetto


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;

Corrigido para entrada de 0


Não funciona corretamente se uma das entradas for zero.
Egor Skriptunoff

Isso deve poupar alguns: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~/

Espera que os números de entrada estejam presentes na pilha, portanto, +3 bytes para o -vsinalizador. Experimente online!

Outra implementação do algoritmo euclidiano.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.