Wussten Sie, dass der euklidische Algorithmus traditionelle musikalische Rhythmen erzeugen kann ? Wir werden sehen, wie dies funktioniert, indem wir einen ähnlichen, aber etwas anderen Algorithmus als den in diesem Artikel beschriebenen beschreiben.
Wählen Sie eine positive Ganzzahl n
, die Gesamtzahl der Schläge, und eine positive Ganzzahl k
, die Anzahl der Schläge, die erklingen (Noten). Wir können uns den Rhythmus als eine Folge von n
Bits vorstellen, k
von denen 1s sind. Die Idee des Algorithmus ist es, die Einsen so gleichmäßig wie möglich unter den Nullen zu verteilen.
Zum Beispiel beginnen wir mit n = 8
und k = 5
mit 5 Einsen und 3 Nullen, jede in ihrer eigenen Reihenfolge:
[1] [1] [1] [1] [1] [0] [0] [0]
Zu jedem Zeitpunkt werden wir zwei Arten von Sequenzen haben - die am Anfang sind die "Kern" -Sequenzen und die am Ende sind die "Rest" -Sequenzen. Hier sind die Kerne [1]
s und die Reste sind [0]
s. Solange wir mehr als eine Restsequenz haben, verteilen wir sie auf die Kerne:
[1 0] [1 0] [1 0] [1] [1]
Jetzt ist der Kern [1 0]
und der Rest ist [1]
, und wir verteilen wieder:
[1 0 1] [1 0 1] [1 0]
Jetzt ist der Kern [1 0 1]
und der Rest ist [1 0]
. Da wir nur eine Restsequenz haben, halten wir an und holen den String
10110110
So klingt es, 4 Mal wiederholt:
Hier ist ein weiteres Beispiel mit n = 16
und k = 6
:
[1] [1] [1] [1] [1] [1] [0] [0] [0] [0] [0] [0] [0] [0] [0] [0]
[1 0] [1 0] [1 0] [1 0] [1 0] [1 0] [0] [0] [0] [0]
[1 0 0] [1 0 0] [1 0 0] [1 0 0] [1 0] [1 0]
[1 0 0 1 0] [1 0 0 1 0] [1 0 0] [1 0 0]
[1 0 0 1 0 1 0 0] [1 0 0 1 0 1 0 0]
1001010010010100
Beachten Sie, wie wir den letzten Schritt mit zwei Kernsequenzen und keinen Restsequenzen beendet haben. Hier wird es zweimal wiederholt:
Eingang
Sie können eine Funktion oder ein vollständiges Programm schreiben, das von STDIN, der Befehlszeile oder ähnlichem gelesen wird. Die Eingabe besteht aus zwei positiven Ganzzahlen n
und k <= n
ist vermutlich in beliebiger Reihenfolge.
Ausgabe
Ihre Aufgabe ist es, den generierten Rhythmus als n
zeichenlange Zeichenfolge auszugeben . Sie können zwei verschiedene druckbare ASCII-Zeichen (0x20 bis 0x7E) auswählen, um Noten und Pausen darzustellen.
Testfälle
Die folgenden Testfälle werden x
zur Darstellung von Notizen und .
s zur Darstellung von Pausen verwendet. Die Eingabe wird in der angegebenen Reihenfolge n
, dann k
.
1 1 -> x
3 2 -> xx.
5 5 -> xxxxx
8 2 -> x...x...
8 5 -> x.xx.xx.
8 7 -> xxxxxxx.
10 1 -> x.........
11 5 -> x.x.x.x.x..
12 7 -> x.xx.x.xx.x.
16 6 -> x..x.x..x..x.x..
34 21 -> x.xx.x.xx.xx.x.xx.x.xx.xx.x.xx.x.x
42 13 -> x...x..x..x..x...x..x..x..x...x..x..x..x..
42 18 -> x..x.x.x..x.x.x..x.x.x..x.x.x..x.x.x..x.x.
Wertung
Dies ist Code-Golf, also gewinnt der Code in den wenigsten Bytes.
q~\,f>
.Haskell, 125 Bytes
Anwendungsbeispiel:
42 # 13
->x...x..x..x..x...x..x..x..x...x..x..x..x..
.f
nimmt zwei Parameter: Kern- und Restliste. Entweder komprimiert es beide Listen (viag
) und ruft sich erneut auf oder stoppt, wenn der Rest zu kurz ist. Die Hauptfunktion#
erstellt die Startlisten und Aufrufef
.quelle
Python, 85
Die natürliche rekursive Lösung. Die Parameter
(n,k,a,b)
stellen einen Kern vonk
a
's dar, gefolgt von einem Rest vonn-k
b'
s.Diese Lösung ist ineffizient, da beide rekursive Aufrufe an
f
ausgewertet werden und eine exponentielle Anzahl von Aufrufen verursachen.Ich habe versucht, den bedingten Aufruf von
f
like zu komprimierenaber keiner fiel kürzer aus.
quelle