Su tarea es calcular el máximo común divisor (GCD) de dos enteros dados en el menor número de bytes posible.
Puede escribir un programa o función, tomando entradas y devolviendo salidas a través de cualquiera de nuestros métodos estándar aceptados (incluidos STDIN / STDOUT, parámetros de función / valores de retorno, argumentos de línea de comandos, etc.).
La entrada será dos enteros no negativos. Debería poder manejar el rango completo compatible con el tipo entero predeterminado de su idioma, o el rango [0,255]
, el que sea mayor. Se le garantiza que al menos una de las entradas será distinta de cero.
No está autorizado a utilizar elementos integrados que calculen el GCD o el LCM (mínimo común múltiplo).
Se aplican reglas estándar de código de golf .
Casos de prueba
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
fuente
SIGFPE
.Respuestas:
Retina , 16
Esto no usa el algoritmo de Euclides en absoluto; en cambio, encuentra el GCD usando grupos de coincidencia de expresiones regulares.
Pruébalo en línea. - Este ejemplo calcula el MCD (8,12).
Ingrese como 2 enteros separados por espacios. Tenga en cuenta que la E / S está en unario. Si eso no es aceptable, entonces podemos hacer esto:
Retina, 30
Pruébalo en línea.
Como señala @ MartinBüttner, esto se desmorona para un gran número (como suele ser el caso de cualquier cosa unaria). Como mínimo, una entrada de INT_MAX requerirá la asignación de una cadena de 2GB.
fuente
+
que*
debería cambiar su s a s. Y puede acortar significativamente la última etapa del código largo reduciéndolo a1
.^
, porque es imposible que el partido falle desde la posición inicial.Código de máquina i386 (x86-32), 8 bytes (9B para sin firmar)
+ 1B si necesitamos manejar la
b = 0
entrada.Código de máquina amd64 (x86-64), 9 bytes (10B para sin signo, o
14B13B para enteros de 64b con signo o sin signo)109B para unsigned en amd64 que se rompe con input = 0Las entradas son enteros con signo distinto de cero de 32 bits en
eax
yecx
. La producción eneax
.Esta estructura de bucle falla el caso de prueba donde
ecx = 0
. (div
provoca una#DE
ejecución de hardware en dividir entre cero. (En Linux, el kernel entrega unaSIGFPE
(excepción de punto flotante)). Si el punto de entrada del bucle estaba justo antes delinc
, evitaríamos el problema. La versión x86-64 puede manejarlo gratis, ver abajo.La respuesta de Mike Shlanta fue el punto de partida para esto . Mi bucle hace lo mismo que el suyo, pero para enteros con signo porque
cdq
es un byte más corto quexor edx,edx
. Y sí, funciona correctamente con una o ambas entradas negativas. La versión de Mike se ejecutará más rápido y ocupará menos espacio en la caché de UOP (xchg
es de 3 uops en las CPU de Intel, yloop
es realmente lenta en la mayoría de las CPU ), pero esta versión gana en tamaño de código de máquina.Al principio no me di cuenta de que la pregunta requería 32 bits sin firmar . Volver a en
xor edx,edx
lugar decdq
costaría un byte.div
es del mismo tamaño queidiv
, y todo lo demás puede permanecer igual (xchg
para el movimiento de datos yinc/loop
seguir funcionando).Curiosamente, para el tamaño de operando de 64 bits (
rax
yrcx
), las versiones firmadas y sin firmar son del mismo tamaño. La versión firmada necesita un prefijo REX paracqo
(2B), pero la versión sin firmar aún puede usar 2Bxor edx,edx
.En el código de 64 bits,
inc ecx
es 2B: el byte únicoinc r32
y los códigos dedec r32
operación se reutilizaron como prefijos REX.inc/loop
no guarda ningún tamaño de código en modo de 64 bits, por lo que también podría hacerlotest/jnz
. Operar en enteros de 64 bits agrega otro byte por instrucción en los prefijos REX, excepto paraloop
ojnz
. Es posible que el resto tenga todos los ceros en los bajos 32b (por ejemplogcd((2^32), (2^32 + 1))
), por lo que debemos probar todo el rcx y no podemos guardar un byte contest ecx,ecx
. Sin embargo, eljrcxz
insn más lento es solo 2B, y podemos ponerlo en la parte superior del ciclo para manejarloecx=0
en la entrada :Programa de prueba ejecutable completo, incluyendo una
main
que correprintf("...", gcd(atoi(argv[1]), atoi(argv[2])) );
la fuente y la salida de ASM en el Godbolt Compilador Explorador , para los 32 y 64b versiones. Probado y funcionando para 32bit (-m32
), 64bit (-m64
) y el x32 ABI (-mx32
) .También se incluye: una versión que usa solo resta repetida , que es 9B para sin signo, incluso para el modo x86-64, y puede tomar una de sus entradas en un registro arbitrario. Sin embargo, no puede manejar que ninguna entrada sea 0 en la entrada (detecta cuando
sub
produce un cero, que x - 0 nunca lo hace).Fuente asm en línea de GNU C para la versión de 32 bits (compilar con
gcc -m32 -masm=intel
)Normalmente escribiría una función completa en asm, pero GNU C inline asm parece ser la mejor manera de incluir un fragmento que puede tener entradas / salidas en cualquier reg que elijamos. Como puede ver, la sintaxis asm en línea de GNU C hace que sea feo y ruidoso. También es una forma realmente difícil de aprender asm .
En realidad, se compilaría y funcionaría en
.att_syntax noprefix
modo, ya que todas las entradas utilizadas son de un solo operando o noxchg
. No es realmente una observación útil.fuente
jrcxz
después de todo en la versión uint64_t :). Además, no noté que había especificado sin firmar, por lo que también incluí recuentos de bytes para eso.jecxz
en la versión de 32 bits con el mismo efecto?inc/loop
tiene 3 bytes en la versión de 32 bits, pero 4B en la versión de 64 bits. Eso significa que solo en la versión de 64 bits, no cuesta bytes adicionales usarjrcxz
y enjmp
lugar deinc / loop
.Hexagonía , 17 bytes.
Desplegado:
Pruébalo en línea!
Encajarlo en la longitud lateral 3 fue muy fácil. Limitar esos dos bytes al final no fue ... Tampoco estoy convencido de que sea óptimo, pero estoy seguro de que creo que está cerca.
Explicación
Otra implementación del algoritmo euclidiano.
El programa usa tres bordes de memoria, que llamaré A , B y C , con el puntero de memoria (MP) comenzando como se muestra:
Aquí está el diagrama de flujo de control:
El flujo de control comienza en la ruta gris con un bit lineal corto para la entrada:
Tenga en cuenta que el código ahora se ajusta alrededor de los bordes al
<
en la esquina izquierda. Esto<
actúa como una rama. Si el borde actual es cero (es decir, el algoritmo euclidiano termina), la IP se desvía hacia la izquierda y toma el camino rojo. De lo contrario, se calcula una iteración del algoritmo euclidiano en el camino verde.Primero consideraremos el camino verde. Tenga en cuenta que
>
y\
todos actúan como espejos que simplemente desvían el puntero de instrucciones. También tenga en cuenta que el flujo de control se envuelve alrededor de los bordes tres veces, una vez desde abajo hacia arriba, una vez desde la esquina derecha a la fila inferior y finalmente desde la esquina inferior derecha a la esquina izquierda para volver a verificar la condición. También tenga en cuenta que.
son no-ops.Eso deja el siguiente código lineal para una sola iteración:
Ahora estamos de vuelta donde comenzamos, excepto que los tres bordes han cambiado sus roles cíclicamente (el C original ahora toma el rol de B y el B original el rol de A ...). En efecto, hemos reequilibrado las entradas
A
yB
conB
yA % B
, respectivamente.Una vez
A % B
(en el borde C ) es cero, el GCD se puede encontrar en el borde B . Nuevamente, el>
solo desvía la IP, por lo que en el camino rojo ejecutamos:fuente
Código de máquina x86 little-endian de 32 bits, 14 bytes
Generado usando
nasm -f bin
d231 f3f7 d889 d389 db85 f475
fuente
cdq
y firmadoidiv
, y un byte enxchg eax, r32
lugar demov
. Para el código de 32 bits: eninc/loop
lugar detest/jnz
(no pude ver una forma de usarjecxz
, y no hayjecxnz
). Publiqué mi versión final como una nueva respuesta, ya que creo que los cambios son lo suficientemente grandes como para justificarlo.T-SQL, 153
169bytesAlguien mencionó el peor idioma para jugar al golf?
Crea una función con valores de tabla
que utiliza una consulta recursiva para resolver los divisores comunes. Luego devuelve el máximo. Ahora usa el algoritmo euclidiano para determinar el MCD derivado de mi respuesta aquí .Ejemplo de uso
fuente
Jalea, 7 bytes
Implementación recursiva del algoritmo euclidiano. Pruébalo en línea!
Si las incorporaciones no estuvieran prohibidas,
g
(1 byte, GCD incorporado) obtendría una mejor puntuación.Cómo funciona
fuente
Haskell, 19 bytes
Ejemplo de uso:
45 # 35
->5
.Euclides, otra vez.
PD: por supuesto, también hay un incorporado
gcd
.fuente
0
o continuar con el módulo.Prelude
Pitón 3, 31
Guardado 3 bytes gracias a Sp3000.
fuente
from math import*;gcd
g=lambda a,b:b and g(b,a%b)or a
MAT ,
119 bytesNadie parece haber usado la fuerza bruta hasta ahora, así que aquí está.
La entrada es una matriz de columnas con los dos números (usando
;
como separador).Pruébalo en línea! o verificar todos los casos de prueba .
Explicación
fuente
C, 38 bytes
fuente
g
lugar degcd
.C, 28 bytes
Una función bastante sencilla que implementa el algoritmo de Euclides. Quizás uno puede acortarse usando un algoritmo alternativo.
Si uno escribe un pequeño contenedor principal
entonces uno puede probar algunos valores:
fuente
Laberinto , 18 bytes
Termina con un error, pero el mensaje de error va a STDERR.
Pruébalo en línea!
Esto todavía no se siente óptimo, pero no estoy viendo una forma de comprimir el ciclo por debajo de 3x3 en este momento.
Explicación
Esto usa el algoritmo euclidiano.
Primero, hay un bit lineal para leer la entrada y entrar en el bucle principal. El puntero de instrucciones (IP) comienza en la esquina superior izquierda, hacia el este.
Ahora ingresamos una especie de ciclo while-do que calcula el algoritmo euclidiano. La parte superior de las pilas contiene
a
yb
(además de una cantidad infinita implícita de ceros, pero no los necesitaremos). Representaremos las pilas de lado a lado, creciendo unas hacia otras:El ciclo termina una vez que
a
es cero. Una iteración de bucle funciona de la siguiente manera:Puedes ver, hemos reemplazado
a
yb
conb%a
ya
respectivamente.Finalmente, una vez que
b%a
es cero, la IP sigue moviéndose hacia el este y ejecuta:fuente
Julia,
2115 bytesImplementación recursiva del algoritmo euclidiano. Pruébalo en línea!
Si los complementos no estuvieran prohibidos,
gcd
(3 bytes, GCD incorporado) obtendría una mejor puntuación.Cómo funciona
fuente
Cubix , 10
12bytesPruébalo aquí
Esto se envuelve en el cubo de la siguiente manera:
Utiliza el método euclidiano.
II
Se toman dos números de STDIN y se colocan en la pila./
Flow se refleja en%
Mod the Top of Stack. Resto que queda en la parte superior de la pila?
Si TOS 0 entonces continuar, de lo contrario gire a la derechav
Si no es 0, entonces redirigir hacia abajo yu
gire a la derecha dos veces de nuevo en el mod/
Si 0 dar la vuelta al cubo para el reflector;
TOS gota,O
la salida de TOS y@
finalesfuente
0,x
yx,0
... luego me encontré con esto. ¡Buena esa!C #, 24 bytes
fuente
Lote de Windows, 76 bytes
Función recursiva. Llámalo como
GCD a b
con el nombre del archivogcd
.fuente
MATL, 7 bytes
Pruébalo en línea!
Explicación
Como no podemos usar explícitamente la función incorporada de GCD (
Zd
en MATL), he explotado el hecho de que el mínimo común múltiplo dea
yb
el mayor común denominador dea
yb
es igual al producto dea
yb
.fuente
*1MZm/
Raqueta (esquema), 44 bytes
Implementación de Euclides en Raqueta (Esquema)
Editar: No vi la solución de @Numeri jajaja. De alguna manera obtuvimos exactamente el mismo código independientemente
fuente
> <> , 32 bytes
Acepta dos valores de la pila y aplica el algoritmo euclidiano para producir su GCD.
Puedes probarlo aquí !
Para una respuesta mucho mejor en> <>, ¡echa un vistazo a Sok's !
fuente
ReRegex , 23 bytes
Funciona de manera idéntica a la respuesta Retina.
Pruébalo en línea!
fuente
GML, 57 bytes
fuente
Delfos 7, 148
Bueno, creo que he encontrado el nuevo peor idioma para el golf.
fuente
Hoon, 20 bytes
-
Hoon # 2, 39 bytes
Curiosamente, la única implementación en stdlib de Hoon para GCD es la que se usa para su criptografía RSA, que también devuelve algunos otros valores. Tengo que envolverlo en una función que solo toma
d
de la salida.La otra implementación es solo la definición GCD recursiva predeterminada.
fuente
Python 3.5,
708273 bytes:En
not
este caso, se asegurará de que la suma de todos los números en el*args
móduloi
sea cero.Además, ahora esta función lambda puede tomar tantos valores como desee, siempre que la cantidad de valores sea
>=2
diferente a lagcd
función del módulo matemático. Por ejemplo, puede tomar los valores2,4,6,8,10
y devolver el MCD correcto de 2.fuente
Ruby, 23 bytes
recuerde que los bloques de rubí se llaman con g [...] o g.call (...), en lugar de g (...)
créditos parciales a voidpigeon
fuente
g.call(a,b)
que pueda usarg[a,b]
. En lugar deproc{|a,b|
, puedes usar->a,b{
.b>0
lugar deb<=0
y cambiando el orden de los otros operandos.Código de máquina ARM, 12 bytes:
montaje:
Actualmente no se puede compilar esto, pero cada instrucción en ARM toma 4 bytes. Probablemente podría jugar golf usando el modo THUMB-2.
fuente
r0 > r1
entoncessublt
no hará nada (ellt
predicado es falso) ybne
será un bucle infinito. Creo que necesita un intercambio si nolt
, por lo que el mismo bucle puede hacerb-=a
oa-=b
según sea necesario. O negar si el subproducto lleva (también conocido como préstamo).cmp r0, r1
/subgt r0, r0, r1
/sublt r1, r1, r0
/bne gcd
. ¿Eso es 16B en las instrucciones ARM, tal vez 12 en las instrucciones thumb2?sub ecx, eax
/jae .no_swap
/add ecx,eax
/xchg ecx,eax
/jne
. Entonces, en lugar de un cmp, simplemente subo, luego deshago e intercambio si el sub debería haber ido para otro lado. Probé esto, y funciona. (add
no saldrájne
en el momento equivocado, porque no puede producir un cero a menos que una de las entradas sea cero para empezar, y no admitimos eso. Actualización: necesitamos admitir que cualquiera de las entradas sea cero: /)ite
instrucción: if-then-else. Debería ser perfecto para cmp / sub de una manera / sub la otra.TI-Basic, 10 bytes
No competir debido a la nueva regla que prohíbe las incorporaciones de gcd
Solución de 17 bytes sin
gcd(
incorporadoNo competir debido a la nueva regla que prohíbe los mcm incorporados
Solución de 27 bytes sin
gcd(
olcm(
incorporada:Solución recursiva de 35 bytes sin
gcd(
olcm(
incorporada (se debe nombrar un sistema operativo de 2.53 MP o superiorprgmG
):Pasarías argumentos a la variante recursiva como
{A,B}
por ejemplo{1071, 462}:prgmG
, produciría21
.fuente
prgmG
.05AB1E , 10 bytes
Código:
Pruébalo en línea!
Con incorporados:
Explicación:
Pruébalo en línea! o Prueba con varios números .
fuente
Oracle SQL 11.2,
104118 bytesFijo para entrada de 0
fuente
SELECT MAX(LEVEL)FROM DUAL WHERE MOD(:1,LEVEL)+MOD(:2,LEVEL)=0 CONNECT BY LEVEL<=:1+:2;
> <> , 12 + 3 = 15 bytes
Espera que los números de entrada estén presentes en la pila, por lo que +3 bytes para el
-v
indicador. Pruébalo en línea!Otra implementación del algoritmo euclidiano.
fuente