# Counting Rhythms

## The Narrative

You are a bad musician. You never bothered to learn how to count rhythms. To remedy this shortcoming, you decide to write a program that will tell you how to count in any given time signature. You are still a bad musician, but you can at least pretend that you can count rhythms.

## The Objective

Given a time signature, output a possible counting pattern for said time signature.

For those who don't know musical terms:
A measure is, essentially, a group of notes, useful for organizing music and making sure the musicians don't lose their place in the music.
A time signature is a set of numbers in a piece of music which tells you how many beats are in a measure, and which note-length is the beat. For example, a 3/4 time signature tells you that each measure has 3 beats, and the quarter note (4) is the beat. An 11/16 T.S. tells you that there are 11 sixteenth note beats (16) in one measure.
A counting pattern is a way to verbally express the division of a measure. For example, a song in 3/4 can simply be counted as "1 2 3". 11/16 can be counted as "1 la li 2 e & a 3 e & a" (this is more intuitive than counting to 11; I will define this later)
It's important to note that the bottom number of almost all T.S.'s are a power of 2. For this challenge, we will ignore irrational T.S.'s. We will also not look at T.S.'s with a beat greater than 16.

How to Generate a Counting Pattern:
Time signatures with a X/1, X/2, or X/4 can simply be counted with numbers (4/2 can be counted as "1 2 3 4").
T.S.'s with a X/8 or X/16 are a bit more tricky. These can be counted by grouping beats together to form larger beats (6/8, despite having 6 'beats', is very often treated as 2 beats with a triplet subdivision). For this challenge, beats should be grouped in groups of 1("1"), 2("1 &"), 3("1 la li"), or 4("1 e & a")
For X/8, groups of 3 should be prioritized over 2, but 1 should be avoided if possible. (For 7/8, even though 3+3+1 prioritizes 3's, 3+2+2 is better because it avoids 1)
For X/16, groups of 3 should be prioritized over 4, but 2 and 1 should be avoided if possible. (For 11/16, even though 3+3+3+2 prioritizes 3's, 3+4+4 is better because it avoids 2)
It is important to note that the ordering of the groups is not important, i.e. 3+2 and 2+3 are both acceptable groupings of 5/8. This would be important normally, but you are a bad musician.
Also note that T.S.'s 'larger' than 1/8 can be grouped entirely with 2's and 3's; T.S.'s 'larger' than 5/16 can be grouped entirely with 3's and 4's.

Whew! What a mouthful!

## The Specs

You will take a time signature as input. this may be formatted within reason (use common sense!).
You will output an acceptable counting pattern. This will be a string of counts (1, la, &, etc.) separated by spaces. Your output should not include leading or trailing whitespace.
Test Cases:
To clarify, the 'numerator' is a positive integer, and the 'denominator' is 1, 2, 4, 8, or 16.
Again, note that some T.S.'s have multiple valid outputs.

"Input", "Output"
"1/1", "1"
"3/2", "1 2 3"
"4/4", "1 2 3 4"
"1/8", "1"
"10/8", "1 la li 2 la li 3 & 4 &"
"2/16", "1 &"
"5/16", "1 la li 2 &"
"29/16", "1 la li 2 la li 3 la li 4 la li 5 la li 6 la li 7 la li 8 e & a 9 e & a"

"Input", "Invalid Output"
"6/4", "1 la li 2 la li"
"7/8", "1 la li 2 la li 3"
"10/8", "1 & 2 & 3 & 4 & 5 &"
"12/16", "1 e & a 2 e & a 3 e & a"


This is , so the shortest answer in bytes wins!

• For 10/8 is 1 & 2 & 3 & 4 & 5 & valid? May 30 at 11:38
• "Your output should not include leading or trailing whitespace." I assume a single trailing newline is allowed, or not either? A lot of programming languages add a trailing newline by default, and disallowing this doesn't add much to the core of the challenge anyway. May 30 at 15:31
• @DeletedComment The 10/8 example is grouped as 3+3+2+2… maybe you misread? 2 groups of 2 look like ”1 & 2 &”, while 1 group of 4 looks like ”1 e & a”. Hope this helps! May 30 at 17:09
• Is a zero-indexed input allowed? So input would be 5/3 for 6/4 time May 31 at 1:34
• @jezza_99 Sure, I’ll allow that May 31 at 1:36

# Jelly, 46 bytes

Œṗi@€o⁸Ṁ;ṢƊɗÞ:5×6Œ?Ɗ}Ḣị““&“la li“e & a”Ė¹Ƈ€K€K


A full program that accepts the beats and the note-length and prints the result

Try it online!

### How?

Œṗi@€o⁸Ṁ;ṢƊɗÞ:5×6Œ?Ɗ}Ḣị“...”Ė¹Ƈ€K€K - Main Link: beats, B; note-length L
Œṗ                                  - all integer partitions of B
}               - using L:
e.g. 1,2,4,8,16
:5                     -     integer divide by 5  -> 0,0,0,1,3
×6                   -     multiply by six      -> 0,0,0,6,18
Œ?                 -     shortest permutation of [1..N] which has that
lexicographic 1-based-index in a list of all
permutaions of [1..N]
-> [],[],[],[3,2,1],[3,4,2,1]
(our ordering)
Þ                       - sort (the partitions) by:
€                               -     for each (run-length, R) in the partition:
i@                                -       first 1-indexed index of R in Ordering or 0
o⁸                             -       logical OR with the Partition (vectorises)
(replaces 0s with the larger, original Rs)
Ṁ                            -         maximum of X
Ṣ                          -         sorted X
;                           -         concatenate
“...”        - ["", "&", "la li", "e & a"]
ị             - index into
Ė       - enumerate (i.e. [A, B, ...] -> [[1,A],[2,B],...])
€    - for each:
¹Ƈ     -   keep truthy (i.e. drop the "" entries)
K€  - join each with spaces
K - join with spaces
- implicit print


# C (gcc), 372354308301299260240237 233 bytes

#define p!printf(" %d%s"+!i++,i,a
#define q(x,y,z)(j=n%3-z/4)|n<z?p[x]),~j:p[y])+p[y])-z;
*a[]={""," &"," la li"," e & a"};f(n,d,i,j){for(i=0;d<5&&n--;)p[0]);n+=d-8?0:q(j,1,4)for(n+=d<16?0:n<2?p[0])-n:q(j=j?j+3:1,3,8)n>0;n-=3)p[2]);}


Try it online!

-24 bytes thanks to ceilingcat

-46 bytes thanks to ceilingcat

-7 bytes thanks to ceilingcat

-2 bytes thanks to ceilingcat

-39 bytes thanks to both Juan Ignacio Díaz and ceilingcat

-20 bytes thanks to both Juan Ignacio Díaz and ceilingcat

-3 bytes thanks to ceilingcat

-4 bytes thanks to ceilingcat

• It breaks for 1/16, 2/16, and 3/16... Everything else seems to be working fine though! May 30 at 12:03
• @Nilster fixed it May 30 at 13:26
• Very nice! Until it’s beaten (or proven faulty) I’m marking this correct! May 30 at 14:01
• @ceilingcat you're crazy. I couldn't even understand what I wrote and you're still golfing it May 30 at 16:12
• Apparently the output shouldn't contain trailing white-space, this seems to fix it for +7 bytes May 31 at 4:05

# 05AB1E, 52 bytes

5‹iLëÅœΣ4LRIg·†3†Rsk{}θε…e&aN>©š®D'&‚®…ÿ…å´à)ćè]˜ðý?


Two separated inputs $$\a\$$ and $$\b\$$, where $$\b\$$ is the beat and $$\a\$$ are the amount of notes in the measure.
If the input was as strict as the output, a trailing '/¡© (+5 bytes) could be added and the I could be replaced with ®.

4LR®g·†3†R could alternatively be 4L14S.I®gè for the same byte-count: verify all test cases.

Explanation:

5‹i            # If the first (implicit) input is smaller than 5 (1, 2, or 4):
L           #  Push a list in the range [1, second (implicit) input]
ë              # Else (it's 8 or 16 instead):
Åœ            #  Get all lists of positive integers that sum to the second
#  (implicit) input
Σ           #  Sort it by:
4LR        #   Push list [4,3,2,1]
I       #   Push the second input again
g      #   Pop and push its length
·     #   Double it
†    #   Filter that value to the front
3†  #   Then filter 3 to the front
R #   And then reverse the list
#   (we now have [1,4,2,3] for input=8
#   and [1,2,4,3] for input=16)
s          #  Swap so the current list
k         #  Get the index of each in this list (or -1 if higher)
{        #  Sort that list from lowest to highest
}θ          #  After the sort: leave the last list
#  (so Σ...}θ acted as a maximum-by builtin)
ε             #  Map that resulting list to:
…e&a         #   Push string "e&a"
N>       #   Push the 1-based map-index
©      #   Store it in variable ® (without popping)
š     #   Convert the string to a list, and append it:
#    ["e","&","a",index]
®            #   Push index ® again
D            #   And again, with a duplicate
'&‚        '#   Pair it with "&"
®            #   And yet again
…ÿ…å´à      #   Push dictionary string "ÿ la li",
#   where the ÿ is replaced with this index
)            #   Wrap all values into a list
ć           #   Extract the head; the current list of the map
è          #   Modular 0-based index those into the list
]              # Close both the map and if-else statement
˜             # Flatten the list of lists
ðý           # Join it with a space delimiter
?          # Explicitly print it without trailing newline


See this 05AB1E tip of mine (section How to use the dictionary?) to understand why …ÿ…å´à is "ÿ la li".

# Charcoal, 70 bytes

ＮθＮη⪫Ｅ⊟Φ…⟦Ｅθ¹Ｅ÷⁺²θ³⁻³‹ι﹪±θ³Ｅ÷θ³⁺³‹ι﹪θ³⟧⊕÷η⁸⁼θΣι⁺⊕κ§⪪“/^e)R⁼0⁷Ｖⅉ8⮌✳”,ι


Try it online! Link is to verbose version of code. Explanation:

ＮθＮη


Input the time signature.

⟦Ｅθ¹Ｅ÷⁺²θ³⁻³‹ι﹪±θ³Ｅ÷θ³⁺³‹ι﹪θ³⟧


Try to create three beat patterns: all single beats, as many groups of three as possible with the rest two, and as many groups of three as possible with the rest four.

…...⊕÷η⁸


Only consider the first or first two patterns depending on the denominator.

Φ...⁼θΣι


Only keep those patters that actually sum to the whole bar. (This prevents e.g. 5/16 from trying to use groups of three and four).

⪫Ｅ⊟...⁺⊕κ§⪪...,ι


Take the last successful pattern and replace each group with its beat number and group suffix obtained by splitting the compressed string  e & a,, &, la li, finally joining the groups with spaces.

# Vyxal, 56 bytes

5<[ɾ|Ṅµ1k½d⁰LǔJ3Jvḟs;tṘ¨2›:£e&afJ¥:\&"¥«cb|«"ṄWḣi;]fṄ₴


Try it Online!

Port of 05AB1E. Quite slow.

# Python 2, 136 135 bytes

-1 byte thanks to Kevin Cruijssen

def f(m,b,r='',i=1):
while m:k=b<5or[m,3-(m<5)+(6<m<9)*b/9][m>2+b/8];m-=k;r+=' '+i+[' e & a',' la li',' &',''][-k];i+=1
print r[1:]


Try it online!

Takes input as f(m,b) where m is the numerator and b is the denominator

### Explanation

while m:


Loop while m > 0

k=b<5or[m,3-(m<5)+(6<m<9)*b/9][m>2+b/8]


Determine the size of the next group. Essentially the logic is as follows:

• b in [1,2,4] => 1
• b == 8 and m == 4 => 2
• b == 16 and m in [7,8] => 4
• (b == 8 and m <= 3) or (b == 16 and m <= 4) => m
• otherwise => 3
m-=k;r+=' '+i+[' e & a',' la li',' &',''][-k];i+=1


Decrease m by the group size. Append the following to r: First a space, then the current group index, then the appropriate suffix based on the group size. Increment the group index

print r[1:]
`

Output the constructed string, removing the leading space