Snooker scoring
Jelly, 66 bytes
L⁼30µÐfµ7Ḋ;\¤;€Ṣ€µ€;/
ċ1<⁴µÐfµ;Ç
7Ḋœċ⁴Ḷ¤;/L€;$€;@þ2B¤;/ḟ€0ÇS⁼¥Ðf⁸G
Well, it's too slow for TIO now!
...so here is a paste of the 2636 ways to make exactly 100 produced offline.
...and here is a version that will run there with just SIX reds (maximum break = 75)
Prints a grid of numbers each line being a space separated list of ball values (e.g. three red and two green would be on a line reading 1 1 1 3 3
).
For a value-grouped version that prints lines of counts along with the full names of the balls, at 102 bytes:
ŒrÑ€
Ṫ;ị“¡^³ṗ⁼¬wḌ⁼ø÷OẏK¦ẆP»Ḳ¤$K
L⁼30µÐfµ7Ḋ;\¤;€Ṣ€µ€;/
ċ1<⁴µÐfµ;Ç
7Ḋœċ⁴Ḷ¤;/L€;$€;@þ2B¤;/ḟ€0ÇS⁼¥Ðf⁸Ñ€K€Y
How?
L⁼30µÐfµ7Ḋ;\¤;€Ṣ€µ€;/ - Link 1, create post-red-ball games: list of all pre-yellow-ball-games
µÐf - filter keep if:
L⁼30 - length equals 30 (games that get on to the yellow)
µ µ€ - for €ach sequence leading to the yellow:
¤ - nilad followed by link(s) as a nilad:
7Ḋ - 7 dequeued = [2,3,4,5,6,7]
;\ - ;\ cumulative reduce with concatenation = [[2],[2,3],[2,3,4],...]
;€ - concatenate the sequence with €ach of those
Ṣ€ - sort each one
;/ - reduce with concatenation (flatten by one)
ċ1<⁴µÐfµ;Ç - Link 2, filter bogus entries created and append post-yellow-ball games: list of pre-yellow-ball games (along with the bogus ones with 16 reds potted)
µÐf - filter keep if:
ċ1 - count ones
⁴ - literal 16
< - less than?
µ - monadic chain separation
Ç - call the last link (1) as a monad
; - concatenate
7Ḋœċ⁴Ḷ¤;/L€;$€;@þ2B¤;/ḟ€0ÇS⁼¥Ðf⁸G - Main link: score
7Ḋ - 7 dequeued = [2,3,4,5,6,7]
¤ - nilad followed by link(s) as a nilad:
⁴ - literal 16
Ḷ - lowered range = [0,1,2,...,15]
œċ - combinations with replacement (every possible colour-ball selection that goes with the red pots)
;/ - reduce with concatenation (flatten by one)
$€ - last two links as a monad for €ach:
L€ - length of €ach (number of coloured balls potted)
; - concatenate
¤ - nilad followed by link(s) as a nilad:
2B - 2 in binary = [1,0]
þ - outer product with:
;@ - concatenation with reversed @rguments
;/ - reduce with concatenation (flatten by one)
ḟ€0 - filter discard zeros from €ach
Ç - call the last link (2) as a monad
Ðf - filter keep:
¥ ⁸ - last two links as a dyad, with score on the right
S⁼ - sum(ball values) is equal to score?
G - format as a grid
- implicit print
JavaScript (ES7), 188 180 178 bytes
Returns an array of arrays (sorted from red to black).
n=>[...Array(17**6)].map((_,x)=>[2,3,4,5,6,p=7].map(v=>(k=a[++j]=x%17|0,x/=17,t+=k,p+=!!(y=y&&k),s-=k*v),y=s=n,a=[j=t=0])&&(s==15|s>=t)&s<16&s<t+2&t<9+p&&(a[0]=s,a)).filter(a=>a)
Commented
Note: This version doesn't include the last optimization on p
(now initialized to 7) which makes the logic harder to understand.
n => // given a target score n:
[...Array(17**6)].map((_, x) => // for each x in [0 .. 17^6 - 1]:
[2, 3, 4, 5, 6, 7].map(v => // for each v in [2 .. 7] (yellow to black):
( k = a[++j] = x % 17 | 0, // k = a[j] = number of colored balls of value v
x /= 17, // update x to extract the next value
t += k, // update t = total number of colored balls
p += !!( // update p = number of consecutive colors that were
y = y && k // potted at least once, using y = flag that is zeroed
), // as soon as a color is not potted at all
s -= k * v ), // subtract k * v from the current score s
y = s = n, // initialize y and s
a = [j = t = p = 0] // initialize a, j (pointer in a), t and p
) // at this point, s is the alleged number of red balls
&& // this combination is valid if we have:
(s == 15 | s >= t) & // - 15 red balls or more red balls than colored ones
s < 16 & // - no more than 15 red balls
s < t + 2 & // - at most one more red ball than colored ones
t < 16 + p // - no more than 15 + p colored balls
&& // if valid:
(a[0] = s, a) // update the combination with red balls and return it
).filter(a => a) // end of outer map(): filter out invalid entries
Example output
Below is the output for n = 140:
// R Y G Br Bl P Bk
[ [ 15, 1, 1, 1, 1, 8, 9 ],
[ 15, 1, 1, 1, 2, 6, 10 ],
[ 15, 1, 1, 1, 3, 4, 11 ],
[ 15, 1, 1, 2, 1, 5, 11 ],
[ 15, 1, 1, 1, 4, 2, 12 ],
[ 15, 1, 1, 2, 2, 3, 12 ],
[ 15, 1, 2, 1, 1, 4, 12 ],
[ 15, 1, 1, 2, 3, 1, 13 ],
[ 15, 1, 1, 3, 1, 2, 13 ],
[ 15, 1, 2, 1, 2, 2, 13 ],
[ 15, 2, 1, 1, 1, 3, 13 ],
[ 15, 1, 2, 2, 1, 1, 14 ],
[ 15, 2, 1, 1, 2, 1, 14 ],
[ 15, 1, 1, 1, 1, 1, 15 ] ]
Demo
This is too slow for a snippet. You can try it here instead. (You may get one or two unresponsive script alerts, but it should eventually complete.)