Çoklu ritimlerimle bana yardım et


17

Ben müzisyenim ve hayatımda daha fazla çok terime ihtiyacım var!

Müzikte (ve doğada) iki olay (alkışlar, notalar, yanıp sönen ateş böcekleri vb.) İki farklı düzenli aralıkta meydana geldiğinde bir çoklu ritim oluşur. İki tür olay aynı aralıkta farklı sayıda gerçekleşir.

Sol elimle iki kez ve sağ elimle 3 kez aynı zamanda dokunursam, biraz şöyle görünür:

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

Üst kısımdaki tireler, en düşük ortak kat veya 2 ve 3 olan politmik desenin uzunluğunu gösterir. Bu, desenin tekrarlandığı nokta olarak anlaşılabilir.

Ayrıca, her iki elden dokunulduğunda üretilen model olan bir 'metaritm' vardır:

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

Bu, 3: 2 oranı ile basit ve çok yaygın bir çok ritimdir.

Diyelim ki kafamda çalışabileceğim basit bir çoklu ritim yapmak istemiyorum, bu yüzden benim için çalışacak bir şeye ihtiyacım var. Kağıt üzerinde uzun formda yapabilirim, ya da ...


Kurallar:

  • Yukarıda açıklandığı gibi, bir çoklu ritim diyagramı oluşturmak ve görüntülemek için bir kod yazın.
  • Herhangi bir eski dil, en az bayt için deneyin.
  • Kodunuz iki argüman alır:
    • Sol elle dokunma sayısı (pozitif tamsayı)
    • Sağ elle dokunma sayısı (pozitif tamsayı)
  • İki argüman için en küçük ortak kat olan uzunluğu hesaplayacaktır.
  • Üst satırda iki boşluk karakteri ve ardından uzunluğu gösteren kısa çizgiler (uzunluk * '-') oluşacaktır.
  • İkinci ve üçüncü çizgiler sağ ve sol eller için paterni gösterecektir:
    • Bir R veya L ile başlayacak, hangi el olduğunu ve ardından bir boşluk gösterecektir.
    • Bu elin aralığı, uzunluğunun argümanına bölünmesidir.
    • Musluklar, seçtiğiniz herhangi bir karakterle gösterilen üçüncü karakterden başlar. O andan itibaren aynı karakter 'aralık' karakterlerini birbirinden ayıracaktır.
    • Uzunluk çizgisinden daha uzun olmayacaktır.
  • Dördüncü satır metaritm:
    • Bir büyük harf M ve ardından bir boşluk ile başlayacaktır.
    • Üçüncü karakterden itibaren, sağ veya sol elin dokunduğu her pozisyonda bir karakter (seçtiğiniz herhangi bir karakter) gösterecektir.
  • Sondaki boşluk önemsizdir.

Test senaryoları:

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

Mutlu golf!


Test durumlarınızda çok sayıda boşluk var, bunları atlayabilir / daha fazlasını ekleyebilir miyiz?
Wastl

Eğer kabul etmeye var mı rve liki ayrı değerler olarak? Bunun yerine iki elemanlı bir diziyi kabul edebilir miyiz? Bunların sırası nasıl olur, bunu kesinlikle rtakip eder lmi?
Sok

@Sok Bu 'iki argümanın' bir yorumu olarak kabul edilebilir
AJFaraday

Diyagramı gerçekten yazdırması gerekiyor mu, yoksa sadece iade edebilir mi?
Monica'yı eski durumuna getirme - notmaynard

@iamnotmaynard iade iyi.
AJFaraday

Yanıtlar:


6

JavaScript (ES6), 131 bayt

Çıkışlar 0olarak musluk karakteri.

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)

Çevrimiçi deneyin!

Nasıl?

Aynı yardımcı işlevi iki farklı amaç için kullanıyoruz.g()

Tüm bir bağımsız değişken veya bir bağımsız değişken ile adı eşittir 0 , yinelemeli uzunluğu tire dize oluşturur k = LCM ( l , r ) bir arka satır besleme ile:g()0k=lcm(l,r)

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

Bu dize olarak kaydedilir .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 bayt

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

Tür uzun; çok kötü Java'nınlcm() işlevi yoktur. Burada çevrimiçi deneyin (TIO'nun henüz Java 11'i yok, bu yüzden bunun yerine bir yardımcı yöntem kullanıyorString.repeat() ).

İlk sürümüm, musluk sayısı yerine musluklar arasındaki aralığı aldı. Şimdi düzeltildi. SayesindeKevin Cruijssen'e1 bayt golf için .

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
}

Çok değil, ama -1 bayt değiştirerek ?".":" "için ?'.':32.
Kevin Cruijssen

@KevinCruijssen Her bayt önemlidir :-) Teşekkürler!
OOBalance

4

Piton 2 , 187 185 183 174 166 156 148 147 145 bayt

Dokunma -karakteri olarak kullanır

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

Çevrimiçi deneyin!


Kaydedilen:

  • -2 bayt, Jonathan Frech sayesinde

[i%(w/y)and i%(w/z)>0]olabilir [i%(w/y)!=0<i%(w/z)].
Jonathan Frech



3

Python 2 , 185 228 223 234 249 bayt

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)

Çevrimiçi deneyin!


Bunu TIO'ya kopyaladım ve oluşturulan formatı oradan aldım. Düşündüğünüzden daha az
baytta yapıldığı ortaya çıkıyor

@Tfeld r=4, l=8benim için iyi çalışıyor
sonrad10

Uzunluğun en düşük ortak kat olduğu varsayılmaktadır. R = 4, l = 8 ile bu 8 olmalı, ancak çıktınız çok daha uzun görünüyor (8 * 4?).
OOBalance

1
Bu hala LCM'yi vermez; örneğin 15,25, verir 375, ama olmalı 75.
OOBalance

1
Son kontrolün yerini alabileceğine inanıyorum i%r+i%l+0**i<1. Ayrıca, kodun önceki sürümlerini kaldırabilirsiniz, çünkü düzenleme geçmişinizde korunacaklardır, bunları görmek isteyen herkes
Jo King

2

Jöle , 32 bayt

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

Çevrimiçi deneyin!

Girişi liste olarak alır [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 bayt

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 yanıtımın bağlantı noktası . İle arayın f(number_of_right_hand_taps, number_of_left_hand_taps). Burada çevrimiçi deneyin .



1

Pyth, 53 bayt

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

Golf kesinlikle oda. Zamanım olduğunda bunu yapacak.
Burada deneyin

açıklama

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 # Etkileşimli Derleyici) , 254 bayt


Golf çevrimiçi deneyin!

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

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

Salıverme

  • v1.0 - 254 bytes- İlk çözüm.

notlar

  • Yok

1

Kömür , 52 bayt

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

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı versiyonudur. Açıklama:

≔θζW﹪ζη≧⁺θζ

Tarafından Rbölünebilen ilk katını alarak girişlerin LCM değerini hesaplayın L.

ζ↙

Gerekli -s sırasını otomatik olarak çıkaran LCM'yi yazdırın . Ardından ritmi sağdan sola yazdırmak için hareket edin.

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

LCM'den 0'a kadar olan sayıların üzerinden geçin ve sağ ve sol ellerin vuruşlarını temsil eden bir dizi liste oluşturun.

Fζ⊞ι⌈ι

Atımların üzerinden geçin ve metarit ekleyin.

↓Eζ⭆ι§ .λ

Ters atımları aşağı doğru yazdırın, ancak bu bir dizi olduğu için sola doğru sonuçlanır.

←↓RLM

Başlığı yazdırın.




1

Pyth, 49 bayt

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

Formdaki girdiyi bekler [r,l]. Kullanımları -ekran musluklara. Buradan çevrimiçi olarak deneyin veya tüm test senaryolarını burada bir kerede doğrulayın .

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 bayt

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

Çevrimiçi deneyin!

Kesinlikle burada iyileştirme için yer var gibi hissediyorum, ama birkaç farklı yaklaşım denedim ve bu sıkışmış tek. İç işlev tanımından kurtulmak beni oldukça mutlu ederdi ve bunu gerçekleştirmek için bir sürü kedinin () yeniden yapılandırmasını denedim.Boşver, gönderir iletmez ne yapabileceğimi fark ettim. Yine de kesinlikle bazı verimlilik tasarrufları bulunacaktır.

Daha kısa adlara sahip kütüphanelerde başka LCM işlevleri de vardır, ancak TIO'nun sayıları vardır ve bu noktada daha değerli olduğunu düşündüm.


1

C ++ (gcc) , 197 bayt

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

Çevrimiçi deneyin!


++p%a+p%bBunun yerine öner++p%a||p%b
ceilingcat
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.