Visualice el algoritmo euclidiano

17

El algoritmo euclidiano es un algoritmo ampliamente conocido para calcular el máximo común divisor (MCD) de dos enteros positivos.

El algoritmo

Para el propósito de este desafío, el algoritmo se describe a continuación:

  1. Visualice las dos entradas como líneas adyacentes de cierto carácter,
    por ejemplo, una entrada de 3,4puede ser representada por las líneas adyacentes 000y0000

  2. Convierta los primeros length(short_line)caracteres en la línea más larga en otro carácter, digamos -
    ahora que parece 000y---0

  3. Elimina los primeros length(short_line)caracteres en la línea más larga.
    ahora 000,0

  4. Repite el paso 2 y 3 hasta que los dos tienen la misma longitud, utilizando las líneas más cortas y más largas después de cada iteración, por ejemplo
    000, 0
    -00, 0
    00, 0
    -0, 0
    0,0

  5. Puede elegir si desea detenerse aquí o continuar la iteración y convertir una de las líneas en una línea vacía.

Cada uno de estos pasos debe estar separado por un intervalo entre 0.3s y 1.5s.

El reto

Escriba un programa que, dados dos números naturales como entrada, cree una salida que se vea exactamente igual a la salida del algoritmo anterior. Puede usar otros caracteres ASCII imprimibles que no sean espacios en blanco que no sean 0y -, pero sea coherente y use solo dos caracteres. También puede usar algoritmos alternativos siempre que el resultado, incluido el tiempo, sea exactamente el mismo que produciría el algoritmo anterior.

Ejemplos

Este es un ejemplo con entrada 24,35, que son coprimos, por lo que su GCD es 1.

ingrese la descripción de la imagen aquí

Este es un ejemplo con entrada 16,42, que tiene el GCD 2.

ingrese la descripción de la imagen aquí

Reglas


Aclaraciones

  • Las líneas que representan los números deben permanecer en su orden original, es decir, la primera y segunda líneas del primer "cuadro" visualizado deben ser la primera y la segunda líneas respectivamente, en todos los cuadros posteriores.
  • Una vez que finaliza el algoritmo, no debe aparecer ninguna entidad visible adicional . Sin embargo, esto también significa que está bien dejar en blanco las líneas, si se asegura de que el último "cuadro" se muestre durante al menos la misma cantidad de tiempo que todos los demás cuadros antes de dejar en blanco.
busukxuan
fuente
Gran sugerencia de @WheatWizard, en él
busukxuan
¿Las líneas tienen que permanecer en el mismo orden relativo? ¿O pueden reordenarse entre iteraciones? (Comprobación ya que este último es probable que sea mucho más concisa en la mayoría de idiomas, y por lo tanto necesito saber si debo utilizar que la optimización o ignorarla, debido a la violación de la sepc.)
@ ais523 Sí, lo hacen:-)
busukxuan
@ ais523 Sí, está bien dejarlo en blanco, pero asegúrese de que el último cuadro tenga el mismo tiempo de visualización que los otros cuadros
busukxuan
1
@busukxuan Personalmente creo que permitiría espacios finales, pero tal vez no espacio como uno de los personajes "significativos"
Luis Mendo

Respuestas:

3

Jalea , 29 bytes

VY“ñc‘ỌœS.⁸
1ẋǵ+M¦ṚÇt€2ǵ⁻/¿

Pruébalo en línea!

Esto define una función 2Ŀ(no un programa completo; el enlace TIO contiene un pie de página que convierte una función en un programa) que toma una lista de dos elementos como entrada y muestra la salida en la pantalla (uno de nuestros métodos legales de E / S , y uno que es bastante necesario para este desafío porque habla sobre la apariencia en pantalla). Esto supone que el programa se ejecuta en un terminal que cumple con el estándar ANSI (lo usé gnome-terminalpero la mayoría funcionará), y que el terminal está inicialmente vacío (lo que parece ser el valor predeterminado más sensible); tenga en cuenta que Pruébelo en línea! no se ajusta a estos supuestos y, por lo tanto, la salida está distorsionada allí (ejecuté el programa localmente para verificar que se anima como se esperaba). Yo uso 1donde la pregunta usa 0, y2en lugar de -.

Explicación

Función auxiliar 1Ŀ (dada una lista de dos listas de dígitos, las muestra en la primera y segunda línea de la pantalla, luego espera 0.5 segundos; devuelve su entrada)

VY“ñc‘ỌœS.⁸
V                   Convert each list of digits to an integer
 Y                  Separate these integers by newlines
  “ñc‘              {Output that; then restart with} the list [27, 99]
      Ọ             Convert codepoints to characters (i.e. "\x1bc"
       œS.          Wait (œS) 0.5 (.) seconds
          ⁸         {Output that; then return} the initial argument

La cadena "\ x1bc", cuando se envía a un terminal compatible con ANSI, se interpreta como un código de control para restablecer el terminal; esto borra la pantalla y mueve el cursor a la esquina superior izquierda (restableciendo así el terminal listo para la próxima salida).

Se nombra la función auxiliar 1Ŀ(Jelly genera automáticamente nombres de esta forma para las funciones, y de hecho no hay otra forma de nombrarlas), pero se puede hacer referencia a ella simplemente Çdesde el programa principal (porque el lenguaje tiene abreviatura para funciones con números cercanos) )

Función principal 2Ŀ (implementa la tarea solicitada en la pregunta)

1ẋǵ+M¦ṚÇt€2ǵ⁻/¿
1ẋ                  Convert input to unary
  Ç                 Call helper function (producing one animation frame)
   µ         µ  ¿   While
              ⁻/      the elements differ:
     M¦               Change the largest element
    +  Ṛ                by adding corresponding elements of the other element
        Ç             Call helper function (producing one animation frame)
         t€2          Delete all 2s from each side of each element
            Ç         Call helper function (producing one animation frame)

fuente
6

JavaScript (ES6), 128 124 bytes

t=0
f=
(a,b,o,c,d)=>setInterval(e=>{e=[b,d,a,c];o.data=`-0
-0`.replace(/./g,c=>c.repeat(e.pop()));c|d?c=d=0:a>b?a-=c=b:b-=d=a},1e3)
<form><input id=a><input id=b><button onclick=clearTimeout(t),t=f(+a.value,+b.value,o.firstChild)>Go!</button><pre id=o>

Neil
fuente
3

Python 2 , 152 146 bytes

import time
s,o='-0'
a,b=input()
while a*b:
 d,e=o*a,o*b
 if a>b:a=a-b;d=s*b+o*a
 elif b>a:b=b-a;e=s*a+o*b
 else:a=0
 print d+'\n'+e;time.sleep(1)

Pruébalo en línea!


Toma dos enteros separados por comas como entrada

ovs
fuente
Esa es una buena respuesta.
ElPedro
2

Javascript (ES6), 215 194 ... 135 129 127 bytes

a=>b=>F=(c=0)=>alert('-'[d='repeat'](e=c&a>b&&b)+'0'[d](a-=e)+`
`+'-'[d](f=c&a<b&&a)+'0'[d](b-=f))|a-b|c&&setTimeout(F,1e3,1-c)

Uso

Esto toma la entrada en una variación de curry. Para usarlo, primero asigna la función a una variable (por ejemplo G), luego llámalo así:

G(5)(6)()

Explicación

Función algo recursiva que se llama a sí misma después de 1 segundo siempre que el algoritmo no haya terminado. Realiza un seguimiento de una tercera variable cque determina si debe ay bdebe cambiarse (si ces así 1, es hora de cambiar).

Primero, la función escribe algo en la consola. Si ces así 0, escribe dos cadenas de ceros con una nueva línea intermedia. Como cse inicializa en 0, podemos aprovechar esto y configurar variables globales fy gque contengan algunas cadenas que necesitamos a menudo (como 0y repeat).

De lo contrario, crea una cadena con ceros y desventajas. Todas estas cadenas consisten en dos partes: primero algunos (llame a esta cantidad A) menos, luego algunos (llame a esta cantidad B) ceros, luego una nueva línea, luego algunos (llame a esta cantidad D) menos y finalmente algunos (llame a esta cantidad E) ceros.

Si la primera entrada es más pequeña que la segunda entrada, necesitamos eliminar los ceros de la segunda entrada, entonces Aes cero, Bigual a la primera entrada, Digual a la primera entrada e Eigual a la segunda entrada menos la primera entrada. Si la primera entrada no es más pequeña que la segunda entrada, se aplica lo contrario ( Aes la segunda entrada,B es la primera entrada menos la segunda entrada, etc.).

Con estos nuevos valores para la entrada y una variable conmutada c, la función está programada para ser llamada nuevamente en1e3 milisegundos, lo que equivale a un segundo.

Notas

  • Usos alert para salida
  • Usos 0y- , al igual que en los ejemplos
  • El retraso entre pasos es de 1000 ms (1 segundo)
  • Después del primer paso, la función (debido a la naturaleza de JavaScript) devolverá algún número que debe ignorarse
  • La versión en TIO genera todo a la vez, pegar el código en la consola del navegador tendrá debidamente en cuenta los retrasos

Pruébalo en línea

Pruébalo aquí!

Luke
fuente
2

Python 2 , 208 204 194 bytes

-4 gracias a @math_junkie por el astuto truco con time.sleep

-10 gracias a @busukxuan por aclarar la regla de "pantalla clara".

def z(a,b,y='-',w=1):
 import time;c,d,n,s='0'*a,'0'*b,'\n',time.sleep
 if w:print c+n+d;s(1)
 if b>a:d=y*a+d[a:]
 else:c=y*b+c[b:]
 print c+n+d;s(1)
 if c!=d:z(len(c),len(d),('','-')[y!='-'],0)

Pruébalo en línea!

Estoy bastante seguro de que esto podría ser más golf. Me duele duplicar el printy el forbucle para crear la pausa, pero no puedo encontrar una forma de evitarlo en este momento.

Notas

  • La pausa ahora usa una pista de @math_junkie
  • No funciona completamente en TIO, ya que almacena la salida y la descarga cuando finaliza el programa. Sin embargo, funciona bien en la consola.
ElPedro
fuente
1
Debería poder guardar algunos bytes usando import time, s=time.sleepy en s(1)lugar de un bucle para la demora
adicto a las matemáticas
Gracias @math_junkie: probé la mayoría de las combinaciones usando, time.sleeppero perdí esa. Lo intentaré.
ElPedro
@math_junkie: llega a 215 para mí. Tal vez me estoy perdiendo algo estúpido. ¿Puedes publicar un ejemplo en Pruébalo en línea ?
ElPedro
1
Pruébalo aquí
adicto a las matemáticas
1

perl, 161 149 bytes

... sin hendiduras y nuevas líneas:

($a,$b)=map 0 x$_,@ARGV;
sub p{say"\n$a\n$b";sleep 1}p;
while($a ne$b){
  ($A,$B)=$b lt$a?(\$a,\$b):(\$b,\$a);
  map$$A=~s/0/-/,1..length$$B;
  p;
  $$A=~s/-//g;
  p
}

Póngalo en un archivo gcd.pl y ejecútelo así:

perl -M5.010 gcd.pl 16 42
Kjetil S.
fuente
1
La -M5.010marca de perl es gratuita, por lo que puede guardar algunos bytes si usa sayover print…\n. Además, estoy bastante seguro de que es terser darle un nombre a su subrutina anónima, en lugar de almacenarla en una variable.
Thx a ais523 para consejos para reducir 12 bytes
Kjetil S.
1

GNU Sed (con e extensión xec), 88

La puntuación incluye +3 para las -zrfopciones sed.

p
:
x
esleep 1
g
ta
:a
s/o+//p
t
s/^((O+)(O+)\n\2\b|(O+)\n\4\B)/\L\2\U\3\4\n\2\L\4\U/p
t

La entrada se proporciona como dos enteros unarios separados de nueva línea, utilizando mayúsculas O como dígitos.

Por ejemplo, el ejemplo 16, 42 se puede ejecutar como:

printf "%0*d\n%0*d\n" 16 0 42 0 | tr 0 O | sed -znrf euclidvis.sed

Según los últimos comentarios, no estoy limpiando la pantalla entre iteraciones.

Trauma digital
fuente
0

V , 47 44 bytes

Àé0á
Àé0Hqwmmjlhmmkl@wqòHî@w
gs`mlhv0r-gsÓ-ò

Pruébalo en línea!

El encabezado y el pie de página en TIO simplemente se modifican gspara copiar las dos líneas actuales en la parte inferior de la pantalla y luego se eliminan las dos primeras al final. Esto visualiza la operación para TIO, pero si lo ejecutó en V (sin el encabezado y el pie de página), solo esperaría un segundo entre cada operación.

Àé0                     " Print (Arg1) zeroes
   á                    " Newline
Àé0                     " Print (Arg2) zeroes
   H                    " Go home
    qwmmjlhmmkl@wq      " Store a recursive macro in w that finds the shorter line
                  ò     " recursively
                   Hî@w " find the longest line
gs                      " wait a second
  `mlhv0r-              " replace the zeroes of the long line with -
          gs            " wait a second
            Ó-          " delete all -
              ò         " end recursion
nmjcman101
fuente
¿Realmente necesitas el final ò?
Kritixi Lithos
Se cuelga sin él, sin saber por qué. Voy a esperar hasta que tenga una computadora con V para depurar cualquier
nmjcman101