16
\$\begingroup\$

Create a program that generates a drum fill. Your program will output a pattern of L (left hand hits), 'R' (right hand hits), and K for kick drum hits.

Rules

  • The pattern must never have more than 2 of the same hits consecutively.
  • The pattern must be loopable, so it mustn't have more than 2 of the same hits when it loops.
  • Your program accepts 1 argument which is the length of the pattern. You can assume this will always be an integer > 1.
  • Program output must be random each time it's ran. It should be properly random each time, so that every combination is possible, so for an input of 2 for example: LR, LK, RL, RK, KL, KR all have a chance of being generated.
  • IO can be used with any convenient method.
  • Standard loopholes are forbidden.
  • This is code-golf, so smallest program wins!

Example valid output:

RLRRKKLL
LRLLKKLR
LKKRLRKLRRKL
LRLR

Example invalid output:

LRLL // 3 characters when looped
LRLRRRLLR // 3 characters in a row
RRLRLLRR // 4 characters when looped
\$\endgroup\$
7
  • 1
    \$\begingroup\$ No it should be properly random each time, so that every combination is possible, so for an input of 2: LL, LR, LK, RR, RL, RK, KK, KL, KR all have a chance of being generated. I'll add something to the rules about that now. \$\endgroup\$
    – TMH
    Commented Jan 6, 2020 at 17:08
  • 1
    \$\begingroup\$ I've made those changes to the question, cheers! \$\endgroup\$
    – TMH
    Commented Jan 6, 2020 at 23:10
  • 1
    \$\begingroup\$ May we output using three other distinct characters instead of L, R, K? (e.g. A, B, C or 2, 3, 9) \$\endgroup\$ Commented Jan 6, 2020 at 23:13
  • 1
    \$\begingroup\$ @tsh more than 2, not 2 or more. \$\endgroup\$
    – Adám
    Commented Jan 7, 2020 at 6:19
  • 1
    \$\begingroup\$ @tsh i'd make that \$hits_{i+1\bmod n}\$ and \$hits_{i+2\bmod n}\$, but yes. \$\endgroup\$
    – Adám
    Commented Jan 7, 2020 at 6:35

15 Answers 15

7
\$\begingroup\$

Jelly, 15 bytes

“LRK”ṗ;`E3Ƥ$ÐṂX

A monadic Link accepting an integer which yields a list of characters.

Try it online!

How?

Pretty similar to Nick Kennedy's Jelly answer...

“LRK”ṗ;`E3Ƥ$ÐṂX - Link: integer, n
“LRK”           - "LRK"
     ṗ          - Cartesian power (all length n strings with alphabet "LRK")
            ÐṂ  - keep those entries which are minimal under:
           $    -   last two links as a monad:
      ;`        -     concatenate with itself
         3Ƥ     -     for each infix of length 3:
        E       -       all equal?
              X - random element
\$\endgroup\$
1
  • \$\begingroup\$ ... but 1 byte shorter! Nice. \$\endgroup\$ Commented Jan 6, 2020 at 23:21
6
\$\begingroup\$

05AB1E, 15 bytes

…LRKãʒDJÅγà3‹}Ω

Try it online!

…LRK                # literal "LRK"
    ã               # strings made of `input` of those letters
     ʒ       }      # filter:
      DJ            #  concatenate the string with itself
        Åγ          #  run-length encode
          à         #  maximum (largest run length)
           3‹       #  less than 3?
              Ω     # get a random element
\$\endgroup\$
6
\$\begingroup\$

R, 67 bytes

n=scan();while(max(rle(c(x<-sample(c("L","R","K"),n,T),x))$l)>2)0;x

Try it online!

A full program taking an integer, n and implicitly printing the drum pattern.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I didn't notice the clever use of pasting the values together to duplicate the vector so for a while thought it was possible to get something like LRLL. Very nicely done. \$\endgroup\$
    – Dason
    Commented Jan 8, 2020 at 19:26
4
\$\begingroup\$

Jelly, 16 bytes

“LRK”ṗ;`ŒɠṀ<ʋƇ3X

Try it online!

A monadic link taking the length \$n\$ and returning a Jelly string of the drum pattern. Like the other answers, assumes that \$n > 1\$

Explanation

“LRK”ṗ           | Cartesian power of "LRK" and n
            ʋƇ   | Keep those where the following is true:
      ;`         | - Concatenate to itself
        Œɠ       | - Lengths of runs
          Ṁ      | - Max
           <  3  | - Less than 3
               X | Pick one at random
\$\endgroup\$
3
\$\begingroup\$

Python 3, 115 \$\cdots\$ 112 104 bytes

from random import*
f=lambda n,s='L':any(b*3in s*3for b in'LRK')and f(n,''.join(choices('LRK',k=n)))or s

Try it online!

Saved a byte thanks to Chas Brown!!!
Saved 8 bytes thanks to Jonathan Allan!!!

\$\endgroup\$
4
  • \$\begingroup\$ 112 bytes by using from random import* (a common trick). \$\endgroup\$
    – Chas Brown
    Commented Jan 6, 2020 at 21:22
  • \$\begingroup\$ Some improvements: 1. import*; 2. recursive lambda function; 3. multiply string (avoiding a space); 4. multiply by 3 (initial s='L' rather than s='LL'). 104 bytes \$\endgroup\$ Commented Jan 6, 2020 at 21:24
  • \$\begingroup\$ @ChasBrown Tried a few different imports but none of them saved any bytes -Thanks so much !! :-) \$\endgroup\$
    – Noodle9
    Commented Jan 6, 2020 at 21:30
  • \$\begingroup\$ @JonathanAllan Totally amazing! Was trying to think of something recursive but didn't get anywhere. Also very clever changing over to s='L' and s*3! Thanks! :-) \$\endgroup\$
    – Noodle9
    Commented Jan 6, 2020 at 21:32
3
\$\begingroup\$

APL (Dyalog Unicode), 30 bytesSBCS

Anonymous tacit prefix function.

{'LRK'[?⍺⍴3]}⍣{~1∊≢¨3∪/⍺,2↑⍺}⍨

Try it online!

{} apply the following function using the single argument also as left argument:

'LRK'[] index into the string "LRK" using the following indices:

  ⍺⍴3 reshape the number three into the length indicated by the left argument

  ? random indices in those ranges

⍣{} keep applying that function until the following is true:

2↑⍺ take the first two characters of the previously generated string

⍺, prepend the previously generated string

3∪/ the unique elements in each window of width three (lit, the union-reduction)

≢¨ the length of each set

1∊ is one a member thereof?

~ negate

\$\endgroup\$
3
\$\begingroup\$

R, 75 bytes

`?`=diff;n=scan();while(!all(??c(x<-sample(9+c(2,3,9),n,T),x)))0;LETTERS[x]

Try it online!

Rejection sampling until an allowable pattern is found. Samples \$x_i\$ from the set \$\{11, 12, 18\}\$ (the positions in the alphabet of K, L, R). Agreeably, these numbers are such that a pattern is allowable iff \$\forall i, (x_{i+1}-x_i)-(x_i-x_{i-1})\neq 0\$. This condition is verified by calling diff twice (diff computes lagged differences, and here we want the lagged differences of the lagged differences).

\$\endgroup\$
3
  • \$\begingroup\$ How about this for 67 bytes? \$\endgroup\$ Commented Jan 7, 2020 at 0:09
  • \$\begingroup\$ @NickKennedy Smart! I always forget about rle. You should post this separately IMO. \$\endgroup\$ Commented Jan 7, 2020 at 6:20
  • \$\begingroup\$ ok thanks! Have done so it \$\endgroup\$ Commented Jan 7, 2020 at 8:03
3
\$\begingroup\$

Ruby, 57 bytes

->x{0while /(.)\1\1/=~(w=(%w(L K R)*x).sample(x)*'')+w;w}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ You can save two sweet bytes by using ?redo:w instead of 0while +;w. See tio.run/… (I had come up with this answer before seeing yours, but it was too close and you got in first.) \$\endgroup\$ Commented Jan 8, 2020 at 21:10
2
\$\begingroup\$

JavaScript (ES6),  77  74 bytes

Assumes that the input is greater than \$1\$.

n=>(g=s=>s[n-1]?/(.)\1\1/.test(s+s)?g``:s:g(s+'LRK'[Math.random()*3|0]))``

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Charcoal, 26 bytes

Nθ≔KηW⊙KLR№×η³×κ³≔⭆θ‽KLRηη

Try it online! Link is to verbose version of code. Hangs for an input of 1 (could be changed to output a random hit at a cost of 1 byte). Explanation:

Nθ

Input the number of hits.

≔Kη

Initialise the output to an illegal value.

W⊙KLR№×η³×κ³

Repeat while the output is illegal, determined by tripling the output and each of the three letters K, L and R, and checking whether one contains any of the others.

≔⭆θ‽KLRη

Assign the desired number of randomly selected letters to the output.

η

Output the final legal result.

\$\endgroup\$
2
\$\begingroup\$

Perl 5 -pa, 86 bytes

$_=R x("@F"+2);1while s|(.)(?=\1\1)|(R,L,K)[rand 3]|e;s/..$//;($_.$_)=~/(.)\1\1/&&redo

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Ruby, 97 bytes

->x,y=->{[*1..x].map{%w[L R K].sample}}{a=y[];a=y[]while(a+a).chunk{|n|n}.any?{|_,e|e[2]};a.join}

Try it online!

This is a lambda function, which takes the length input as x. It creates a function y which generates a list of length x containing random characters from the list ["L", "R", "K"]. It then checks to see if there are any repeating occurrences of more than 2, and if so recreates a random string.

The chunk method on an array groups consecutive elements.

I check for any repetitions on (a+a) (where a is the generated drum loop), to find any looping-round repetitions.

Golfy Tricks

  • Using e[2] instead of e.size > 2 - this works as everything is truthy in Ruby except nil and false, and indexing out of bounds in an array returns nil.
  • Using %w[L R K] instead of ["L","R","K"] or [?L,?R,?K] - This is ruby's whitespace-separated word array.
\$\endgroup\$
1
\$\begingroup\$

Perl 6, 55 bytes

{({S:g{.}=<R L K>.pick}...{!/(.)$0$0/}o*x 2).tail}o\*x*

Try it online!

Anonymous code block that takes an integer and returns a string of RKLs.

Explanation:

                                                  o\*x*  # Generate a string of n *s
{                                                }  # And pass to code block
 (                     ...                 ).tail   # Get the last element of the sequence
  {                   }      # Where each element is
   S:g{.}=       # Substitute each character of the previous string with
          <R K L>.pick   # A random character 
                          {          }      # Until
                                      o*x 2 # The double of the string
                           !                # Does not
                            /(.)$0$0/       # Contain three of the same character in a row
\$\endgroup\$
1
\$\begingroup\$

Red, 141 112 bytes

func[n][until[s: copy""loop n[append s random/only"LRK"]parse
rejoin[s s][any[copy t skip opt t ahead not t]]]s]

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Burlesque, 43 bytes

pe"LRK"jCB{J?+gw)-]>]3.<}f[sa0#Rx/x/jrn-]!!

Try it online!

Made trickier by the fact there is no "select random element from list" as far as I am aware. 15 bytes are just trying to select a random element.

pe      # Push inputs onto stack takes "SEED N"
"LRK"   # Literal LRK
jCB     # Form all combinations of length N
{
 J?+    # Double string
 gw     # Zip with length of consecutive vals
 )-]    # Take length
 >]     # Maximum
 3.<    # Less than 3
}f[     # Filter for
sa0     # Find number of matches
#Rx/x/j # Fiddle stack to get SEED 0 num_matches
rn      # Gen random ints
-]!!    # Select the first
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.