Visualizza l'algoritmo euclideo


17

L'algoritmo euclideo è un algoritmo ampiamente noto per il calcolo del massimo comun divisore (GCD) di due numeri interi positivi.

L'algoritmo

Ai fini di questa sfida, l'algoritmo è descritto di seguito:

  1. Visualizza i due input come linee adiacenti di un certo carattere,
    ad esempio un input di 3,4può essere rappresentato dalle linee adiacenti 000e0000

  2. Trasforma i primi length(short_line)personaggi della linea più lunga in un altro personaggio, ad esempio -
    ora sembra000 e---0

  3. Elimina i primi length(short_line)caratteri nella riga più lunga.
    adesso000 ,0

  4. Ripetere il punto 2 e 3 finché i due hanno uguale lunghezza, utilizzando le linee più corte e più dopo ogni iterazione, ad esempio
    000, 0
    -00, 0
    00, 0
    -0,0
    0 ,0

  5. Puoi scegliere se interrompere qui o continuare l'iterazione e trasformare una delle righe in una riga vuota.

Ognuno di questi passaggi deve essere separato da un intervallo tra 0,3 secondi e 1,5 secondi.

La sfida

Scrivi un programma che, dati due numeri naturali come input, crea un output che è esattamente uguale a quello dell'algoritmo sopra. È possibile utilizzare altri caratteri ASCII stampabili non bianchi rispetto a 0e -, ma essere coerenti e utilizzare solo due caratteri. Puoi anche usare algoritmi alternativi a condizione che l'output, incluso il timing, sia esattamente lo stesso che verrebbe prodotto dall'algoritmo sopra.

Esempi

Questo è un esempio con input 24,35, che sono coprimes quindi il loro GCD è 1.

inserisci qui la descrizione dell'immagine

Questo è un esempio con input 16,42, che ha GCD 2.

inserisci qui la descrizione dell'immagine

Regole


chiarimenti

  • Le righe che rappresentano i numeri devono rimanere nel loro ordine originale, ovvero la prima e la seconda riga del primo "frame" visualizzato devono essere rispettivamente la prima e la seconda riga, in tutti i frame successivi.
  • Al termine dell'algoritmo, non dovrebbero apparire ulteriori entità visibili . Tuttavia, ciò significa anche che va bene svuotare le linee, se si assicura che l'ultimo "fotogramma" sia visualizzato per almeno la stessa quantità di tempo di tutti gli altri fotogrammi prima di oscurare.

@WheatWizard grande suggerimento, su di esso
busukxuan

Le linee devono rimanere nello stesso ordine relativo? O possono essere riordinati tra le iterazioni? (Verifica perché è probabile che quest'ultimo sia molto più conciso nella maggior parte delle lingue, e quindi devo sapere se dovrei usare quell'ottimizzazione o ignorarla a causa della violazione del sepc.)

@ ais523 Sì, lo fanno:-)
busukxuan,

@ ais523 Sì, va bene cancellarlo, ma assicurati che l'ultimo fotogramma abbia lo stesso tempo di visualizzazione degli altri fotogrammi
busukxuan,

1
@busukxuan Personalmente penso che permetterei spazi finali, ma forse non spazio come uno dei personaggi "significativi"
Luis Mendo,

Risposte:


3

Gelatina , 29 byte

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

Provalo online!

Questo definisce una funzione 2Ŀ(non un programma completo; il collegamento TIO contiene un piè di pagina che converte una funzione in un programma) che accetta un elenco di due elementi come input e visualizza l'output sullo schermo (uno dei nostri metodi I / O legali e uno che è un po 'necessario per questa sfida perché parla dell'aspetto sullo schermo). Ciò presuppone che il programma sia eseguito in un terminale conforme allo standard ANSI (ho usato gnome-terminalma funzionerà la maggior parte) e che il terminale è inizialmente vuoto (che sembra il valore predefinito più sensato); nota che provalo online! non è conforme a questi presupposti, e quindi l'output è distorto lì (ho eseguito il programma localmente per verificare che si anima come previsto). Uso 1dove utilizza la domanda 0e2al posto di -.

Spiegazione

Funzione di aiuto 1Ŀ (dato un elenco di due elenchi di cifre, li emette sulla prima e seconda riga dello schermo, quindi attende 0,5 secondi; restituisce il suo input)

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 stringa "\ x1bc", quando inviata a un terminale compatibile ANSI, viene interpretata come un codice di controllo per resettare il terminale; questo cancella lo schermo e sposta il cursore nell'angolo in alto a sinistra (ripristinando così il terminale pronto per l'uscita successiva).

La funzione di supporto è denominata 1Ŀ(Jelly genera automaticamente i nomi di questo modulo per le funzioni, e in effetti non c'è altro modo di nominarli), ma può essere definita semplicemente come Çdal programma principale (perché la lingua ha una scorciatoia per le funzioni con numeri nelle vicinanze ).

Funzione principale 2Ŀ (implementa l'attività richiesta nella domanda)

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)

6

JavaScript (ES6), 128 124 byte

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>


3

Python 2 , 152 146 byte

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)

Provalo online!


Accetta due numeri interi separati da virgola come input


Questa è una bella risposta.
ElPedro,

2

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

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

Questo richiede input in una variazione sul curry. Per usarlo, pugno assegna la funzione a una variabile (per esempio G), quindi chiamala così:

G(5)(6)()

Spiegazione

Funzione un po 'ricorsiva che si chiama dopo 1 secondo fino a quando l'algoritmo non è terminato. Tiene traccia di una terza variabile cche determina se ae bdeve essere modificata (se lo cè 1, è tempo di cambiare).

Innanzitutto, la funzione scrive qualcosa sulla console. Se cè 0, scrive due stringhe di zeri con un inbetween nuova riga. Poiché cè stato inizializzato 0, possiamo trarne vantaggio e impostare variabili globali fe gche contengono alcune stringhe di cui abbiamo bisogno spesso (come 0e repeat).

Altrimenti, crea una stringa con zero e svantaggi. Tutte queste stringhe sono composte da due parti: prima alcuni (chiama questo importo A), poi alcuni (chiama questo importo B) azzeramenti, quindi una nuova riga, quindi alcuni (chiama questo importo D) e infine alcuni (chiama questo importo E) azzerati.

Se il primo input è più piccolo del secondo input, dobbiamo rimuovere gli zero dal secondo input, quindi Aè zero, è Buguale al primo input, è Duguale al primo input ed è Euguale al secondo input meno il primo input. Se il primo input non è più piccolo del secondo input, si applica il contrario ( Aè il secondo input, Bè il primo input meno il secondo input ecc.).

Con questi nuovi valori per l'ingresso e una variabile commutata c, la funzione è programmata per essere richiamata di nuovo in 1e3millisecondi, che equivale a un secondo.

Appunti

  • Utilizza alertper l'output
  • Usi 0e -, proprio come negli esempi
  • Il ritardo tra i passaggi è 1000 ms (1 secondo)
  • Dopo il primo passo, la funzione (a causa della natura di JavaScript) restituirà un numero che deve essere ignorato
  • La versione su TIO emette tutto in una volta, incollando il codice nella console del browser si terrà correttamente conto dei ritardi

Provalo online

Provalo qui!


2

Python 2 , 208 204 194 byte

-4 grazie a @math_junkie per il trucco subdolo con time.sleep

-10 grazie a @busukxuan per aver chiarito la regola "cancella schermo".

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)

Provalo online!

Abbastanza sicuro che questo potrebbe essere più golfato. Mi fa male duplicare il printe il forciclo per creare la pausa, ma al momento non riesco a trovare un modo per aggirarlo.

Appunti

  • La pausa ora utilizza un suggerimento di @math_junkie
  • Non funziona completamente su TIO poiché memorizza l'output e lo scarica al termine del programma. Funziona bene nella console però.

1
Dovreste essere in grado di salvare alcuni byte utilizzando import time, s=time.sleepe s(1)invece di un ciclo per il ritardo
matematica drogato

Grazie @math_junkie - Ho provato la maggior parte delle combinazioni usando time.sleepma non l' ho visto . Ci proverò.
ElPedro,

@math_junkie - arriva a 215 per me. Forse mi manca qualcosa di stupido. Puoi pubblicare un esempio su Provalo online ?
ElPedro,


1

perl, 161 149 byte

... senza rientri e newline:

($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
}

Inseriscilo in un file gcd.pl ed eseguilo in questo modo:

perl -M5.010 gcd.pl 16 42

1
Il -M5.010flag per perl è gratuito, quindi puoi salvare qualche byte usando sayover print…\n. Inoltre, sono abbastanza sicuro che sia meglio dare un nome alla tua subroutine anonima, piuttosto che memorizzarla in una variabile.

Grazie a ais523 per suggerimenti su come radere 12 byte
Kjetil S.

1

GNU Sed (con eestensione xec), 88

Il punteggio include +3 per le -zrfopzioni a 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

L'input viene dato come due numeri interi unari separati da una nuova riga, usando le maiuscole Ocome cifre.

Ad esempio, l'esempio 16, 42 può essere eseguito come:

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

Secondo gli ultimi commenti, non sto cancellando lo schermo tra le iterazioni.


0

V , 47 44 byte

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

Provalo online!

L'intestazione e il piè di pagina su TIO si limitano a modificare gsper copiare le due linee correnti nella parte inferiore dello schermo, quindi eliminare le prime due alla fine. Questo visualizza l'operazione per TIO, ma se l'avessi eseguita in V (senza intestazione e piè di pagina), aspetterebbe solo un secondo tra ogni operazione.

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

Hai davvero bisogno del finale ò?
Kritixi Lithos,

Si blocca senza di essa, incerto sul perché. Aspetterò fino a quando avrò un computer con V per il debug di qualsiasi
nmjcman101
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.