Допоможіть мені з моїми поліритмами


17

Я музикант, і мені потрібно більше поліритмів у житті!

Поліритм виникає в музиці (і в природі), коли відбувається дві події (хлопання, ноти, миготіння світлячків тощо) з двома різними регулярними інтервалами. Два види події трапляються різну кількість разів за один і той же інтервал.

Якщо я торкаюся лівою рукою двічі, а правою рукою 3 рази, за той же проміжок часу, це виглядає трохи так:

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

Дефіси вгорі позначають довжину поліритмічного малюнка, яка є найменшим загальним кратним або 2 і 3. Це можна зрозуміти як точку, в якій повторюється візерунок.

Існує також "метаризм", який є зразком, що утворюється при натисканні будь-якої руки:

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

Це простий і дуже поширений поліритм із співвідношенням 3: 2.

Скажімо просто, що я не хочу робити простий поліритм, який я можу опрацювати в голові, тому мені потрібно щось розробити для мене. Я міг би зробити це на довгій формі на папері, або ...


Правила:

  • Напишіть деякий код для створення та відображення діаграми поліритму, як описано вище.
  • Будь-яка стара мова, спробуйте найменше байтів.
  • Ваш код бере два аргументи:
    • Кількість відводів лівою рукою (додатне ціле число)
    • Кількість натискань правою рукою (натуральне число)
  • Він визначить довжину, яка є найнижчим загальним кратним для двох аргументів.
  • Верхня лінія буде складатися з двох символів пробілу, а потім дефісів із довжиною (довжина * '-')
  • У другому та третьому рядках буде показано схему для правої та лівої руки:
    • Почнеться з R або L, позначте, яка це рука, а потім пробіл.
    • Інтервал для цієї руки - це довжина, поділена на аргумент.
    • Мітки починатимуться з третього символу, який позначатиметься будь-яким обраним вами символом. З цього моменту він відображатиме однакові символи "інтервалу" один від одного.
    • Вона не буде довшою, ніж лінія довжини.
  • Четвертий рядок - метаритм:
    • Почнеться з верхнього регістру М, після чого пробіл.
    • Починаючи з третього символу, він показуватиме персонаж (будь-який обраний вами персонаж) у кожному положенні, де є крана правої чи лівої руки.
  • Пробіл пробігу не має значення.

Тестові приклади:

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

Щасливого гольфу!


Ваші тестові випадки містять багато пробілів пробілу, чи можемо ми їх опустити / додати ще?
wastl

Чи потрібно приймати rі lяк дві окремі величини? Чи можемо ми замість цього прийняти двоелементний масив? Як щодо порядку їх дотримання, це суворо rдотримується l?
Сок

@ Сок Це прийнятно як тлумачення "двох аргументів"
AJFaraday,

Чи потрібно насправді роздрукувати діаграму, чи може просто повернути її?
Відновіть Моніку - немайнард

@iamnotmaynard повернення добре.
AJFaraday

Відповіді:


6

JavaScript (ES6), 131 байт

Виводиться 0як символ крана .

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)

Спробуйте в Інтернеті!

Як?

Ми використовуємо той же допоміжну функцію 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] && ' ')

4

Java 11, 226 234 233 219 байт

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

Вид тривалий; занадто погана Java не має lcm()функції. Спробуйте його в Інтернеті тут (у TIO ще немає Java 11, тому для цього використовується допоміжний метод String.repeat()).

У моїй початковій версії прийнято інтервал між кранами замість кількості натискань. Виправлено зараз. Дякую Кевіну Крейсейну за те, що він займався 1 байтом для гри в гольф.

Безумовно:

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
}

Це не багато, але -1 байт, змінивши ?".":" "на ?'.':32.
Kevin Cruijssen

@KevinCruijssen Кожен байт рахується :-) Дякую!
OOBalance

4

Пітон 2 , 187 185 183 174 166 156 148 147 145 байт

Використовується -як символ крана

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

Спробуйте в Інтернеті!


Збережено:

  • -2 байти, завдяки Джонатану Фреху

[i%(w/y)and i%(w/z)>0]могло бути [i%(w/y)!=0<i%(w/z)].
Джонатан Фрех

@JonathanFrech Спасибі :)
TFeld


3

Python 2 , 185 228 223 234 249 байт

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)

Спробуйте в Інтернеті!


Я просто скопіював це в TIO і взяв згенерований формат звідти. Виявляється, це робиться в меншій кількості байтів, ніж ви думали;)
AJFaraday

@Tfeld r=4, l=8 для мене прекрасно працює
sonrad10

Довжина повинна бути найменшим загальним кратним. З r = 4, l = 8, це має бути 8, але, здається, ваш вихід набагато довший (8 * 4?).
OOBalance

1
Це все ще не дає LCM; наприклад 15,25, це дає 375, але так і має бути 75.
OOBalance

1
Я вважаю, останню перевірку можна замінити на i%r+i%l+0**i<1 . Також ви можете видалити попередні версії коду, оскільки вони зберігатимуться у вашій історії редагування всіх, хто хоче їх побачити
Jo King

2

Желе , 32 байти

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

Спробуйте в Інтернеті!

Вводиться як список [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.

1

C (gcc), 204 байт

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

Порт моєї відповіді на Java . Подзвоніть з f(number_of_right_hand_taps, number_of_left_hand_taps). Спробуйте його онлайн тут .



1

Pyth, 53 байти

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

Однозначно номер для гольфу. Зробимо це, коли встигну.
Спробуйте тут

Пояснення

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.

1

C # (Visual C # Interactive Compiler) , 254 байти


Гольф Спробуйте в Інтернеті!

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

Безумовно

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

Повний код

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

Релізи

  • v1.0 - 254 bytes- Початкове рішення.

Примітки

  • Немає

1

Вугілля деревне , 52 байти

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

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

≔θζW﹪ζη≧⁺θζ

Обчисліть LCM входів, взявши перше кратне, Rщо ділиться на L.

ζ↙

Роздрукуйте LCM, який автоматично виводить необхідний рядок -s. Потім перейдіть до друку ритму справа наліво.

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

Переведіть цифри з LCM на 0 і створіть масив списків, що представляють удари правої та лівої руки.

Fζ⊞ι⌈ι

Переведіть петлю над ударами і додайте метаритм.

↓Eζ⭆ι§ .λ

Друкуйте зворотні удари вниз, але оскільки це масив, вони закінчуються вліво.

←↓RLM

Роздрукуйте заголовок.




1

Pyth, 49 байт

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

Очікує введення форми [r,l]. Використовує -для відображення кранів. Спробуйте в Інтернеті тут або перевірити всі тестові випадки тут .

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

1

R , 161 149 146 байт

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

Спробуйте в Інтернеті!

Я, безумовно, відчуваю, що тут є місце для вдосконалення, але я спробував кілька різних підходів, і це єдиний, хто застряг. Позбавлення від визначення внутрішніх функцій зробило б мене дуже щасливим, і я спробував купу реструктуризації кота (), щоб це відбулося.Не забудьте, як тільки я розмістив повідомлення, я зрозумів, що можу зробити. Проте, безумовно, можна знайти деякі економії ефективності.

Є інші функції LCM у бібліотеках із короткими назвами, але TIO має цифри, і я вважав, що на даний момент це цінніше.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.