aboutsummaryrefslogtreecommitdiffstats
path: root/day21/part2.hs
blob: 926e1e5ab755a11c6c350c1e560c60a5979a5ebf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
module Part2 (makeState2, simulate2) where

import Debug.Trace (traceShow)
import Utils

-- (position, score)
type Player = (Int, Int)

type State = (Player, Player)

makeState2 :: Player -> Player -> State
makeState2 p1 p2 = (p1, p2)

win player state = snd (pick player state) >= 21

pick :: Int -> State -> Player
pick 0 = fst
pick 1 = snd

move :: Int -> Int -> (Player, Player) -> State
move delta player state =
  let (oldPos, oldScore) = pick player state
      newPos = (oldPos + delta - 1) `mod` 10 + 1
      newScore = oldScore + newPos
      newState = updatePlayer player (newPos, newScore) state
   in newState

updatePlayer :: Int -> Player -> State -> State
updatePlayer 0 value (_, other) = (value, other)
updatePlayer 1 value (other, _) = (other, value)

die = [1, 2, 3]

possible3RollSums = [3 .. 9]

coeffs = [1, 3, 6, 7, 6, 3, 1]

simulate2 :: Int -> ((Int, Int), (Int, Int)) -> Integer
simulate2 player state
  | win 0 state = 1
  | win 1 state = 0
  | otherwise =
    let (pos, score) = pick player state
        nextStates = possible3RollSums $> map (\roll -> move roll player state)
        nextStatesWithC = zip coeffs nextStates
        nextPlayer = (player + 1) `mod` 2
        wins = nextStatesWithC $> map (\(c, nextState) -> c * simulate2 nextPlayer nextState) .> sum
     in wins