Помоги мне с моими полиритмами


17

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

Полиритм возникает в музыке (и в природе), когда два события (хлопки, ноты, мигание светлячков и т. Д.) Происходят с двумя разными регулярными интервалами. Два вида событий происходят разное количество раз в одном и том же интервале.

Если я коснусь левой рукой два раза и правой рукой три раза за одно и то же время, это будет выглядеть примерно так:

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

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

Есть также «метаритм», который представляет собой паттерн, генерируемый при нажатии любой руки:

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

Это простой и очень распространенный полиритм с соотношением 3: 2.

Скажем так, я не хочу делать простой полиритм, который я могу выработать в своей голове, поэтому мне нужно что-то, чтобы решить это для меня. Я мог бы сделать это на бумаге, или ...


Правила:

  • Напишите некоторый код для генерации и отображения диаграммы ритма, как описано выше.
  • Любой старый язык, попробуйте наименьшее количество байтов.
  • Ваш код принимает два аргумента:
    • Количество нажатий левой рукой (положительное целое число)
    • Количество нажатий правой рукой (положительное целое число)
  • Он определит длину, которая является наименьшим общим кратным для двух аргументов.
  • Верхняя строка будет состоять из двух пробельных символов, за которыми следуют дефисы, отображающие длину (длина * '-')
  • Вторая и третья строки покажут образец для правой и левой руки:
    • Он начнется с R или L, обозначьте, какая это рука, а затем пробел.
    • Интервал для этой руки - это длина, разделенная на аргумент.
    • Нажатие начнется с третьего символа, обозначенного любым выбранным вами символом. С этого момента он будет отображать один и тот же символ с интервалом.
    • Это не будет длиннее, чем длина линии.
  • Четвертая строка - это метаритм:
    • Он начнется с заглавной буквы M, за которой следует пробел.
    • Начиная с третьего символа, он будет отображать символ (любой выбранный вами символ) в каждой позиции, где есть нажатие на правую или левую руку.
  • Конечный пробел не имеет значения.

Тестовые случаи:

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?
Сок

@Sok Это приемлемо как интерпретация «двух аргументов»
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)

Попробуйте онлайн!

Как?

Мы используем одну и ту же вспомогательную функцию для двух разных целей.грамм()

грамм()0Кзнак равноLCM(L,р)

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

s

грамм()1N3Иксs0

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 байт.

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
}

Это не много, но -1 байт, изменив ?".":" "на ?'.':32.
Кевин Круйссен

@KevinCruijssen Каждый байт имеет значение :-) Спасибо!
OOBalance

4

Python 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 #) , 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}";}

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

Полный код

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

Попробуйте онлайн!

Я определенно чувствую, что здесь есть возможности для улучшения, но я попробовал несколько разных подходов, и это единственный, который застрял. Избавление от определения внутренней функции сделало бы меня очень счастливым, и я попытался сделать несколько изменений структуры cat (), чтобы это произошло. Не берите в голову, как только я отправил, я понял, что я мог сделать. По-прежнему определенно можно найти некоторую экономию эффективности.

В библиотеках с более короткими именами есть другие функции LCM, но у TIO есть числа, и я посчитал это более ценным на данный момент.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.