Visualizza il massimo comun divisore


28

sfondo

Il più grande divisore comune ( abbreviato in gcd ) è una comoda funzione matematica, poiché ha molte proprietà utili. Uno di questi è l'identità di Bézout : if d = gcd(a, b), allora esistono numeri interi xe ytali d = x*a + y*b. In questa sfida, il tuo compito è visualizzare questa proprietà con una semplice arte ASCII.

Ingresso

I tuoi input sono due numeri interi positivi ae b, forniti in qualsiasi formato ragionevole. Puoi anche prendere input unari (ripetizioni di un singolo carattere ASCII stampabile di tua scelta), ma devi essere coerente e usare lo stesso formato per entrambi gli input. Gli input possono essere in qualsiasi ordine e possono essere uguali.

Produzione

L'output è una stringa sdi lunghezza lcm(a, b) + 1( mcm sta per il minimo comune multiplo). I caratteri di srappresentano numeri interi da 0a lcm(a, b). Il personaggio s[i]è in minuscolo ose iè un multiplo di ao b, e un punto .altrimenti. Si noti che zero è un multiplo di ogni numero. Ora, a causa dell'identità di Bézout, ci sarà almeno una coppia di caratteri oin scui distanza è esattamente gcd(a, b). La coppia all'estrema sinistra deve essere sostituita da Os maiuscole ; questo è l'output finale.

Esempio

Considera gli input a = 4e b = 6. Quindi abbiamo gcd(a, b) = 2e lcm(a, b) = 12, quindi, la lunghezza ssarà 13. I multipli di ae bsono evidenziati come segue:

0  1  2  3  4  5  6  7  8  9 10 11 12
o  .  .  .  o  .  o  .  o  .  .  .  o

Ci sono due coppie di os con distanza due, ma sostituiremo solo quelle più a sinistra con Os, quindi l'output finale è

o...O.O.o...o

Regole e punteggio

È possibile scrivere un programma completo o una funzione. Vince il conteggio di byte più basso e non sono consentite scappatoie standard.

Casi test

 1  1 -> OO
 2  2 -> O.O
 1  3 -> OOoo
 4  1 -> OOooo
 2  6 -> O.O.o.o
 2  3 -> o.OOo.o
10  2 -> O.O.o.o.o.o
 4  5 -> o...OO..o.o.o..oo...o
 8  6 -> o.....O.O...o...o.o.....o
12 15 -> o...........O..O........o.....o.....o........o..o...........o
19 15 -> o..............o...o..........o.......o......o...........o..o..............OO.............o....o.........o........o.....o............o.o..............o.o............o.....o........o.........o....o.............oo..............o..o...........o......o.......o..........o...o..............o

1
Quando prendiamo un input unario, possiamo scegliere qualsiasi personaggio? (In particolare, come su ., oo O.) O ha essere 1? Oppure 0?
Martin Ender,

1
@ MartinBüttner Può avere qualsiasi carattere, purché tu sia coerente e utilizzi lo stesso formato per entrambi gli input.
Zgarb,

2
Sono sorpreso che tu non abbia usato 3 e 5 come uno dei tuoi casi di test.
Neil

Posso usare buildin?
Akangka,

@ChristianIrwan Sì, sono ammessi tutti gli incorporati.
Zgarb,

Risposte:


7

Jolf, 52 byte

on*'.wm9jJΡR m*Yhm8jJDN?<*%Sj%SJ1'o'.}"'o%o"n"O%O"n

Dividerò questo codice in due parti.

on*'.wm9jJ
on         set n
  *'.       to a dot repeated
      m9jJ  the gcd of two numeric inputs

ΡR m*Yhm8jJDN?<*%Sj%SJ1'o'.}"'o%o"n"O%O"n
    *Y                                    multiply (repeat) Y (Y = [])
      hm8jJ                                by the lcm of two inputs + 1
  _m       DN              }              and map the array of that length
             ?<*%Sj%SJ1'o'.               "choose o if i%a*(i%b)<1; otherwise choose ."
 R                          "'            join by empty string
Ρ                            'o%o"n        replace once (capital Rho, 2 bytes): "o"+n+"o"
                                   "O%O"n   with "O"+n+"O"
                                          implicit printing

Provalo qui!


Più corto di tutto il resto finora. : P
R

1
@RikerW Sì! Spero che Jolf alla fine vincerà, una volta.
Conor O'Brien,

10

Julia, 111 110 107 103 96 byte

f(a,b)=replace(join([i%a*(i%b)<1?"o":"."for i=0:lcm(a,b)]),"o$(d="."^(gcd(a,b)-1))o","O$(d)O",1)

Questa è una funzione che accetta due numeri interi e restituisce una stringa.

Ungolfed:

function f(a::Int, b::Int)
    # Construct an array of dots and o's
    x = [i % a * (i % b) < 1 ? "o" : "." for i = 0:lcm(a, b)]

    # Join it into a string
    j = join(x)

    # Replace the first pair with distance gcd(a, b) - 1
    replace(j, "o$(d = "."^(gcd(a, b) - 1))o", "O$(d)O", 1) 
end

Hai salvato un byte grazie a nimi!


10

Retina , 112 109 99 94 91 byte

^
. 
+r`(?<!^\1+). (.+) 
$'$0
.(?=.* (.+) (.+))(?=\1* |\2* )
o
o(\.*)o((\1\.*o)*) .*
O$1O$2

Non molto competitivo, penso, ma la teoria dei numeri in Retina è sempre abbastanza divertente. :)

Accetta input come numeri unari usando .come cifra unaria.

Provalo online.

Spiegazione

^
. 

Ciò inserisce ae uno .spazio davanti all'ingresso. Questo alla fine diventerà l'output.

+r`(?<!^\1+). (.+) 
$'$0

Ciò antepone l'LCM di ae balla stringa. Dal momento che abbiamo già un .lì, finiremo con lcm(a,b)+1. Ciò si ottiene anteponendo ripetutamente bfinché anon si divide questo nuovo prefisso. Catturiamo ain un gruppo uno e quindi controlliamo se possiamo raggiungere l'inizio della stringa abbinando tale acquisizione almeno una volta. bviene quindi inserito nella stringa tramite il raramente utilizzato $'che inserisce tutto nella partita dopo la corrispondenza.

.(?=.* (.+) (.+))(?=\1* |\2* )
o

Questo corrisponde a personaggi in posizioni che sono divise per ao b. Si avvale del fatto che il risultato è simmetrico: poiché lcm(a,b)è diviso per entrambi ae bva a sinistra sottraendo istanze di ao bproduce lo stesso modello di andare a destra 0aggiungendole. Il primo lookahead semplicemente cattura ae b. Il secondo lookahead verifica che vi sia un multiplo di ciascuno ao dei bcaratteri prima del primo spazio.

o(\.*)o((\1\.*o)*) .*
O$1O$2

Come affermato su Wikipedia, oltre all'identità di Bézout è anche vero

Il massimo comune divisore dè il più piccolo intero positivo che può essere scritto come ax + by.

Ciò implica che il GCD corrisponderà allo spazio più breve tra due os nell'uscita. Quindi non dobbiamo preoccuparci di trovare il GCD. Invece cerchiamo solo la prima istanza del divario più breve. o(\.*)ocorrisponde a un gap candidato e ne acquisisce la larghezza nel gruppo 1. Quindi proviamo a raggiungere il primo spazio alternando un riferimento a gruppi 1 e os (con ulteriori .s opzionali ). Se c'è uno spazio più corto più a destra, questo non corrisponderà, perché non possiamo superare tale spazio con il riferimento. Non appena tutte le ulteriori lacune sono almeno pari a quella attuale, questo corrisponde. Catturiamo la fine della stringa LCM nel gruppo 2 e abbiniamo il resto della stringa con .*. Scriviamo in maiuscoloOs (con lo spazio tra) e il resto della stringa LCM, ma scarta tutto a partire dallo spazio, per rimuovere ae bdal risultato finale.


Non so molto sulla teoria dei numeri di Retina, ma non impostare il carattere di input su qualcosa che non richiede la fuga dei byte di salvataggio? Vale a dire (\.*)=>(a*)
Conor O'Brien,

@ CᴏɴᴏʀO'Bʀɪᴇɴ Sì, ma poi dovrei sostituirlo con .più tardi, il che costa quattro byte (e sbarazzarsi delle fughe salva solo 3).
Martin Ender,

Ohh. Freddo! Risposta molto interessante
Conor O'Brien,

5

𝔼𝕊𝕄𝕚𝕟, 50 caratteri / 90 byte

⩥Мū⁽îí+1)ⓜ$%î⅋$%í?⍘.:⍘o)⨝ċɼ(`o⦃⍘.ĘМũ⁽îí-1)}o”,↪$ú⬮

Try it here (Firefox only).

Ci deve essere un modo per giocare a golf ulteriormente!

Spiegazione

Questo è un algoritmo bifase di base. In realtà è abbastanza semplice.

Fase 1

⩥Мū⁽îí+1)ⓜ$%î⅋$%í?⍘.:⍘o)⨝

Innanzitutto, creiamo un intervallo da 0 a LCM + 1. Quindi mappiamo su di esso, controllando se uno degli input è un fattore dell'articolo corrente nell'intervallo. In tal caso, sostituiamo l'articolo con un o; altrimenti, lo sostituiamo con a .. Unendoci ci dà una serie di o e punti che possiamo passare alla fase due.

Fase 2

ċɼ(`o⦃⍘.ĘМũ⁽îí-1)}o”,↪$ú⬮

Questa è solo una grande funzione di sostituzione. Viene creata una regex come o[dots]o, dove la quantità di punti è determinata dal GCD-1. Poiché questa regex non è globale, corrisponderà solo alla prima occorrenza. Successivamente, la corrispondenza viene sostituita O[dots]Outilizzando una funzione toUpperCase.


3

MATL , 72 byte

Utilizza la versione 6.0.0 , che è precedente a questa sfida. Il codice viene eseguito in Matlab e in Octave.

2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)

Esempio

>> matl
 > 2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)
 > 
> 1
> 1
OO

>> matl
 > 2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)
 > 
> 2
> 3
o.OOo.o

>> matl
 > 2$tZm1+:1-bbvtbw\A~otbZ}ZdXK1+ltb(3X53$X+1K2$lh*t2=f1)tK+hwg1+Ib('.oO'w)
 > 
> 12
> 15
o...........O..O........o.....o.....o........o..o...........o

Spiegazione

Non ho idea di come funzioni. Ho appena digitato i caratteri in modo casuale. Penso che ci sia qualche convoluzione coinvolta.

Modifica: provalo online! Il codice nel link è stato leggermente modificato per adeguarsi alle modifiche della lingua (dal 2 giugno 2016).


Non è possibile digitare un programma a 72 byte in modo casuale. Calcolerà la probabilità più tardi (dopo aver dormito e AGIRE per un po ')
CalculatorFeline

2

Japt , 83 byte

'.pD=U*V/(C=(G=@Y?G$($YX%Y :X} $($UV)+1 £Y%U©Y%V?".:o"} $.replace($E=`o{'.pC-1}o`Eu

Non ancora completamente giocato a golf ... E non vuole essere giocato a golf: /


Non puoi usare ral posto di $.replace($?
ETHproductions

@Eth Non ho capito come sostituire senza g flag, quindi no, non posso.
nicael

2

Javascript, 170 164 161 153 145 141 136 byte

(a,b)=>[...Array(a*b/(c=(g=(a,b)=>b?g(b,a%b):a)(a,b))+1)].map((x,i)=>i%a&&i%b?'.':'o').join``.replace(`o${e='.'.repeat(c-1)}o`,`O${e}O`)

Questo è abbastanza lonnnggggg ....

Demo , variabili esplicitamente definite perché l'interprete utilizza la modalità rigorosa.


Prova a sostituirlo i%a<1||i%b<1?'o':'.'coni%a&&i%b?'.':'o'
Mama Fun Roll

Oh sì, penso che tu possa alias unirti.
Mama Fun Roll

@ ן nɟuɐɯɹɐ ן oɯ grazie, sostituendo anche le matrici con una semplice ripetizione.
nicael

Oh, quindi in quel caso, probabilmente non dovresti alias unirti a meno che tu non ne abbia 3 occorrenze.
Mama Fun Roll

[...Array((d=a*b/(c=(g=(a,b)=>b?g(b,a%b):a)(a,b)))+1).keys()].map(i=>i%a&&i%b?'.':'o')ti salva due byte. (Ho anche provato a utilizzare l'indicizzazione delle stringhe per creare '.' E 'o' ma che in realtà costa due byte.)
Neil

1

Python 2, 217 200 191 byte

Questo è un po 'schietto, ma funziona. Tutti i consigli sul golf sono apprezzati, specialmente se sai come risolvere quel s[i] = s[v] = "o"problema che ho riscontrato, dove questo sovrascriverebbe "O" .

g=lambda a,b:b and g(b,a%b)or a
def f(a,b):
 h=g(a,b);x=1+a*b/h;s=["."]*x;v=k=0
 for i in range(x):
    if(i%a)*(i%b)<1:
     if k:s[i]="o"
     else:k=i==h+v;s[i]=s[v]="oO"[k]
     v=i
 return''.join(s)

Ungolfed:

def gcd(a,b):                           # recursive gcd function
    if b:
        return g(b,a%b)
    else:
        return a
def f(a,b):
    h = gcd(a,b)
    x = 1 + a*b/h                       # 1 + lcm(a,b)
    s = ["."] * x
    v = 0
    k = 0
    for i in range(x):
        if i%a == 0 and i % b == 0:
            if k == 0:
                k = (i == h+v)          # correct distance apart?
                if k:                   # if "O" just found
                    s[i] = s[v] = "O"
                else:
                    s[i] = s[v] = "o"
            else:
                s[i] = "o"              # if "O" already found, always "o"
            v = i                       # If we found an "o" or an "O", i is the new v
    return ''.join(s)
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.