Aidez-moi avec mes polyrythmies

17

Je suis musicien et j'ai besoin de plus de polyrythmies dans ma vie!

Un polyrythmie se produit dans la musique (et dans la nature) lorsque deux événements (applaudissements, notes, lucioles clignotantes, etc.) se produisent à deux intervalles réguliers différents. Les deux types d'événements se produisent un nombre différent de fois dans le même intervalle.

Si je tape avec ma main gauche deux fois, et avec ma main droite 3 fois, dans le même espace de temps, cela ressemble un peu à ceci:

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

Les tirets en haut indiquent la longueur du motif polyrthmique, qui est le plus petit commun multiple ou 2 et 3. Cela peut être compris comme le point auquel le motif se répète.

Il y a aussi un `` rythme rythmique '', qui est le motif produit lorsque l'une des mains tape:

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

Il s'agit d'un polyrythmie simple et très courant, avec un rapport de 3: 2.

Disons simplement que je ne veux pas faire un polyrythmie simple que je peux travailler dans ma tête, j'ai donc besoin de quelque chose pour le faire pour moi. Je pourrais le faire en long sur papier, ou ...


Règles:

  • Écrivez du code pour générer et afficher un diagramme de polyrythmie, comme décrit ci-dessus.
  • N'importe quelle langue ancienne, essayez le moins d'octets.
  • Votre code prend deux arguments:
    • Nombre de tapotements avec la main gauche (entier positif)
    • Nombre de tapotements avec la main droite (entier positif)
  • Il calculera la longueur, qui est le plus petit commun multiple pour les deux arguments.
  • La ligne du haut sera composée de deux caractères blancs suivis de tirets affichant la longueur (longueur * '-')
  • Les deuxième et troisième lignes montreront le motif pour les mains droite et gauche:
    • Il commencera par un R ou un L, indiquez de quelle main il s'agit, suivi d'un espace.
    • L'intervalle pour cette main est la longueur divisée par son argument.
    • Les tapotements commenceront au troisième caractère, indiqué par n'importe quel caractère que vous choisissez. A partir de là, il affichera les mêmes caractères «intervalle» de caractère.
    • Il ne sera pas plus long que la ligne de longueur.
  • La quatrième ligne est le métarythme:
    • Il commencera par un majuscule M, suivi d'un espace.
    • À partir du troisième personnage, il affichera un personnage (n'importe quel personnage que vous choisissez) dans chaque position où il y a un tap sur la main droite ou la main gauche.
  • L'espace de fuite n'est pas pertinent.

Cas de test:

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

Bon golf!

AJFaraday
la source
Vos cas de test incluent beaucoup d'espaces de fin, pouvons-nous les omettre / ajouter plus?
wastl
Faut-il accepter ret lcomme deux valeurs distinctes? Pourrions-nous accepter un tableau à deux éléments à la place, par exemple? Qu'en est-il de leur ordre, est-ce strictement rsuivi l?
Sok
@Sok C'est acceptable comme interprétation de «deux arguments»
AJFaraday
Doit-il réellement imprimer le diagramme ou peut-il simplement le retourner?
Rétablir Monica - notmaynard
@iamnotmaynard revient très bien.
AJFaraday

Réponses:

6

JavaScript (ES6), 131 octets

Sort 0comme le caractère tap .

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)

Essayez-le en ligne!

Comment?

Nous utilisons la même fonction d'aide à deux fins différentes.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
la source
4

Java 11, 226 234 233 219 octets

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);}

Un peu long; dommage Java n'a pas de lcm()fonction. Essayez-le en ligne ici (TIO n'a pas encore Java 11, donc cela utilise une méthode d'assistance à la place de String.repeat()).

Ma version initiale a pris l'intervalle entre les tapotements au lieu du nombre de tapotements. Fixé maintenant. Merci à Kevin Cruijssen d' avoir joué au golf 1 octet.

Non golfé:

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
la source
Ce n'est pas beaucoup, mais -1 octet en changeant ?".":" "en ?'.':32.
Kevin Cruijssen
@KevinCruijssen Chaque octet compte :-) Merci!
OOBalance
4

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

Utilise -comme caractère tap

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

Essayez-le en ligne!


Enregistré:

  • -2 octets, merci à Jonathan Frech
TFeld
la source
[i%(w/y)and i%(w/z)>0]pourrait être [i%(w/y)!=0<i%(w/z)].
Jonathan Frech
@JonathanFrech Merci :)
TFeld
3

Perl 6 , 85 80 78 octets

-2 octets grâce à Jo King.

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

Essayez-le en ligne!

Renvoie une liste de quatre lignes.

nwellnhof
la source
3

Python 2 , 185 228 223 234 249 octets

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)

Essayez-le en ligne!

sonrad10
la source
Je viens de copier-coller ceci dans TIO et j'ai pris le format généré à partir de là. Il s'avère que cela se fait en moins d'octets que vous ne le pensiez;)
AJFaraday
@Tfeld r=4, l=8fonctionne bien pour moi
sonrad10
La longueur est supposée être le plus petit commun multiple. Avec r = 4, l = 8, cela devrait être 8, mais il semble que votre sortie soit beaucoup plus longue (8 * 4?).
OOBalance
1
Cela ne donne toujours pas le LCM; par exemple pour 15,25, ça donne 375, mais ça devrait l'être 75.
OOBalance
1
Je pense que le dernier chèque peut être remplacé par i%r+i%l+0**i<1. En outre, vous pouvez supprimer les versions précédentes du code, car elles seront conservées dans votre historique d'édition de quiconque veut les voir
Jo King
2

Gelée , 32 octets

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

Essayez-le en ligne!

Prend la saisie sous forme de 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
la source
1

C (gcc), 204 octets

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 de ma réponse Java . Appelez avec f(number_of_right_hand_taps, number_of_left_hand_taps). Essayez-le en ligne ici .

OOBalance
la source
200 octets
plafondcat
1

Pyth, 53 octets

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

Certainement de la place pour jouer au golf. Je le ferai quand j'aurai le temps.
Essayez-le ici

Explication

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.

la source
1

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


Golfé Essayez-le en ligne!

(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}";}

Non golfé

( 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}";
}

Code complet

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

Communiqués

  • v1.0 - 254 bytes- Solution initiale.

Remarques

  • Aucun
auhmaan
la source
1

Fusain , 52 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

≔θζW﹪ζη≧⁺θζ

Calculez le LCM des entrées en prenant le premier multiple Rdivisible par L.

ζ↙

Imprimez le LCM, qui sort automatiquement la ligne nécessaire de - s. Ensuite, déplacez pour imprimer le rythme de droite à gauche.

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

Faites une boucle sur les nombres du LCM jusqu'à 0 et créez un tableau de listes représentant les battements des mains droite et gauche.

Fζ⊞ι⌈ι

Faites une boucle sur les temps et ajoutez le métarythmie.

↓Eζ⭆ι§ .λ

Imprimez les temps inversés vers le bas, mais comme il s'agit d'un tableau, ils se retrouvent à gauche.

←↓RLM

Imprimez l'en-tête.

Neil
la source
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*" "}}

Essayez-le en ligne!

Réintégrer Monica - notmaynard
la source
1

Python 2 , 117 octets

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

Essayez-le en ligne!

xnor
la source
1

Pyth, 49 octets

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

Attend l'entrée dans le formulaire [r,l]. Utilise -pour afficher les taps. Essayez-le en ligne ici ou vérifiez tous les cas de test en même temps ici .

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
la source
1

R , 161 149 146 octets

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='')}

Essayez-le en ligne!

J'ai vraiment l'impression qu'il y a place à amélioration ici, mais j'ai essayé quelques approches différentes et c'est la seule qui est restée. Se débarrasser de la définition de la fonction interne me rendrait très heureux, et j'ai essayé un tas de restructurations de cat () pour y arriver. Peu importe, dès que j'ai posté, j'ai réalisé ce que je pouvais faire. Encore certainement des économies d'efficacité à trouver.

Il existe d'autres fonctions LCM dans les bibliothèques avec des noms plus courts, mais TIO a des nombres et j'ai considéré que c'était plus utile à ce stade.

CriminellementVulgar
la source
1

C ++ (gcc) , 197 octets

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

Essayez-le en ligne!

Annyo
la source
Suggérer ++p%a+p%bau lieu de++p%a||p%b
plafond