Visualisieren Sie den größten gemeinsamen Teiler

28

Hintergrund

Der größte gemeinsame Divisor (kurz gcd ) ist eine bequeme mathematische Funktion, da er viele nützliche Eigenschaften hat. Eines davon ist Bézouts Identität : Wenn d = gcd(a, b), dann gibt es ganze Zahlen xund ysolche, die es gibt d = x*a + y*b. In dieser Herausforderung besteht Ihre Aufgabe darin, diese Eigenschaft mit einfacher ASCII-Grafik zu visualisieren.

Eingang

Ihre Eingaben bestehen aus zwei positiven ganzen Zahlen aund bwerden in einem angemessenen Format angegeben. Sie können auch unäre Eingaben vornehmen (Wiederholungen eines einzelnen druckbaren ASCII-Zeichens Ihrer Wahl), müssen jedoch konsistent sein und für beide Eingaben dasselbe Format verwenden. Die Eingaben können in beliebiger Reihenfolge und gleich sein.

Ausgabe

Ihre Ausgabe ist eine Zeichenfolge mit seiner Länge lcm(a, b) + 1( lcm steht für das niedrigste gemeinsame Vielfache). Die Zeichen von stehen sfür Ganzzahlen von 0bis lcm(a, b). Das Zeichen s[i]ist ein Kleinbuchstabe, owenn ies ein Vielfaches von aoder ist b, und .ansonsten ein Punkt . Beachten Sie, dass Null ein Vielfaches jeder Zahl ist. Aufgrund von Bézouts Identität wird es nun mindestens ein Zeichenpaar geben, oin sdessen Abstand genau ist gcd(a, b). Das am weitesten links stehende Paar wird durch Os in Großbuchstaben ersetzt . Dies ist die endgültige Ausgabe.

Beispiel

Betrachten Sie die Eingänge a = 4und b = 6. Dann haben wir gcd(a, b) = 2und lcm(a, b) = 12, so wird die Länge ssein 13. Die Vielfachen von aund bwerden wie folgt hervorgehoben:

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

Es gibt zwei Paare von os mit Abstand zwei, aber wir werden nur die ganz linken durch Os ersetzen , so dass die endgültige Ausgabe erfolgt

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

Regeln und Wertung

Sie können ein vollständiges Programm oder eine Funktion schreiben. Die niedrigste Byteanzahl gewinnt, und Standardlücken sind nicht zulässig.

Testfälle

 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
Zgarb
quelle
1
Können wir bei unären Eingaben ein beliebiges Zeichen auswählen? (Insbesondere , wie etwa ., ooder O.) Oder muss es sein 1? Oder 0?
Martin Ender
1
@ MartinBüttner Es kann ein beliebiges Zeichen sein, solange Sie konsistent sind und für beide Eingaben dasselbe Format verwenden.
Zgarb
2
Ich bin überrascht, dass Sie nicht 3 und 5 als einen Ihrer Testfälle verwendet haben.
Neil
Kann ich buildin verwenden?
Akangka
@ChristianIrwan Ja, alle eingebauten Funktionen sind zulässig.
Zgarb

Antworten:

7

Jolf, 52 Bytes

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

Ich werde diesen Code in zwei Teile aufteilen.

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

Probieren Sie es hier aus!

Conor O'Brien
quelle
Kürzer als alles andere bisher. : P
Rɪᴋᴇʀ
1
@RikerW Ja! Ich hoffe, dass Jolf endlich einmal gewinnt.
Conor O'Brien
10

Julia, 111 110 107 103 96 Bytes

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)

Dies ist eine Funktion, die zwei Ganzzahlen akzeptiert und eine Zeichenfolge zurückgibt.

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

Dank nimi ein Byte gespart!

Alex A.
quelle
10

Retina , 112 109 99 94 91 Bytes

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

Ich denke, das ist nicht sehr konkurrenzfähig, aber die Zahlentheorie in der Netzhaut macht immer Spaß. :)

Nimmt Eingaben als unäre Zahlen unter Verwendung .der unären Ziffer an.

Probieren Sie es online aus.

Erläuterung

^
. 

Dies fügt ein .und ein Leerzeichen vor der Eingabe ein. Dies wird letztendlich zur Ausgabe.

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

Dies stellt das LCM von aund bvor den String. Da wir bereits eine .dort haben, werden wir am Ende mit lcm(a,b)+1. Dies wird durch wiederholtes Voranstellen erreicht b, solange adieses neue Präfix nicht geteilt wird. Wir erfassen ain einer Gruppe eins und prüfen dann, ob wir den Anfang der Zeichenfolge erreichen können, indem wir mindestens einmal mit dieser Erfassung übereinstimmen. bwird dann über den selten verwendeten in den String eingefügt, der nach dem Match $'alles in die Ersetzung einfügt .

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

Dieser stimmt mit Zeichen an Positionen überein, die durch aoder geteilt sind b. Dabei wird die Tatsache ausgenutzt, dass das Ergebnis symmetrisch ist: da lcm(a,b)durch beide geteilt wird aund bnach links gegangen wird, indem Instanzen von aoder subtrahiert werden, was bdasselbe Muster ergibt, als wenn nach rechts gegangen 0wird, indem sie addiert werden. Der erste Lookahead erfasst einfach aund b. Der zweite Lookahead prüft, ob vor dem ersten Leerzeichen ein Vielfaches von jedem aoder mehreren bZeichen steht.

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

Wie auf Wikipedia angegeben, ist es neben Bézouts Identität auch so

Der größte gemeinsame Teiler dist die kleinste positive ganze Zahl, die als geschrieben werden kann ax + by.

Dies impliziert, dass die GCD der kürzesten Lücke zwischen zwei oSekunden in der Ausgabe entspricht. Wir müssen uns also überhaupt nicht darum kümmern, die GCD zu finden. Stattdessen suchen wir nur die erste Instanz der kürzesten Lücke. o(\.*)oStimmt mit einer Kandidatenlücke überein und erfasst deren Breite in Gruppe 1. Dann versuchen wir, das erste Leerzeichen zu erreichen, indem wir zwischen einem Rückverweis auf Gruppe 1 und os wechseln (mit optionalen zusätzlichen .s). Wenn es weiter rechts eine kürzere Lücke gibt, wird diese nicht übereinstimmen, da wir diese Lücke mit der Rückreferenz nicht überwinden können. Sobald alle weiteren Lücken mindestens so groß wie die aktuelle sind, stimmt dies überein. Wir erfassen das Ende des LCM-Strings in Gruppe 2 und passen den Rest des Strings an .*. Wir schreiben den Großbuchstaben zurückOs (mit der Lücke dazwischen) sowie den Rest der LCM-Zeichenfolge, aber alles verwerfen, beginnend mit dem Leerzeichen, um zu entfernen aund bvom Endergebnis.

Martin Ender
quelle
Ich weiß nicht viel über die Retina-Zahlentheorie, würde aber das Eingabezeichen nicht auf etwas setzen, bei dem es nicht erforderlich ist, Sicherungsbytes zu maskieren? Dh (\.*)=>(a*)
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Ja, aber dann müsste ich es durch .später ersetzen , was vier Bytes kostet (und das Entfernen der Escape-Zeichen spart nur 3).
Martin Ender
Ohh Cool! Sehr interessante Antwort.
Conor O'Brien
5

𝔼𝕊𝕄𝕚𝕟 50 Zeichen / 90 Bytes

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

Try it here (Firefox only).

Es muss einen Weg geben, weiter Golf zu spielen!

Erläuterung

Dies ist ein grundlegender Zwei-Phasen-Algorithmus. Es ist eigentlich ganz einfach.

Phase 1

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

Zunächst erstellen wir einen Bereich von 0 bis LCM + 1. Dann mappen wir darüber und prüfen, ob einer der Eingänge ein Faktor des aktuellen Elements im Bereich ist. In diesem Fall ersetzen wir diesen Eintrag durch ein o; ansonsten ersetzen wir es durch a .. Wenn wir uns dazu gesellen, erhalten wir eine Reihe von O's und Punkten, die wir in die zweite Phase überführen können.

Phase 2

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

Dies ist nur eine große Ersetzungsfunktion. Eine Regex wird als erstellt o[dots]o, wobei die Anzahl der Punkte vom GCD-1 bestimmt wird. Da dieser reguläre Ausdruck nicht global ist, stimmt er nur mit dem ersten Vorkommen überein. Danach wird die Übereinstimmung durch O[dots]Oeine toUpperCase-Funktion ersetzt.

Mama Fun Roll
quelle
3

MATL , 72 Bytes

Verwendet Version 6.0.0 , die älter als diese Herausforderung ist. Der Code läuft in Matlab und in Octave.

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

Beispiel

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

Erläuterung

Ich habe keine Ahnung, wie es funktioniert. Ich habe nur zufällig Zeichen eingegeben. Ich denke, es gibt eine Faltung.

Bearbeiten: Probieren Sie es online! Der Code im Link wurde geringfügig geändert, um Änderungen in der Sprache Rechnung zu tragen (Stand: 2. Juni 2016).

Luis Mendo
quelle
Sie können ein 72-Byte-Programm nicht zufällig eingeben. Berechnet die Wahrscheinlichkeit später (nach dem Schlafen und nach einer Weile WIRKEN)
CalculatorFeline
2

Japt , 83 Bytes

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

Noch nicht voll bespielt ... Und will nicht bespielt werden: /

nicael
quelle
Können Sie nicht ranstelle von verwenden $.replace($?
ETHproductions
@Eth Ich habe nicht herausgefunden, wie man ohne g flag ersetzt, also nein, ich kann nicht.
Nicoleel
2

Javascript, 170 164 161 153 145 141 136 Bytes

(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`)

Das ist ziemlich lonnnggggg ....

Demo , explizit definierte Variablen, da der Interpreter den strikten Modus verwendet.

nicael
quelle
Versuchen Sie zu ersetzen i%a<1||i%b<1?'o':'.'durchi%a&&i%b?'.':'o'
Mama Fun Roll
Oh ja, ich denke, Sie können alias beitreten.
Mama Fun Roll
@ ן nןuɟ ן oן Danke, auch das Ersetzen von Arrays durch einfache Wiederholung.
nicael
Oh, dann sollten Sie in diesem Fall wahrscheinlich nicht alias beitreten, es sei denn, Sie haben 3 Vorkommen davon.
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')spart Ihnen zwei Bytes. (Ich habe auch versucht, Zeichenfolgenindizierung zu verwenden, um das '.' Und 'o' zu erstellen, aber das kostet tatsächlich zwei Bytes.)
Neil
1

Python 2, 217 200 191 Bytes

Dies ist ein wenig stumpf, aber es funktioniert. Irgendwelche Golf - Tipps geschätzt werden, vor allem , wenn Sie wissen , wie das beheben s[i] = s[v] = "o"Problem , das ich gestoßen, wo das würde überschreiben „O“ s Got it!

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)
Sherlock9
quelle