3
\$\begingroup\$

Input variables:

(Names are just examples, they don't need to be named like this)

  • GrandTotal - integer to divide
  • SplitCount - number of output integers required
  • UpperLimit - highest valid value for any one output integer
  • LowerLimit - lowest valid value for any one output integer

Valid Output:

Outout must be a random set of SplitCount integers, each between UpperLimit and LowerLimit (your language's RNG is fine), the sum of which is GrandTotal.

The output should be uniformly random in that any valid output should be equally likely. For example input of [8,3,4,2] has the following six valid outputs:

  1. 2,3,3
  2. 3,2,3
  3. 3,3,2
  4. 2,2,4
  5. 2,4,2
  6. 4,2,2

Each output should have, therefore, 1/6 chance of occurring.

The order of the output matters: 5,8,7 is not an equal set to 5,7,8. Both outputs must be equally likely if either is possible.
(This does mean that output where all three integers are the same is less likely output to one where all three are different: Given GrandTotal=6, SplitCount=3, UpperLimit=4, LowerLimit=1, a set including 1, 2 and 3 can appear in 6 different configurations, while a set of all 2s can only appear in one, making it 6 times as likely that one of the varied sets will appear, rather than the set of 3 2s.)

Valid Input:

Any input variables should work, assuming that the following is true

  1. UpperLimit * SplitCount >= GrandTotal
  2. LowerLimit * SplitCount <= GrandTotal
  3. all input variables are positive integers.

Tie-Breaker

Submissions that accept invalid input but return output as though it was the closest valid input would win a tie-breaker. (eg GrandTotal=10, SplitCount=2, UpperLimit=3, LowerLimit=2 returning [5,5] treats the UpperLimit variable as though it was the lowest valid input, rather than what it was.) Closest here means change as few variables as possible, and change those variables by the smallest possible integer. Ideally, change the latest possible variable(s) (here, SplitCount could have been changed to make input valid, but UpperLimit is a later variable.)

Sample in-out range

GrandTotal SplitCount UpperLimit LowerLimit Possible Output Range
11 2 7 4 4,7;5,6;6,5;7,4
8 3 11 2 2,3,3;3,2,3;3,3,2;2,2,4;2,4,2;4,2,2
13 2 8 4 8,5;7,6;6,7;5,8
16 2 8 4 8,8
16 2 10 4 10,6;9,7;8,8;7,9;6,10
16 4 10 4 4,4,4,4
\$\endgroup\$
2
  • \$\begingroup\$ I don’t understand the worked example… splitCount is 4 but all outputs have 3 items. “Must be a random set of splitcount integers”. Also they sum to 8, not 10. \$\endgroup\$
    – Jonah
    May 1 at 13:50
  • 1
    \$\begingroup\$ @Jonah Weird, I thought I'd updated that to be correct. Oh well, thanks for the catch, fixed now. \$\endgroup\$ May 2 at 2:58

7 Answers 7

3
\$\begingroup\$

Wolfram Language (Mathematica), 49 bytes

RandomChoice@Pick[t=Range@##3~Tuples~#2,Tr/@t,#]&

Try it online!

Input [GrandTotal, SplitCount, LowerLimit, UpperLimit].

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

05AB1E, 8 bytes

ŸIãʒOQ}Ω

Inputs in the order UpperLimit,LowerLimit,SplitCount,GrandTotal.

Try it online or verify all test cases (without the ).

Explanation:

Ÿ       # Take the first two (implicit) inputs and push a list in the range
        # [LowerLimit,UpperLimit]
 Iã     # Create all combinations of a size of the third input SplitCount using
        # the cartesian product
   ʒ    # Filter this list of lists by:
    O   #  Sum the list
     Q  #  Check if it's equal to the fourth (implicit) input GrandTotal
   }Ω   # After the filter: pop and leave a random list
        # (which is output implicitly as result)
\$\endgroup\$
2
\$\begingroup\$

Python 3.8 (pre-release), 116 bytes

-12 bytes thanks to Jitse

Accepts input in the form of GrandTotal,SplitCount,UpperLimit,LowerLimit.
Returns a randomly picked range, as a tuple, from a list of possible ranges.

lambda g,s,u,l:r.choice([p for p in i.product(range(l,u+1),repeat=s)if sum(p)==g])
import random as r,itertools as i

Try it online!

\$\endgroup\$
4
  • 3
    \$\begingroup\$ You're missing a random in there. I misread the challenge at first as well, but the idea is to output one of those possible lists at random. So you can keep your existing approach, and pick a random item from that list to output. \$\endgroup\$ Apr 29 at 9:44
  • 1
    \$\begingroup\$ @KevinCruijssen Thank you for your feedback, I think it works properly now. If not let me know. \$\endgroup\$
    – solid.py
    Apr 29 at 10:38
  • 1
    \$\begingroup\$ You need to output only one of the options at random. This saves you 12 bytes. \$\endgroup\$
    – Jitse
    Apr 29 at 12:10
  • \$\begingroup\$ @Jitse Thank you for you clarification, I misread the part of the challenge about returning just one random choice. \$\endgroup\$
    – solid.py
    Apr 29 at 19:34
1
\$\begingroup\$

Burlesque, 49 bytes

r@s1Js2rzjCBf{++g2==}f{{g1j~[}al}sa-.3 0x/rn1.+si

Try it online!

r@s1          # Range from lowerLimit to upperLimit and save to 1
Js2           # Duplicate grandTotal and save to 2
rz            # Range [0, grandTotal]
jCB           # Combinations of SplitCount
f{++g2==}     # Filter for sum == grantTotal
f{{g1j~[}al}  # Filter for all elements in range
sa-.3 0x/rn   # Generate infinite list of random numbers [0, len)
1.+si         # Take 1 and select it
\$\endgroup\$
0
\$\begingroup\$

Bash, 164 bytes

echo>0
seq 1 $2|xargs -I, sh -c "rm ,;seq $4 $3|xargs -i sh -c \"<\$((,-1)) sed s/^/{}\ />>,\""
<$2 tr \  +|sed s/+$//|bc|pr -mt $2 -|grep $1$|cut -d\	 -f1|shuf -n1

Try it online!

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

JavaScript (ES6), 85 bytes

Expects (count, lower, upper)(total).

(n,a,b)=>g=(t,k=n,s=t,...o)=>k?g(t,k-1,s-=q=a-Math.random()*(~b+a)|0,...o,q):s?g(t):o

Try it online!

(NB: The function is likely to stack overflow on some test cases. The above test includes some extra recovery code.)

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

Charcoal, 34 bytes

NθNηNζ≔⊕⁻NζεI‽ΦEXεη⁺﹪÷ιXε…⁰ηεζ⁼Σιθ

Try it online! Link is to verbose version of code. Takes input in the order GrandTotal, SplitCount, LowerLimit, UpperLimit. Explanation:

NθNηNζ

Input the grand total, split count and lower limit.

≔⊕⁻Nζε

Input the upper limit and calculate the length of the inclusive range from the lower limit to the upper limit.

I‽ΦEXεη⁺﹪÷ιXε…⁰ηεζ⁼Σιθ

Generate the Cartesian product of the split count number of inclusive ranges, filter out those whose sum isn't the desired grand total, and output one uniformly at random.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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