Introduction
The Day 21 problem starts with a pretty simple and obvious part of not random dice game, while in second part we have to think deeper how to efficiently simulate multiple paths of quantum game that may appear. Let’s see then how we can deal with both parts by working with model built with immutable objects.
Solution
We simulate the game with its immutable representation as DiceGame
that holds points for both players and
the order of players to move. We added to it some helper methods looser
and winner
which are designed
to answer the question “Was the last moved player a looser/winner?” as we use them only after player moves.
We’re able to transform such a game with some dice value by creating a new instance of game with points
of player updated and players switched. As it is an immutable data, we used fold
once again as in multiple
previous problems to simulate state change of such object.
In the second part, we have to count the worlds, in which players win. As the number of possible values of
dice is limited, we write them to QUANTUM_DICE_SPLITS
for better readability of our intention.
The numbers on right represent on how many ways we have get every sum from left, when the possible
sums are listed in comment.
Then, the simulation of quantum game have to count the occurrences of each game instead of keeping them in
some collection. For example, instead of having a list with 42 the same games, we just remember the game
and its associated value that equals 42. We can update these values accordingly by multiplying the last
count by the number of worlds splits
, in which current dice
value appear by simply writing
|
|
as we’ve used the DefaultMap<DiceGame, Long>
once again for simpler problem representation.
Day21.kt
|
|
Extra notes
The process of generation next values of dice in the first part of problem could have been expressed in really
handy way, with the usage of sequences and windowed
function of them. It’s not the most performant approach
to this problem as we could define closed formula for these numbers, but as it was the first part of the
problem, single line solution with just
|
|
was in my opinion the best fit here.
Notice, that in the solution of second part, we decided to use some local updated
map, which is used to
store the current state of the playing games instead of modifying the playing
map. We need to remember that
in case of Java collections (which are used in Kotlin), we cannot modify the collection when iterating over
its values. The ConcurrentModificationException
is thrown, if we would try to do so. There are of course
different approaches to solve such problems, e.g. we can copy the collection to iterate over copy and modify
the original one or just iterate over original and modify it after iteration. The second approach seemed to
give more clear result in this solution and was fast enough, so we decided to apply it to our solution.