Drum fill generator

15

1

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

TMH

Posted 2020-01-06T16:59:49.183

Reputation: 1 273

1No 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. – TMH – 2020-01-06T17:08:52.633

1I've made those changes to the question, cheers! – TMH – 2020-01-06T23:10:55.330

1May we output using three other distinct characters instead of L, R, K? (e.g. A, B, C or 2, 3, 9) – Robin Ryder – 2020-01-06T23:13:30.840

"The pattern must never have more than 2 of the same hits consecutively." What is this mean? Should I read for output hits[], forall i: hits[i] != hits[i+1]? But the example output RLRRKKLL doesn't agree on what I mean. – tsh – 2020-01-07T01:12:36.080

1@tsh more than 2, not 2 or more. – Adám – 2020-01-07T06:19:13.963

@Adám So, does it mean $ \forall i: hits_i = hits_{i+1} \implies hits_i \ne hits_{i+2} $? – tsh – 2020-01-07T06:32:42.193

1@tsh i'd make that $hits_{i+1\bmod n}$ and $hits_{i+2\bmod n}$, but yes. – Adám – 2020-01-07T06:35:32.383

Answers

6

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

Grimmy

Posted 2020-01-06T16:59:49.183

Reputation: 12 521

7

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

Jonathan Allan

Posted 2020-01-06T16:59:49.183

Reputation: 67 804

... but 1 byte shorter! Nice. – Nick Kennedy – 2020-01-06T23:21:27.800

6

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.

Nick Kennedy

Posted 2020-01-06T16:59:49.183

Reputation: 11 829

1I 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. – Dason – 2020-01-08T19:26:17.243

4

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

Nick Kennedy

Posted 2020-01-06T16:59:49.183

Reputation: 11 829

3

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

Noodle9

Posted 2020-01-06T16:59:49.183

Reputation: 2 776

112 bytes by using from random import* (a common trick). – Chas Brown – 2020-01-06T21:22:31.287

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

– Jonathan Allan – 2020-01-06T21:24:16.077

@ChasBrown Tried a few different imports but none of them saved any bytes -Thanks so much !! :-) – Noodle9 – 2020-01-06T21:30:06.130

@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! :-) – Noodle9 – 2020-01-06T21:32:10.267

3

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

Adám

Posted 2020-01-06T16:59:49.183

Reputation: 37 779

3

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

Robin Ryder

Posted 2020-01-06T16:59:49.183

Reputation: 6 625

How about this for 67 bytes?

– Nick Kennedy – 2020-01-07T00:09:24.653

@NickKennedy Smart! I always forget about rle. You should post this separately IMO. – Robin Ryder – 2020-01-07T06:20:06.563

ok thanks! Have done so it – Nick Kennedy – 2020-01-07T08:03:08.137

3

Ruby, 57 bytes

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

Try it online!

G B

Posted 2020-01-06T16:59:49.183

Reputation: 11 099

You can save two sweet bytes by using ?redo:w instead of 0while+;w. See https://tio.run/##KypNqvyfZvtf1y6vWqPIVkO1vNpHIUjBu1YrT1OvODG3ICdVI09TS0lJU8vItk5fQ08zxjDGUN@@KDUl36qo9n@BQlq0cex/AA (I had come up with this answer before seeing yours, but it was too close and you got in first.)

– Reinstate Monica -- notmaynard – 2020-01-08T21:10:34.433

2

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!

Arnauld

Posted 2020-01-06T16:59:49.183

Reputation: 111 334

2

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.

Neil

Posted 2020-01-06T16:59:49.183

Reputation: 95 035

2

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!

Xcali

Posted 2020-01-06T16:59:49.183

Reputation: 7 671

2

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.

IMP1

Posted 2020-01-06T16:59:49.183

Reputation: 510

1

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!

Galen Ivanov

Posted 2020-01-06T16:59:49.183

Reputation: 13 815

1

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

Jo King

Posted 2020-01-06T16:59:49.183

Reputation: 38 234

0

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

DeathIncarnate

Posted 2020-01-06T16:59:49.183

Reputation: 916