# How can I get the highest or lowest values of an irregular dice pool in AnyDice?

I want to calculate irregular dice pools, such as (2d10, 1d8) in AnyDice, but I'm having difficulties.

What I mean to do is out of a roll of 2d10 and a 1d8, take the highest (or lowest) two values of the three dice and sum them (total 2-20 with highest & total 2-18 with lowest). I.e. d10 => 7, d10 => 4, d8 => 5 results in either 4 & 5 for 9 total (keep lowest) or 7 & 5 for 12 total (keep highest).

I can do this in Troll, by putting sum largest 2 {2d10,1d8}. I would like to translate this to AnyDice, since I prefer it due to the overlapping graph when comparing probabilities, but am having difficulties since the odds don't match when doing output [highest of 2d10 and 1d8].

Take into account that when you pass 2d10 to Anydice, it automatically sums it. Trying to simulate what you wanted the easiest way I found, here's the code:

function: highestsum A:n B:n C:n {
result: {1,2} @ [sort {A, B, C}]
}

function: lowestsum A:n B:n C:n {
result: {2,3} @ [sort {A, B, C}]
}

output [highestsum 1d10 1d10 1d8]
output [lowestsum 1d10 1d10 1d8]


You can test it here.

What both functions do, is sum the three dices and then take out the highest or the lowest. Take into account that it's important to use three dices in this code, splitting the two 2d10 in 1d10 and 1d10.

Edit: Improved thanks to Ilmari Karonen

• Tip: you can replace [lowest of [lowest of A and B] and C] with just 3 @ [sort {A, B, C}]. And, in fact, the whole expression A+B+C - [lowest of [lowest of A and B] and C] can be simplified down to just {1,2} @ [sort {A, B, C}]. – Ilmari Karonen Mar 12 '16 at 20:32

The answer I posted to a similar question can be pretty easily generalized to handle this:

function: sum IDX:s in A:s B:s {
result: IDX@[sort {A, B}]
}
output [sum {1,2} in 2d10 1d8] named "highest 2 of 2d10 and 1d8"
output [sum {2,3} in 2d10 1d8] named "lowest 2 of 2d10 and 1d8"


The trick is that, when you pass a die (like 2d10) to a function expecting a sequence (like A:s) here, AnyDice will automatically evaluate the function for all the possible rolls of the dice (e.g. {1,1}, {1,2}, {1,3} and so on up to {10,10}) and return a new die (i.e. a probability distribution) consisting of the outputs of the function weighted by their likelihood. If you have two or more such parameters, like here, AnyDice will do the same for all possible combinations here.

So the function defined here will receive a single sequence named IDX (which tells it which of the sorted dice to sum and return), and two sequences named A and B corresponding to the two types of dice rolled. (In this example, sequence A will always contain two numbers between 1 and 10, and sequence B will just contain one number between 1 and 8.) It will then concatenate these sequences, sort the resulting sequence in descending order, and then pick the elements given by the index list IDX from the sorted sequence and sum them. (That's what seq @ seq does in AnyDice; see the section titled "Introspection" in the docs for details.)

The only somewhat annoying limitation is that if you want to make the function handle pools with more than two types of dice, you'll need to add more parameters to the function signature. Of course, while you're at it, you could always add a few extra ones "for future expansion", and just pad them with empty sequences when calling the function, like this:

function: sum IDX:s in A:s B:s C:s D:s E:s {
result: IDX@[sort {A, B, C, D, E}]
}
output [sum {1,2} in 2d10 1d8 {} {} {}] named "highest 2 of 2d10 and 1d8"
output [sum {2,3} in 2d10 1d8 {} {} {}] named "lowest 2 of 2d10 and 1d8"


Also, while taking an explicit list of indices to sum makes the function above nice and flexible, it might be a bit inconvenient if you, say, always want to sum the n lowest dice in a pool of variable size. In that case, you can use introspection to find the size of the dice pool inside the function, and base the indexing on that:

function: highest N:n of A:s B:s C:s D:s E:s {
result: {1..N} @ [sort {A, B, C, D, E}]
}
function: lowest N:n of A:s B:s C:s D:s E:s {
S: [sort {A, B, C, D, E}]
result: {#S-N+1 .. #S} @ S
}
output [highest 2 of 2d10 1d8 {} {} {}] named "highest 2 of 2d10 and 1d8"
output [lowest 2 of 2d10 1d8 {} {} {}] named "lowest 2 of 2d10 and 1d8"


(Note: While testing this code, I found what seems like a bug in AnyDice: passing 0dX, for any X, into a function expecting a sequence will turn it into a one-element sequence containing a single zero, rather than an empty sequence. Using {} does produce an actual zero-length sequence, however.)