Hilf mir mit meinen Polyrhythmen

17

Ich bin Musiker und brauche mehr Polyrhythmen in meinem Leben!

Ein Polyrhythmus tritt in der Musik (und in der Natur) auf, wenn zwei Ereignisse (Klatschen, Noten, Glühwürmchen blinken usw.) in zwei verschiedenen regelmäßigen Intervallen auftreten. Die beiden Arten von Ereignissen treten in demselben Intervall unterschiedlich oft auf.

Wenn ich zweimal mit der linken Hand und dreimal mit der rechten Hand im selben Zeitraum tippe, sieht es ein bisschen so aus:

  ------
R . . .
L .  .  

Die Bindestriche oben bezeichnen die Länge des polyrthmischen Musters, das ist das niedrigste gemeinsame Vielfache oder 2 und 3. Dies kann als der Punkt verstanden werden, an dem sich das Muster wiederholt.

Es gibt auch einen "Metarhythmus", der das Muster ist, das erzeugt wird, wenn eine Hand tippt:

  ------
R . . .
L .  .  
M . ...

Dies ist ein einfacher und sehr gebräuchlicher Polyrhythmus mit einem Verhältnis von 3: 2.

Sagen wir einfach, ich möchte keinen einfachen Polyrhythmus machen, den ich in meinem Kopf trainieren kann, also brauche ich etwas, um es für mich zu trainieren. Ich könnte es auf Papier machen, oder ...


Regeln:

  • Schreiben Sie Code, um wie oben beschrieben ein Polyrhythmusdiagramm zu erstellen und anzuzeigen.
  • Bei allen alten Sprachen versuchen Sie es mit den wenigsten Bytes.
  • Ihr Code benötigt zwei Argumente:
    • Anzahl der Taps mit der linken Hand (positive ganze Zahl)
    • Anzahl der Taps mit der rechten Hand (positive ganze Zahl)
  • Es wird die Länge berechnet, die das niedrigste gemeinsame Vielfache für die beiden Argumente ist.
  • Die oberste Zeile besteht aus zwei Leerzeichen, gefolgt von Bindestrichen, die die Länge anzeigen (Länge * '-').
  • Die zweite und dritte Zeile zeigen das Muster für die rechte und die linke Hand:
    • Es beginnt mit einem R oder L, gibt an, um welche Hand es sich handelt, gefolgt von einem Leerzeichen.
    • Das Intervall für diese Hand ist die Länge geteilt durch das Argument.
    • Die Taps beginnen mit dem dritten Zeichen, das durch ein beliebiges von Ihnen ausgewähltes Zeichen gekennzeichnet ist. Von da an wird das gleiche Zeichen "Intervall" Zeichen angezeigt.
    • Es wird nicht länger als die Länge sein.
  • Die vierte Zeile ist der Metarhythmus:
    • Es beginnt mit einem Großbuchstaben M, gefolgt von einem Leerzeichen.
    • Ab dem dritten Zeichen wird an jeder Stelle, an der auf die rechte oder linke Hand getippt wird, ein Zeichen (ein beliebiges Zeichen) angezeigt.
  • Das nachgestellte Leerzeichen ist irrelevant.

Testfälle:

r = 3, l = 2

  ------
R . . .
L .  .  
M . ...

r = 4, l = 3

  ------------
R .  .  .  .    
L .   .   .    
M .  .. . ..

r = 4, l = 5

  --------------------
R .    .    .    .                     
L .   .   .   .   .      
M .   ..  . . .  ..

r = 4, l = 7

  ----------------------------
R .      .      .      .      
L .   .   .   .   .   .   .   
M .   .  ..   . . .   ..  .

r = 4, l = 8

  --------
R . . . . 
L ........
M ........

Viel Spaß beim Golfen!

AJFaraday
quelle
Ihre Testfälle enthalten viele abschließende Leerzeichen. Können wir sie weglassen oder weitere hinzufügen?
Wastl
Müssen wir rund lals zwei getrennte Werte akzeptieren ? Können wir stattdessen beispielsweise ein Array mit zwei Elementen akzeptieren? Wie steht es mit der Reihenfolge, wird das genau rbefolgt l?
Sok
@Sok Das ist akzeptabel als Interpretation von "zwei Argumenten"
AJFaraday
Muss das Diagramm tatsächlich ausgedruckt werden, oder kann es einfach zurückgegeben werden?
Wiedereinsetzung von Monica - notmaynard
@iamnotmaynard Rückkehr ist in Ordnung.
AJFaraday

Antworten:

6

JavaScript (ES6), 131 Byte

Ausgabe 0als Tap- Zeichen.

r=>l=>`  ${g=n=>n?s.replace(/./g,(_,x)=>[,a=x%(k/r),x%=k/l,a*x][n]&&' '):++k%l|k%r?'-'+g():`-
`,s=g(k=0)}R ${g(1)}L ${g(2)}M `+g(3)

Probieren Sie es online!

Wie?

g()

g()0k=lcm(l,r)

g = _ => ++k % l | k % r ? '-' + g() : `-\n`

s

g()1n3xs0

g = n => s.replace(/./g, (_, x) => [, a = x % (k / r), x %= k / l, a * x][n] && ' ')
Arnauld
quelle
4

Java 11, 226 234 233 219 Bytes

String h(int r,int l,int m){var s="";for(;m>0;)s+=m%r*(m--%l)<1?'.':32;return s;}

r->l->{int a=r,b=l,m;for(;b>0;b=a%b,a=m)m=b;m=r*l/a;return"  "+repeat("-",m)+"\nR "+h(m/r,m+1,m)+"\nL "+h(m/l,m+1,m)+"\nM "+h(m/r,m/l,m);}

Art von langwierig; Schade, Java hat keine lcm()Funktion. Probieren Sie es hier online aus (TIO hat noch kein Java 11, daher wird stattdessen eine Hilfsmethode verwendet String.repeat()).

Meine ursprüngliche Version hat das Intervall zwischen den Klicks anstelle der Anzahl der Klicks verwendet. Jetzt behoben. Vielen Dank an Kevin Cruijssen für das Golfen mit 1 Byte.

Ungolfed:

String h(int r, int l, int m) { // helper function returning a line of metarhythm; parameters are: tap interval (right hand), tap interval (left hand), length
    var s = ""; // start with an empty String
    for(; m > 0; ) // repeat until the length is reached
        s += m % r * (m-- % l) < 1 ? '.' : 32; // if at least one of the hands taps, add a dot, otherwise add a space (ASCII code 32 is ' ')
    return s; // return the constructed line
}

r -> l -> { // lambda taking two integers in currying syntax and returning a String
    int a = r, b = l, m; // duplicate the inputs
    for(; b > 0; b = a % b, a = m) // calculate the GCD of r,l using Euclid's algorithm:
        m=b; // swap and replace one of the inputs by the remainder of their division; stop once it hits zero
    m = r * l / a; // calculate the length: LCM of r,l using a=GCD(r,l)
    return // build and return the output:
    "  " + "-".repeat(m) // first line, m dashes preceded by two spaces
    + "\nR " + h(m / r, m + 1, m) // second line, create the right-hand rhythm; by setting l = m + 1 for a metarhythm, we ensure there will be no left-hand taps
    + "\nL " + h(m / l, m + 1, m) // third line, create the left-hand rhythm the same way; also note that we pass the tap interval instead of the number of taps
    + "\nM " + h(m / r, m / l, m); // fourth line, create  the actual metarhythm
}
OOBalance
quelle
Es ist nicht viel, aber -1 Byte durch Ändern ?".":" "von ?'.':32.
Kevin Cruijssen
@KevinCruijssen Jedes Byte zählt :-) Danke!
OOBalance
4

Python 2 , 187 185 183 174 166 156 148 147 145 Bytes

Verwendet -als Tap-Zeichen

a,b=r,l=input()
while b:a,b=b,a%b
w=r*l/a
for x,y,z in zip(' RLM',(w,r,l,r),(w,r,l,l)):print x,''.join('- '[i%(w/y)!=0<i%(w/z)]for i in range(w))

Probieren Sie es online!


Gerettet:

  • -2 Bytes, danke an Jonathan Frech
TFeld
quelle
[i%(w/y)and i%(w/z)>0]könnte sein [i%(w/y)!=0<i%(w/z)].
Jonathan Frech
@ JonathanFrech Danke :)
TFeld
3

Perl 6 , 85 80 78 Bytes

-2 Bytes dank Jo King.

'  'R L M»Z~'-'x($!=[lcm] @_),|(@_.=map:{' '~(0~' 'x$!/$_-1)x$_}),[~|] @_}

Probieren Sie es online!

Gibt eine Liste mit vier Zeilen zurück.

nwellnhof
quelle
3

Python 2 , 185 228 223 234 249 Bytes

def f(r,l):
     c='.';d=' ';M,R,L=[r*l*[d]for _ in d*3]
     for i in range(r*l):
      if i%r<1:L[i]=M[i]=c
      if i%l<1:R[i]=M[i]=c
      if r<R.count(c)and l<L.count(c):R[i]=L[i]=M[i]=d;break
     print d,i*'-','\nR',''.join(R),'\nL',''.join(L),'\nM',''.join(M)

Probieren Sie es online!

sonrad10
quelle
Ich habe dies gerade in TIO kopiert und das generierte Format von dort übernommen. Es stellt sich heraus, dass es in weniger Bytes erledigt ist, als Sie dachten;)
AJFaraday
@Tfeld r=4, l=8funktioniert gut für mich
sonrad10
Die Länge soll das niedrigste gemeinsame Vielfache sein. Mit r = 4, l = 8 sollte das 8 sein, aber es scheint, dass Ihre Ausgabe viel länger ist (8 * 4?).
OOBalance
1
Das gibt der LCM noch nicht; ZB für 15,25, es gibt 375, aber es sollte sein 75.
OOBalance
1
Ich glaube der letzte Scheck kann durch ersetzt werden i%r+i%l+0**i<1. Sie können auch frühere Codeversionen entfernen, da diese in Ihrem Bearbeitungsverlauf von jedem, der sie sehen möchte, beibehalten werden
Jo King,
2

Jelly , 32 Bytes

æl/Ḷ%Ɱµa/ṭ=0ị⁾. Z”-;ⱮZ“ RLM”żK€Y

Probieren Sie es online!

Übernimmt die Eingabe als Liste [L,R].

æl/       Get LCM of this list.
   Ḷ      Range [0..LCM-1]
    %Ɱ    Modulo by-each-right (implicitly the input, [L,R]):
           [[0%L ... (LCM-1)%L], [0%R ... (LCM-1)%R]]
µ         Take this pair of lists, and:
 a/ṭ      Append their pairwise AND to the pair.
    =0    Is zero? Now we have a result like:
              [[1 0 0 1 0 0 1 0 0 1 0 0 1 0 0]
               [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0]
               [1 0 0 1 0 1 1 0 0 1 1 0 1 0 0]]

ị⁾.       Convert this into dots and spaces.
Z”-;ⱮZ    Transpose, prepend a dash to each, transpose. Now we have
              ['---------------'
               '.  .  .  .  .  '
               '.    .    .    '
               '.  . ..  .. .  ']

“ RLM”ż       zip(' RLM', this)
       K€     Join each by spaces.
         Y    Join the whole thing by newlines.
Lynn
quelle
1

C (gcc), 204 Bytes

p(s){printf(s);}
g(a,b){a=b?g(b,a%b):a;}
h(r,l,m){for(;m;)p(m%r*(m--%l)?" ":".");}
f(r,l,m,i){m=r*l/g(r,l);p("  ");for(i=m;i-->0;)p("-");p("\nR ");h(m/r,m+1,m);p("\nL ");h(m/l,m+1,m);p("\nM ");h(m/r,m/l,m);}

Port meiner Java- Antwort . Mit anrufen f(number_of_right_hand_taps, number_of_left_hand_taps). Probieren Sie es hier online aus .

OOBalance
quelle
200 Bytes
Ceilingcat
1

Pyth, 53 Bytes

j.b+NYc"  L R M "2++*\-J/*FQiFQKm*d+N*\ t/JdQsmeSd.TK

Auf jeden Fall Platz zum Golfen. Werde es tun, wenn ich Zeit habe.
Probieren Sie es hier aus

Erläuterung

j.b+NYc"  L R M "2++*\-J/*FQiFQKm*d+N*\ t/JdQsmeSd.TK
                       J/*FQiFQ                        Get the LCM.
                    *\-                                Take that many '-'s.
                               Km*d+N*\ t/dJQ          Fill in the taps.
                                             smeSd.TK  Get the metarhythm.
                  ++                                   Append them all.
      c"  L R M "2                                     Get the prefixes.
 .b+NY                                                 Prepend the prefixes.
j                                                      Join with newlines.

quelle
1

C # (Visual C # Interactive Compiler) , 254 Byte


Golf Versuchen Sie es online!

(r,l)=>{int s=l>r?l:r,S=s;while(S%l>0|S%r>0)S+=s;string q(int a){return"".PadRight(S/a,'.').Replace(".",".".PadRight(a,' '));}string R=q(S/r),L=q(S/l),M="";s=S;while(S-->0)M=(R[S]+L[S]>64?".":" ")+M;return"  ".PadRight(s+2,'-')+$"\nR {R}\nL {L}\nM {M}";}

Ungolfed

( r, l ) => {
    int
        s = l > r ? l : r,
        S = s;

    while( S % l > 0 | S % r > 0 )
        S += s;

    string q( int a ) {
        return "".PadRight( S / a, '.' ).Replace( ".", ".".PadRight( a, ' ' ) );
    }

    string
        R = q( S / r ),
        L = q( S / l ),
        M = "";

    s = S;

    while( S-- > 0 )
        M = ( R[ S ] + L[ S ] > 64 ? "." : " " ) + M;

    return "  ".PadRight( s + 2, '-') + $"\nR {R}\nL {L}\nM {M}";
}

Vollständiger Code

Func<Int32, Int32, String> f = ( r, l ) => {
    int
        s = l > r ? l : r,
        S = s;

    while( S % l > 0 | S % r > 0 )
        S += s;

    string q( int a ) {
        return "".PadRight( S / a, '.' ).Replace( ".", ".".PadRight( a, ' ' ) );
    }

    string
        R = q( S / r ),
        L = q( S / l ),
        M = "";

    s = S;

    while( S-- > 0 )
        M = ( R[ S ] + L[ S ] > 64 ? "." : " " ) + M;

    return "  ".PadRight( s + 2, '-') + $"\nR {R}\nL {L}\nM {M}";
};

Int32[][]
    testCases = new Int32[][] {
        new []{ 3, 2 },
        new []{ 4, 3 },
        new []{ 4, 5 },
        new []{ 4, 7 },
        new []{ 4, 8 },
    };

foreach( Int32[] testCase in testCases ) {
    Console.Write( $" Input: R: {testCase[0]}, L: {testCase[1]}\nOutput:\n{f(testCase[0], testCase[1])}" );
    Console.WriteLine("\n");
}

Console.ReadLine();

Releases

  • v1.0 - 254 bytes- Anfangslösung.

Anmerkungen

  • Keiner
auhmaan
quelle
1

Holzkohle , 52 Bytes

≔θζW﹪ζη≧⁺θζζ↙≔⮌Eζ⟦¬﹪×ιθζ¬﹪×ιηζ⟧ζFζ⊞ι⌈ι↓Eζ⭆ι§ .λ←↓RLM

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

≔θζW﹪ζη≧⁺θζ

Berechnen Sie den LCM der Eingaben, indem Sie das erste Vielfache dessen nehmen R, das durch teilbar ist L.

ζ↙

Drucken Sie das LCM, das automatisch die erforderliche Reihe von -s ausgibt . Bewegen Sie dann, um den Rhythmus von rechts nach links zu drucken.

≔⮌Eζ⟦¬﹪×ιθζ¬﹪×ιηζ⟧ζ

Durchlaufen Sie die Zahlen vom LCM bis auf 0 und erstellen Sie eine Reihe von Listen, die die Beats der rechten und linken Hand darstellen.

Fζ⊞ι⌈ι

Überfliege die Beats und füge den Metarhythmus hinzu.

↓Eζ⭆ι§ .λ

Drucken Sie die umgekehrten Beats nach unten, aber da es sich um ein Array handelt, werden sie nach links verschoben.

←↓RLM

Drucken Sie die Kopfzeile.

Neil
quelle
1

Ruby , 130 126 Bytes

->*a{puts"  "+?-*s=a[0].lcm(a[1])
r,l=a.map!{|e|(?.+' '*(s/e-1))*e}
[?R,?L,?M].zip(a<<r.gsub(/ /){l[$`.size]}){|e|puts e*" "}}

Probieren Sie es online!

Setzen Sie Monica wieder ein - notmaynard
quelle
1

Python 2 , 117 Bytes

a,b=input();n=a
while n%b:n+=a
for i in-1,1,2,3:print'_RLM '[i],''.join(' -'[i%2>>m*a%n|i/2>>m*b%n]for m in range(n))

Probieren Sie es online!

xnor
quelle
1

Pyth, 49 Bytes

J/*FQiFQjC+c2" RLM    "ms@L" -"!M++0d*Fdm%Ld/LJQJ

Erwartet Eingaben in das Formular [r,l]. Dient -zum Anzeigen von Taps. Versuchen Sie es online hier , oder prüfen Sie alle Testfälle auf einmal hier .

J/*FQiFQjC+c2" RLM    "ms@L" -"!M++0d*Fdm%Ld/LJQJ   Implicit: Q=eval(input())
 /*FQiFQ                                            Compute LCM: (a*b)/(GCD(a,b))
J                                                   Store in J
                                        m       J   Map d in [0-LCM) using:
                                            /LJQ      Get number of beats between taps for each hand
                                         %Ld          Take d mod each of the above
                                                    This gives a pair for each beat, with 0 indicating a tap
                       m                            Map d in the above using:
                                     *Fd              Multiply each pair (effecively an AND)
                                 ++0d                 Prepend 0 and the original pair
                               !M                     NOT each element
                        s@L" -"                       Map [false, true] to [' ', '-'], concatenate strings
                                                    This gives each column of the output
           c2" RLM    "                             [' RLM','    ']
          +                                         Prepend the above to the rest of the output
         C                                          Transpose
        j                                           Join on newlines, implicit print
Sok
quelle
1

R , 161 149 146 Bytes

function(a,b){l=numbers::LCM(a,b)
d=c(0,' ')
cat('  ',strrep('-',l),'\nR ',d[(x<-l:1%%a>0)+1],'\nL ',d[(y<-l:1%%b>0)+1],'\nM ',d[(x&y)+1],sep='')}

Probieren Sie es online!

Ich habe definitiv das Gefühl, dass es hier Raum für Verbesserungen gibt, aber ich habe ein paar verschiedene Ansätze ausprobiert und dies ist der einzige, der stecken geblieben ist. Die interne Funktionsdefinition loszuwerden würde mich sehr freuen, und ich habe eine Reihe von Umstrukturierungen von cat () versucht, um dies zu erreichen. Aber egal, als ich gepostet habe, wurde mir klar, was ich tun konnte. Dennoch sind definitiv einige Einsparungen bei der Effizienz zu verzeichnen.

Es gibt andere LCM-Funktionen in Bibliotheken mit kürzeren Namen, aber TIO hat Nummern, und ich hielt das an dieser Stelle für wertvoller.

KriminellVulgar
quelle
1

C ++ (gcc) , 197 Bytes

int f(int a,int b){std::string t="  ",l="\nL ",r="\nR ",m="\nM ";int c=-1,o,p=0;for(;++p%a||p%b;);for(;o=++c<p;t+="-")l+=a*c%p&&++o?" ":".",r+=b*c%p&&++o?" ":".",m+=o-3?".":" ";std::cout<<t+l+r+m;}

Probieren Sie es online!

Annyo
quelle
Schlagen Sie ++p%a+p%bstattdessen vor++p%a||p%b
ceilingcat