Say you have a vertical game board of length n (being the number of spaces). And you have a three-sided die that has the options: go forward one, stay and go back one. If you go below or above the number of board game spaces it is an invalid game. The only valid move once you reach the end of the board is "stay". Given an exact number of die rolls t, is it possible to algorithmically work out the number of unique dice rolls that result in a winning game?
So far I've tried producing a list of every possible combination of (-1,0,1) for the given number of die rolls and sorting through the list to see if any add up to the length of the board and also meet all the requirements for being a valid game. But this is impractical for dice rolls above 20.
For example: t=1, n=2; Output=1 t=3, n=2; Output=3
Let
M[i, j]
be anN
byN
matrix withM[i, j] = 1
if|i-j| <= 1
and0
otherwise (and the special case for the "stay" rule ofM[N, N-1] = 0
)This matrix counts paths of length
1
from positioni
to positionj
.To find paths of length
t
, simply raiseM
to thet
'th power. This can be performed efficiently by linear algebra packages.The solution can be read off:
M^t[1, N]
.For example, computing paths of length 20 on a board of size 5 in an interactive Python session:
So there's
M^20[1, 5]
, or 19535230 paths of length 20 from start to finish on a board of size 5.Try a backtracking algorithm. Recursively "dive down" into depth
t
and only continue with dice values that could still result in a valid state. Propably by passing a "remaining budget" around.For example,
n=10, t=20
, when you reached depth 10 of 20 and your budget is still 10 (= steps forward and backwards seemed to cancelled), the next recursion steps until deptht
would discontinue the0
and-1
possibilities, because they could not result in a valid state at the end.A backtracking algorithms for this case is still very heavy (exponential), but better than first blowing up a bubble with all possibilities and then filtering.
You can use a dynamic programming approach. The sketch of a recurrence is:
Of course you have to consider the border cases (like going off the board or not allowing to exit the end of the board, but it's easy to code that).
Here's some Python code:
Bonus: fancy "one-liner" with list compreehension and reduce
Since zeros can be added anywhere, we'll multiply those possibilities by the different arrangements of (-1)'s:
(-1)'s can only appear in spaces 1,2 or 3, not in space 4. I got help with the mathematical recurrence that counts the number of ways to place minus ones without skipping backwards.
JavaScript code:
Output: