Ayudame con mis polirritmos

17

¡Soy músico y necesito más polirritmos en mi vida!

Se produce una polirritmia en la música (y en la naturaleza) cuando ocurren dos eventos (aplausos, notas, luciérnagas, etc.) en dos intervalos regulares diferentes. Los dos tipos de eventos ocurren una cantidad diferente de veces en el mismo intervalo.

Si toco con la mano izquierda dos veces y con la mano derecha 3 veces, en el mismo espacio de tiempo, se ve un poco así:

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

Los guiones en la parte superior denotan la longitud del patrón polítmico, que es el múltiplo común más bajo o 2 y 3. Esto puede entenderse como el punto en el que se repite el patrón.

También hay un 'metarritmo', que es el patrón producido cuando cualquiera de las manos toca:

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

Esta es una polirritmia simple y muy común, con una proporción de 3: 2.

Digamos que no quiero hacer una simple polirritmia que pueda resolver en mi cabeza, así que necesito algo para resolverlo por mí. Podría hacerlo en formato largo en papel, o ...


Reglas:

  • Escriba un código para generar y mostrar un diagrama de polirritmia, como se describió anteriormente.
  • Cualquier idioma antiguo, intente con la menor cantidad de bytes.
  • Su código toma dos argumentos:
    • Número de toques con la mano izquierda (entero positivo)
    • Número de toques con la mano derecha (entero positivo)
  • Resolverá la longitud, que es el múltiplo común más bajo para los dos argumentos.
  • La línea superior constará de dos caracteres de espacio en blanco seguidos de guiones que muestran la longitud (longitud * '-')
  • La segunda y tercera líneas mostrarán el patrón para las manos derecha e izquierda:
    • Comenzará con una R o L, denote qué mano es, seguido de un espacio.
    • El intervalo para esa mano es la longitud dividida por su argumento.
    • Los toques comenzarán en el tercer carácter, denotado por cualquier personaje que elija. A partir de entonces, mostrará los mismos caracteres de 'intervalo' de caracteres separados.
    • No será más largo que la línea de longitud.
  • La cuarta línea es el metarritmo:
    • Comenzará con una M mayúscula, seguida de un espacio.
    • A partir del tercer personaje, mostrará un personaje (cualquier personaje que elija) en cada posición donde haya un toque en la mano derecha o izquierda.
  • El espacio en blanco al final es irrelevante.

Casos de prueba:

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

¡Feliz golf!

AJFaraday
fuente
Sus casos de prueba incluyen muchos espacios en blanco al final, ¿podemos omitirlos / agregar más?
wastl
¿Tenemos que aceptar ry lcomo dos valores separados? ¿Podríamos aceptar una matriz de dos elementos, por ejemplo? ¿Qué tal el orden de ellos, es estrictamente rseguido l?
Sok
@Sok Eso es aceptable como una interpretación de 'dos ​​argumentos'
AJFaraday
¿Necesita realmente imprimir el diagrama, o puede simplemente devolverlo?
Restablece a Monica - notmaynard el
@iamnotmaynard volver está bien.
AJFaraday

Respuestas:

6

JavaScript (ES6), 131 bytes

Salidas 0como el carácter de 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)

Pruébalo en línea!

¿Cómo?

Utilizamos la misma función auxiliar para dos propósitos diferentes.sol()

sol()0 0k=mcm(l,r)

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

s

sol()1norte3Xs0 0

g = n => s.replace(/./g, (_, x) => [, a = x % (k / r), x %= k / l, a * x][n] && ' ')
Arnauld
fuente
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);}

Tipo de largo; lástima que Java no tenga una lcm()función. Pruébelo en línea aquí (TIO todavía no tiene Java 11, por lo que utiliza un método auxiliar en lugar deString.repeat() ).

Mi versión inicial tomó el intervalo entre toques en lugar del número de toques. Corregido ahora. Gracias a Kevin Cruijssen por jugar al golf 1 byte.

Sin 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
fuente
No es mucho, pero -1 byte al cambiar ?".":" "a ?'.':32.
Kevin Cruijssen
@KevinCruijssen Cada byte cuenta :-) ¡Gracias!
OOBalance
4

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

Usos - como el personaje de 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))

Pruébalo en línea!


Salvado:

  • -2 bytes, gracias a Jonathan Frech
TFeld
fuente
[i%(w/y)and i%(w/z)>0]podría ser [i%(w/y)!=0<i%(w/z)].
Jonathan Frech
@JonathanFrech Gracias :)
TFeld
3

Perl 6 , 85 80 78 bytes

-2 bytes gracias a Jo King.

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

Pruébalo en línea!

Devuelve una lista de cuatro líneas.

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

Pruébalo en línea!

sonrad10
fuente
Acabo de copiar esto en TIO y tomar el formato generado desde allí. Resulta que se hace en menos bytes de lo que pensabas;)
AJFaraday
@Tfeld r=4, l=8funciona bien para mí
sonrad10
Se supone que la longitud es el mínimo común múltiplo. Con r = 4, l = 8, eso debería ser 8, pero parece que su salida es mucho más larga (8 * 4?).
OOBalance
1
Eso todavía no da el LCM; por ejemplo para 15,25, da 375, pero debería ser 75.
OOBalance
1
Creo que el último cheque puede ser reemplazado por i%r+i%l+0**i<1. Además, puede eliminar versiones anteriores del código, ya que se conservarán en su historial de edición de cualquier persona que quiera verlas
Jo King
2

Jalea , 32 bytes

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

Pruébalo en línea!

Toma la entrada como una lista [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
fuente
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);}

Puerto de mi respuesta Java . Llamada con f(number_of_right_hand_taps, number_of_left_hand_taps). Pruébelo en línea aquí .

OOBalance
fuente
200 bytes
ceilingcat
1

Pyth, 53 bytes

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

Definitivamente espacio para golf. Lo haré cuando tenga tiempo.
Pruébalo aquí

Explicación

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.

fuente
1

C # (compilador interactivo de Visual C #) , 254 bytes


Golfed Pruébalo en línea!

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

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

Código completo

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

Lanzamientos

  • v1.0 - 254 bytes- Solución inicial.

Notas

  • Ninguna
auhmaan
fuente
1

Carbón , 52 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

≔θζW﹪ζη≧⁺θζ

Calcule el MCM de las entradas tomando el primer múltiplo de Rque es divisible por L.

ζ↙

Imprima el LCM, que genera automáticamente la fila necesaria de -s. Luego, mueva para imprimir el ritmo de derecha a izquierda.

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

Pase los números del LCM hacia abajo hasta 0 y cree una serie de listas que representen los latidos de las manos derecha e izquierda.

Fζ⊞ι⌈ι

Recorre los ritmos y agrega el metarritmo.

↓Eζ⭆ι§ .λ

Imprima los latidos invertidos hacia abajo, pero como se trata de una matriz, terminan hacia la izquierda.

←↓RLM

Imprime el encabezado.

Neil
fuente
1

Rubí , 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*" "}}

Pruébalo en línea!

Restablecer a Monica - notmaynard
fuente
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))

Pruébalo en línea!

xnor
fuente
1

Pyth, 49 bytes

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

Espera entrada en el formulario [r,l]. Utiliza -para mostrar grifos. Pruébelo en línea aquí , o verifique todos los casos de prueba a la vez aquí .

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

Pruébalo en línea!

Definitivamente siento que hay margen de mejora aquí, pero probé algunos enfoques diferentes y este es el único que se quedó. Deshacerme de la definición de la función interna me haría muy feliz, y probé un montón de reestructuraciones de cat () para que sucediera. No importa, tan pronto como publiqué me di cuenta de lo que podía hacer. Todavía definitivamente se pueden encontrar algunos ahorros de eficiencia.

Hay otras funciones LCM en bibliotecas con nombres más cortos, pero TIO tiene números y lo consideré más valioso en este momento.

Criminalmente vulgar
fuente
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;}

Pruébalo en línea!

Annyo
fuente
Sugerir en ++p%a+p%blugar de++p%a||p%b
ceilingcat