Pomóż mi z moimi polirytmami

17

Jestem muzykiem i potrzebuję więcej rytmów w moim życiu!

Polirytm występuje w muzyce (i w naturze), gdy dwa zdarzenia (klaszcze, nuty, migające świetliki itp.) Występują w dwóch różnych regularnych odstępach czasu. Te dwa zdarzenia zdarzają się różną liczbę razy w tym samym przedziale czasowym.

Jeśli stuknę lewą ręką dwa razy, a prawą 3 razy w tym samym czasie, wygląda to trochę tak:

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

Łączniki u góry oznaczają długość wzoru wielotermicznego, który jest najniższą wspólną wielokrotnością lub 2 i 3. Można to rozumieć jako punkt, w którym wzór się powtarza.

Istnieje również „rytm”, który jest wzorem generowanym, gdy któraś ręka stuka:

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

Jest to prosty i bardzo popularny polirytm o stosunku 3: 2.

Powiedzmy, że nie chcę robić prostego polirytmu, który mogę wypracować w mojej głowie, więc potrzebuję czegoś, aby to dla mnie wypracować. Mógłbym to zrobić w formie długiej na papierze lub ...


Zasady:

  • Napisz kod, aby wygenerować i wyświetlić diagram polirytmii, jak opisano powyżej.
  • Dowolny stary język, spróbuj uzyskać jak najmniej bajtów.
  • Twój kod przyjmuje dwa argumenty:
    • Liczba uderzeń lewą ręką (dodatnia liczba całkowita)
    • Liczba uderzeń prawą ręką (dodatnia liczba całkowita)
  • Wyliczy długość, która jest najniższą wspólną wielokrotnością dwóch argumentów.
  • Górny wiersz będzie się składał z dwóch białych znaków, a następnie łączników wyświetlających długość (długość * '-')
  • Druga i trzecia linia pokażą wzór dla prawej i lewej ręki:
    • Zacznie się od R lub L, zaznacz, która to ręka, a następnie spację.
    • Interwał dla tej ręki jest długością podzieloną przez argument.
    • Krany zaczną się od trzeciego znaku, oznaczonego dowolną wybraną postacią. Od tego momentu wyświetla te same znaki „odstęp” między znakami.
    • Nie będzie dłuższy niż linia długości.
  • Czwarta linia to rytm:
    • Rozpocznie się od dużej litery M, po której nastąpi spacja.
    • Od trzeciej postaci będzie ona wyświetlała postać (dowolną wybraną przez ciebie postać) na każdej pozycji, w której dotknie się prawej lub lewej ręki.
  • Końcowe białe znaki nie mają znaczenia.

Przypadki testowe:

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

Miłej gry w golfa!

AJFaraday
źródło
Twoje przypadki testowe zawierają wiele białych spacji, czy możemy je pominąć / dodać więcej?
wastl
Czy musimy zaakceptować ri ljako dwie odrębne wartości? Czy możemy na przykład zaakceptować tablicę dwuelementową? A co z ich kolejnością, czy jest to ściśle rprzestrzegane l?
Sok
@Sok Jest to dopuszczalne jako interpretacja „dwóch argumentów”
AJFaraday
Czy rzeczywiście musi wydrukować schemat, czy może po prostu go zwrócić?
Przywróć Monikę - notmaynard
Zwrot @iamnotmaynard jest w porządku.
AJFaraday

Odpowiedzi:

6

JavaScript (ES6), 131 bajtów

Wyprowadza 0jako znak kranu .

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)

Wypróbuj online!

W jaki sposób?

Używamy tej samej funkcji pomocniczej do dwóch różnych celów.sol()

Kiedy jest wywoływane bez argumentu lub argumentu równego 0 , rekurencyjnie buduje ciąg łącznika o długości k = lcm ( l , r ) z końcowym przesuwem linii:sol()0k=lcm(l,r)

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

Ten ciąg jest zapisywany w .s

sol()1n3)xs0

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

Java 11, 226 234 233 219 bajtów

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

Długo; szkoda, że ​​Java nie ma lcm()funkcji. Wypróbuj online tutaj (TIO nie ma jeszcze Java 11, więc zamiast tego używa metody pomocniczejString.repeat() ).

Moja początkowa wersja zajęła przerwę między dotknięciami zamiast liczby uderzeń. Naprawiono teraz. Dzięki Kevin Cruijssen za grę w golfa 1 bajt.

Nie golfowany:

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
źródło
To niewiele, ale -1 bajt, zmieniając ?".":" "na ?'.':32.
Kevin Cruijssen
@KevinCruijssen Każdy bajt się liczy :-) Dzięki!
OOBalance
4

Python 2 , 187 185 183 174 166 156 148 147 145 bajtów

Używa -jako znaku kranu

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

Wypróbuj online!


Zapisano:

  • -2 bajty, dzięki Jonathan Frech
TFeld
źródło
[i%(w/y)and i%(w/z)>0]może być [i%(w/y)!=0<i%(w/z)].
Jonathan Frech,
@JonathanFrech Thanks :)
TFeld
3

Perl 6 , 85 80 78 bajtów

-2 bajty dzięki Jo King.

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

Wypróbuj online!

Zwraca listę czterech linii.

nwellnhof
źródło
3

Python 2 , 185 228 223 234 249 bajtów

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)

Wypróbuj online!

sonrad10
źródło
Właśnie skopiowałem to do TIO i stamtąd wziąłem wygenerowany format. Okazuje się, że zrobiono to w mniejszej liczbie bajtów niż myślisz;)
AJFaraday
@Tfeld r=4, l=8działa dla mnie dobrze
sonrad10
Długość ma być najniższą wspólną wielokrotnością. Przy r = 4, l = 8, powinno to być 8, ale wydaje się, że twój wynik jest znacznie dłuższy (8 * 4?).
OOBalance
1
To wciąż nie daje LCM; np 15,25. daje 375, ale powinno być 75.
OOBalance,
1
Uważam, że ostatni czek można zastąpić i%r+i%l+0**i<1. Możesz także usunąć poprzednie wersje kodu, ponieważ zostaną one zachowane w historii edycji każdego, kto chce je zobaczyć
Jo King
2

Galaretka , 32 bajty

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

Wypróbuj online!

Pobiera dane wejściowe jako listę [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
źródło
1

C (gcc), 204 bajty

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 mojej odpowiedzi Java . Zadzwoń z f(number_of_right_hand_taps, number_of_left_hand_taps). Wypróbuj online tutaj .

OOBalance
źródło
200 bajtów
ceilingcat
1

Pyth, 53 bajty

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

Zdecydowanie miejsce na golfa. Zrobię to, gdy będę miał czas.
Wypróbuj tutaj

Wyjaśnienie

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.

źródło
1

C # (interaktywny kompilator Visual C #) , 254 bajty


Gra w golfa Wypróbuj 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}";}

Bez golfa

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

Pełny kod

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

Prasowe

  • v1.0 - 254 bytes- Wstępne rozwiązanie.

Notatki

  • Żaden
auhmaan
źródło
1

Węgiel , 52 bajty

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

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

≔θζW﹪ζη≧⁺θζ

Oblicz LCM danych wejściowych, biorąc pierwszą wielokrotność tego R, przez którą można podzielić L.

ζ↙

Wydrukuj LCM, który automatycznie wyświetli wymagany wiersz -s. Następnie przejdź do drukowania rytmu od prawej do lewej.

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

Zapętlaj liczby od LCM do 0 i utwórz tablicę list reprezentujących uderzenia prawej i lewej ręki.

Fζ⊞ι⌈ι

Pętlę nad uderzeniami i dodaj rytm.

↓Eζ⭆ι§ .λ

Wydrukuj odwrócone uderzenia w dół, ale ponieważ jest to tablica, kończą się w lewo.

←↓RLM

Wydrukuj nagłówek.

Neil
źródło
1

Rubin , 130 126 bajtów

->*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*" "}}

Wypróbuj online!

Przywróć Monikę - notmaynard
źródło
1

Python 2 , 117 bajtów

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

Wypróbuj online!

xnor
źródło
1

Pyth, 49 bajtów

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

Oczekuje danych wejściowych w formularzu [r,l]. Używa -do wyświetlania kranów. Spróbuj go online tutaj , lub sprawdzić wszystkie przypadki testowe od razu tutaj .

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
źródło
1

R , 161 149 146 bajtów

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

Wypróbuj online!

Zdecydowanie czuję, że jest tu miejsce na poprawę, ale wypróbowałem kilka różnych podejść i tylko to utknęło. Pozbycie się definicji funkcji wewnętrznej sprawi, że będę całkiem szczęśliwy, i spróbowałem zrobić kilka zmian struktury cat (), aby tak się stało. Nieważne, jak tylko opublikowałem, zdałem sobie sprawę, co mogę zrobić. Nadal zdecydowanie można znaleźć oszczędności wydajności.

Istnieją inne funkcje LCM w bibliotekach o krótszych nazwach, ale TIO ma liczby i uważam, że w tym momencie jest to bardziej wartościowe.

Kryminalnie Wulgarne
źródło
1

C ++ (gcc) , 197 bajtów

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

Wypróbuj online!

Annyo
źródło
Zaproponuj ++p%a+p%bzamiast++p%a||p%b
ceilingcat