In anydice, I'd like to create a die, so that a roll would be the sum of 4 random values from the following sequence:
{1, 1, 1, 1, 1, 3, 3, 3, 5, 5, 7}
So that each number in the sequence is used at maximum once. (That is 3+5+5+7 result is possible where as 5+5+7+7 is not because there are not enough 7s for that) Is this possible?
This is a cards mechanics, not dice mechanics. I'm trying to get a roll by getting a player to draw several card out of pool of cards that I put together. While Anydice is mostly for dice mechanics not for cards drawing mechanics Anydice works well for probability analysis in general, and for sharing the visual spread of probabilities with less technically apt people.
Best Answer
I came up with two solutions, which why inherently different, give the same result. This instills confidence in me that they are correct.
Solution 1
This solution is the one I started working on before I read Sandwich's answer. You can try it here. The idea is to use Buckles algorithm for mapping an lexicographical index (from a die roll) to a selection from my sequence. Let's look at the code:
The
factorial
andchoose
functions are self explanatory. The first calculates 1*2*3....*n, and the second one gives the total number of different ways to get k item out of n, in my case 4 out of 11.buckles
andbuckles inner
implement the Buckles algorithm itself. If we pass N=11, P=4 and X=1 to thebuckles
function we will receive {1,2,3,4}. If we pass N=11, P=4 and X=2, we will receive {1,2,3,5} and so on an so forth until we go all the way to N=11, P=4 and X=330 to get {8,9,10,11}. Note that 330 here is[11 choose 4]
.select
is a helper function, that takes a selector, a sequence and returns the resulting sequence. For example for selector {1,6,7,11} and sequence {1, 1, 1, 1, 1, 3, 3, 3, 5, 5, 7} the result will be {1,3,3,7}.draw items
function selects K items from the given sequence at a given lexicographical index. For example with K = 4 at index 1 and sequence {1, 3, 5 , 9, 11} the result will be {1, 3 , 5 , 9}.The second
draw
function allow you specifying a sequence and the number of items to draw from it. That will be the die.Solution 2
This one is completely inspired by sandwich's answer. You try it here. And here is the code:
I was not sure how to remove a value from an existing sequence, so I had to write my own function for that. It's
remove
. The twodraw
functions implement sandwich's idea of rolling a die and then removing the result from the die sequence. There are two of them, because one of them is recursive and the other bootstraps the first one.I can tell you that the first solution took me about 3 hours, and the second one only a few minutes. Well done sandwich!