Your 10&|&.<: is probably more comprehensible than my 11 |&.<:
But for part B, how did you handle the smearing of scores that resulted from those new positions and counts? Thanks, -- Raul On Mon, Jan 10, 2022 at 7:07 PM 'Mike Day' via Programming <[email protected]> wrote: > > Part 1 was relatively easy, but I was annoyed that I couldn’t see how to > exploit its cyclic nature. Here’s a comment to self from my script: > > “ m10 +/\"1}."1 |: 15 2 $+/|:30 3$die > 4 6 6 4 10 4 6 6 4 10 4 6 6 4 > 3 4 3 10 5 8 9 8 5 10 3 4 3 10 > > NB. Players 1 2 score 60 65 respectively every 10 plays > 10 +/\"1 m10 +/\"1}."1 |: 15 2 $+/|:30 3$die > 60 60 60 60 60 > 65 65 65 65 65 > > NB. ... but cant quite see how to make it work! “ > ( where m10 =: 10&|&.<: NB. does the modulo correction in origin 1.) > > No use at all for part 2, where I wasted an hour or two wondering how to get > the right orders of magnitude of the number of “universes” having forgotten > that each go is three throws, not just one! Anyway, I counted states too, > based on these constants: > > die3,:ctdie3 > 3 4 5 6 7 8 9 > 1 3 6 7 6 3 1 > > Given a set of positions, pos, and counts of these, cts, a new set of > positions and counts is: > pos =. m10 , pos +/ die3 > cts =. ,cts <.@*/ ctdie3 > > Cheers > > Mike > > Sent from my iPad > > > On 10 Jan 2022, at 22:26, Raul Miller <[email protected]> wrote: > > > > https://adventofcode.com/2021/day/21 > > > > For day 21, we played a "dice game" with two chess pawns. > > > > The game was a two player game, with a track with 10 positions, > > labeled 1 through 10, and the data for the puzzle was the player's > > starting positions. > > > > example=:{{)n > > Player 1 starting position: 4 > > Player 2 starting position: 8 > > }} > > > > Rather than write a parser for this, I used the starting positions > > directly -- for this example: 4 8. > > > > The game itself was to roll a die three times, move that many > > positions forward and then add the resulting position to the player's > > score (which starts at 0). The first player to reach 1000 wins. > > > > Anyways, for part A of the puzzle, our "die" was a "deterministic 100 > > sided die". This die first rolls a 1 and then rolls a 2 and then a 3 > > and... so on up to 100 after which the next roll is 1. And our answer > > for part A was the loser's score multiplied by the number of times the > > die was rolled. > > > > My implementation for this was brute force and uninspired: > > > > NB. deterministic die > > det=: 100 NB. value before start > > k=: 0 NB. count of times rolled > > roll=: {{ > > k=: k+1 > > det=: 1+100|det > > }} > > > > NB. roll die 3 times > > d3=: {{ > > +/roll"0 i.3 > > }} > > > > NB. move > > m10=: {{ > > 1+10|y-1 > > }} > > > > a21=:{{ > > p=: y > > s=: 0 0 > > while. 1 do. > > assert. k < 10000 NB. avoid infinite loops > > if. 1000<:>./s=: s+ 1 0 *p=:m10 p+1 0 * d3'' do. done p return.end. > > if. 1000<:>./s=: s+ 0 1 *p=:m10 p+0 1 * d3'' do. done p return.end. > > end. > > }} > > > > NB. calculate puzzle value > > done=: {{ > > k*<./s > > }} > > > > Thinking about this, I could have instead done something like > > > > play=: * (=i.2) $~ # > > > > A21=: {{ > > die=: 1+100|i.6e3 > > rolls=: _3 +/\ die > > positions=: 11 |&.<: y+"1 play+/\play rolls > > scores=:+/\play positions > > limit=: 1 i.~1000 <: >./"1 scores > > (3*1+limit)*<./limit{scores > > }} > > > > Is that more comprehensible though? I am not sure... > > > > For part B, instead of a 100 sided deterministic die, we had a 3 sided > > "dirac die". Every time we "roll" this die, the universe splits into > > three copies, with the die having value 1, 2 or 3 in those three > > universes. And, for part B, the puzzle was: count the number of > > universes won by the player who wins the most times in these > > universes. > > > > Also, to keep this game "simple" a win was a score of 21 instead of a > > score of 1000. > > > > So, for this game, we needed to track the count of universes in each > > "has not yet won" state. That's a score of 0 .. 20 and a board > > position of 1..10. We do not care about the history of a universe > > prior to reaching that state except in the sense that we are counting > > those universes. We can also ignore universes after we have counted > > their wins. > > > > I approached that this way: > > > > NB. we only care about the counts of "universes" > > NB. each player's position and score marks a universe > > NB. multiple copies of "identical" universe occur because > > NB. of differing histories of die rolls reaching that state > > map=:{{ > > dirac=. ,1 2 3 +/1 2 3+/1 2 3 > > c=. #/.~ dirac > > i=. ~.dirac > > 'sc in' =.|:21 10 #:i.210 NB. sc: score, in: index into 1+i.10 > > 'SC CN IN'=. 0 1 |: ((sc,"0/c),"1 0]_1)+"1(1+10|in+/i)*"0 1]1 0 1 > > NB. score before: 0..20, each move adds a number in range 1..10 to score > > |:CN {{x y}310$0}}"1 IN+10*SC > > }}'' > > > > So, basically, each row of this matrix represents a track position and > > a score, and each column represents the next track position and score, > > and the values are the number of transitions between that row and that > > column. It's mostly zeros, but if we summarize the dice (how much they > > add to the track position and the count for that change), the counts > > we see here are the values which go into the non-zero parts of the > > transition map: > > > > (~.,.#/.~),1 2 3 +/1 2 3+/1 2 3 > > 3 1 > > 4 3 > > 5 6 > > 6 7 > > 7 6 > > 8 3 > > 9 1 > > > > With that map from one collection of universes to the next, I could > > write a step function representing a player taking their turn: > > > > NB. y is universe counts > > NB. leading dimension of y represents current player > > NB. scores over 20 end the game and get counted > > NB. x is the player id for this move > > adv=: {{ > > next=. map +/ .*y > > wins=:((x{wins)+x:+/,210}. next) x} wins > > 210{. next > > }} > > > > And, my puzzle solution starts with a single universe (based on the > > starting position and a score of zero), and runs until every universe > > has won, then reports on the largest number of wins for any player: > > > > b21=:{{ > > wins=: 0 0x > > uni=. 1 (<<:y)} 210 210$0 > > while. 0 < >./,uni do. > > uni=. |: 1 adv |: 0 adv uni > > end. > >> ./wins > > }} > > > > With the example data: > > > > b21 4 8 > > 444356092776315 > > > > Possibly the only remaining tricky thing in b21 itself was that I'm > > using position indices (0 .. 9) rather than position labels (1 .. 10) > > to indicate the position of pawns on the circular track. > > > > Anyways, I hope this made sense. > > > > Thanks, > > > > -- > > Raul > > ---------------------------------------------------------------------- > > For information about J forums see http://www.jsoftware.com/forums.htm > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
