3

I needed to calculate the number of different possible rolls that could arise from rolling K dice, each with N-sides. My definition of roll is that something like {1, 1, 2, 3, 4} is equivalent to {1, 4, 3, 1, 2} (order doesn't matter), but not to {1, 1, 3, 3, 3} (they're not the same set of results). For example: Yahtzee is a game involving rolls of 5 6-sided dice—at least initially, before rerolls—and the number of different rolls is thus 252. The case when N = K leads to OEIS sequence A001700.

If I'm not horribly mistaken, this is given by "(N-1+K) choose (N-1)", or equivalently, "(N+K-1) choose K", which is K ! <: K + N in J. This leads me to four different tacit representations:

  • d =: ([ ! [: <: +). Simple train, without parentheses, though I need to use a cap.
  • d =: ([ (! <:) +). No cap, but parenthesizing the inner hook.
  • d =: (] !&<: +). Only a three verb train, but using a Compose. It uses the (<: N) ! <: K + N version.
  • d =: (([ ! +) * ] % +). This one rewrites "C(N+K-1, K)" as "C(N+K, K) * N / (N+K)". It's uglier, but in the 0 dice of 0 sides case, it gives 0 instead of 1, which is arguably a less nonsensical answer.

Which of these is the most "J-ish" solution?

Also, the monadic case for all of these is meaningless: 1 0 0 0 0 ... for the first three and 0 1 1 1 ... for the fourth. A more logical monad for this verb would be the reflexive, as given by d~, so would it be better to define this verb as (d~ : d)?

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
algorithmshark
  • 267
  • 2
  • 9

1 Answers1

2

My preference would be:

d =: ([ (! <:) +)

and to add a monadic option to the dyadic

d =: d~ : ([ (! <:) +) NB. 4 d 5 ( 4 rolls of 5 sided dice : 70 possible combinations)

I would add the comment including sample arguments and an expected purpose to save me time were I to stumble across it later.

Of course, the final version would be the choice if 0 d 0 were to return 0, even if it does look a little more complicated.

bob
  • 4,282
  • 2
  • 22
  • 30
  • I share your preference. If zero rolls or dice are desired to produce zero as the result, I'd make [ (! <:) + the right tine of this wider fork: *&* * ([ (! <:) +) – kaleidic Oct 04 '13 at 15:36
  • I can't figure out how to make the comment actually display the code. To the left of the original verb should be star-ampersand-star-space-star. (The space is decorative, not semantic, of course.) – kaleidic Oct 04 '13 at 15:47
  • Oh, so you mean `(*&* * [ (! <:) +)`? Now there's an idea. You can't just signum the product, because I think 1 way to roll 0 dice with N sides makes combinatorical sense. But that idea leads us to `(*@] * [ (! <:) +)`, which fits the bill. Nice! – algorithmshark Oct 04 '13 at 16:26
  • The code you came up with here was my first idea, actually, but I didn't understand the distinction you're making between rolling no dice and having no sides, so I generalized. – kaleidic Oct 04 '13 at 17:00
  • Well if `(*@] * [ (! <:) +)` fits the bill then `(* *) @ ([ (! <:) +)` should as well. And if zero sided die could only be thrown one way then `( (* *) (! <:) + )` would work as well. – bob Oct 05 '13 at 00:07