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 código de golfe .
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
fonte
SIGFPE
.Respostas:
Retina , 16
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
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.
fonte
+
s para*
s deve fazer. E você pode reduzir significativamente o último estágio do código longo, reduzindo-o para1
.^
, porque é impossível a partida falhar da posição inicial.código da máquina i386 (x86-32), 8 bytes (9B para não assinado)
+ 1B se precisarmos lidar
b = 0
com a entrada.código de máquina amd64 (x86-64), 9 bytes (10B para não assinado ou
14B13B para números inteiros de 64b assinados ou não)109B para não assinado em amd64 que quebra com a entrada = 0As entradas são de 32 bits zero não assinados inteiros
eax
eecx
. Saída emeax
.Essa estrutura de loop falha no caso de teste em que
ecx = 0
. (div
causa uma#DE
execução de hardware na divisão por zero. (No Linux, o kernel fornece umaSIGFPE
(exceção de ponto flutuante)). Se o ponto de entrada do loop estivesse logo antes doinc
, 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 quexor 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 (xchg
são 3 uops nas CPUs Intel eloop
é 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,edx
vez decdq
custaria um byte.div
é do mesmo tamanhoidiv
e tudo o mais pode permanecer o mesmo (xchg
para movimentação de dados einc/loop
ainda funciona).Curiosamente, para operandos de 64 bits (
rax
ercx
), as versões assinadas e não assinadas têm o mesmo tamanho. A versão assinada precisa de um prefixo REX paracqo
(2B), mas a versão não assinada ainda pode usar 2Bxor edx,edx
.No código de 64 bits,
inc ecx
é 2B: o byte únicoinc r32
e osdec r32
códigos de operação foram redirecionados como prefixos REX.inc/loop
não salva nenhum tamanho de código no modo de 64 bits, então você também podetest/jnz
. Operar em números inteiros de 64 bits adiciona outro byte por instrução nos prefixos REX, exceto paraloop
oujnz
. É possível que o restante tenha todos os zeros em 32b baixo (por exemplogcd((2^32), (2^32 + 1))
), portanto, precisamos testar todo o rcx e não podemos salvar um bytetest ecx,ecx
. No entanto, ojrcxz
insn mais lento é apenas 2B, e podemos colocá-lo no topo do loop para lidarecx=0
com a entrada :Programa de teste executável completo, incluindo um
main
que executaprintf("...", 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
sub
produz 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
)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 noprefix
modo, porque todos os insns usados são únicos / sem operando ouxchg
. Não é realmente uma observação útil.fonte
jrcxz
afinal 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.jecxz
na versão de 32 bits para o mesmo efeito?inc/loop
sã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 usarjrcxz
e emjmp
vez deinc / loop
.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:
Aqui está o diagrama de fluxo de controle:
O fluxo de controle começa no caminho cinza com um pequeno bit linear para entrada:
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:
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
A
eB
comB
eA % 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:fonte
Código de máquina x86 little-endian de 32 bits, 14 bytes
Gerado usando
nasm -f bin
d231 f3f7 d889 d389 db85 f475
fonte
cdq
e assinadoidiv
, e um byte emxchg eax, r32
vez demov
. Para código de 32 bits: eminc/loop
vez detest/jnz
(eu não conseguia ver uma maneira de usarjecxz
, 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.T-SQL, 153
169bytesAlguém mencionou a pior linguagem para jogar golfe?
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
fonte
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
fonte
Haskell, 19 bytes
Exemplo de uso:
45 # 35
->5
.Euclides, novamente.
PS: é claro que também há um built-in
gcd
.fonte
0
ou continuando com o módulo.Prelude
Python 3, 31
Economizou 3 bytes graças ao Sp3000.
fonte
from math import*;gcd
g=lambda a,b:b and g(b,a%b)or a
MATL ,
119 bytesNinguém parece ter usado força bruta até agora, então aqui está.
Entrada é uma matriz de colunas com os dois números (usando
;
como separador).Experimente online! ou verifique todos os casos de teste .
Explicação
fonte
C, 38 bytes
fonte
g
vez degcd
.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.
Se alguém escreve um pequeno invólucro principal
então pode-se testar alguns valores:
fonte
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.
Agora entramos em uma espécie de loop while-do que calcula o algoritmo euclidiano. Os topos das pilhas contêm
a
eb
(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:O loop termina quando
a
é zero. Uma iteração de loop funciona da seguinte maneira:Você pode ver, substituímos
a
eb
porb%a
ea
respectivamente.Finalmente, uma vez que
b%a
é zero, o IP continua se movendo para o leste e executa:fonte
Julia,
2115 bytesImplementaçã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
fonte
Cubix , 10
12bytesExperimente aqui
Isso envolve o cubo da seguinte maneira:
Usa o método euclidiano.
II
Dois 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 à direitav
Se não for 0, em seguida, redirecionar para baixo eu
vire à direita duas vezes de volta para o mod/
Se 0 Vá ao redor do cubo para o refletor;
TOS gota,O
saída TOS e@
finalfonte
0,x
ex,0
... então me deparei com isso. Agradável!C #, 24 bytes
fonte
Lote do Windows, 76 bytes
Função recursiva. Chame-o como
GCD a b
com o nome do arquivogcd
.fonte
MATL, 7 bytes
Experimente Online!
Explicação
Como não podemos usar explicitamente a função GCD incorporada (
Zd
em MATL), explorei o fato de que o mínimo múltiplo comum dea
eb
vezes o maior denominador comum dea
eb
é igual ao produto dea
eb
.fonte
*1MZm/
Raquete (esquema), 44 bytes
Implementação de Euclides em Raquete (Esquema)
Edit: Não viu a solução de @Numeri lol. De alguma forma, obtivemos exatamente o mesmo código independentemente
fonte
> <> , 32 bytes
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 !
fonte
ReRegex , 23 bytes
Funciona de forma idêntica à resposta da Retina.
Experimente online!
fonte
GML, 57 bytes
fonte
Delfos 7, 148
Bem, acho que encontrei a nova pior linguagem para o golfe.
fonte
Hoon, 20 bytes
-
Hoon # 2, 39 bytes
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
d
a saída.A outra implementação é apenas a definição padrão do GCD recursivo.
fonte
Python 3.5,
708273 bytes:A
not
, neste caso, certifique-se a soma de todos os números no*args
moduloi
são zero.Além disso, agora essa função lambda pode receber quantos valores você desejar, desde que a quantidade de valores seja
>=2
diferente dagcd
função do módulo matemático. Por exemplo, ele pode receber os valores2,4,6,8,10
e retornar o GCD correto de 2.fonte
Ruby, 23 bytes
lembre-se de que blocos de rubi são chamados com g [...] ou g.call (...), em vez de g (...)
créditos parciais a voidpigeon
fonte
g.call(a,b)
você pode usarg[a,b]
. Em vez deproc{|a,b|
, você pode usar->a,b{
.b>0
vez deb<=0
e alternando a ordem dos outros operandos.Código da máquina ARM, 12 bytes:
montagem:
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.
fonte
r0 > r1
entãosublt
não fará nada (olt
predicado é falso) ebne
será um loop infinito. Eu acho que você precisa de uma troca, se nãolt
, então o mesmo loop pode fazerb-=a
oua-=b
conforme necessário. Ou negar se o subproduto for transportado (também conhecido como empréstimo).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?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. (add
nãojne
sairá 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: /)ite
instrução: if-then-else. Deve ser perfeito para cmp / sub de uma maneira / sub de outra maneira.TI-Basic, 10 bytes
Não-concorrente devido à nova regra que proíbe os integrados do gcd
Solução de 17 bytes sem
gcd(
built-inNão-concorrente devido à nova regra que proíbe embutidos lcm
Solução de 27 bytes sem
gcd(
oulcm(
embutida:Solução recursiva de 35 bytes sem
gcd(
oulcm(
embutida (requer sistema operacional de 2,53 MP ou superior, deve ser nomeadoprgmG
):Você passaria argumentos para a variante recursiva, como
{A,B}
por exemplo{1071, 462}:prgmG
renderia21
.fonte
prgmG
.05AB1E , 10 bytes
Código:
Experimente online!
Com built-ins:
Explicação:
Experimente online! ou Tente com vários números .
fonte
Oracle SQL 11.2,
104118 bytesCorrigido para entrada de 0
fonte
SELECT MAX(LEVEL)FROM DUAL WHERE MOD(:1,LEVEL)+MOD(:2,LEVEL)=0 CONNECT BY LEVEL<=:1+:2;
> <> , 12 + 3 = 15 bytes
Espera que os números de entrada estejam presentes na pilha, portanto, +3 bytes para o
-v
sinalizador. Experimente online!Outra implementação do algoritmo euclidiano.
fonte