-
Notifications
You must be signed in to change notification settings - Fork 0
/
9.hs
60 lines (50 loc) · 1.93 KB
/
9.hs
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
49
50
51
52
53
54
55
56
57
58
59
60
{-# LANGUAGE FlexibleContexts #-}
import Data.CircularList
import qualified Data.Map as Map
import Data.List
import Data.List.Split
import Control.Monad.State
-- unsafe version of Clist focus
getFocus cl = n
where Just n = focus cl
-- returns a tuple of score and a new board from an existing one using the standard rule
newb newMarble board = (0, newBoard)
where
newBoard = insertL newMarble $ rotR board
-- returns a tuple of the score and a new board from an existing one using the 23 marble rule
newb23 newMarble board = (newMarble + removedMarble, newBoard)
where
tmpBoard = rotN (-7) board
removedMarble = getFocus tmpBoard
newBoard = removeR tmpBoard
-- play a marble, just picks the appropriate rule depending on the marble
playMarble m b
| m `mod` 23 == 0 = newb23 m b
| otherwise = newb m b
-- If we have no marbles, then there is nothing to do so
-- just return the player scores from the game state.
playGame _ [] = do
(scores, _) <- get
return scores
-- play the game. Pop a marble from the list of marbles
-- get the current state of scores and board
-- play the marble and alter the state
-- the ... do it again, but with the remaining marbles
playGame numPlayers (x:xs) = do
(scores, board) <- get
let (score, newBoard) = playMarble x board
let player = x `mod` numPlayers
-- only update the scores if we have to
-- makes a big difference to running time
case score of
0 -> put (scores, newBoard)
_ -> put (Map.insertWith (+) player score scores, newBoard)
playGame numPlayers xs
-- initialise the game scores as a Map
-- and the board as a CList for easy insertion and moving etc
game numPlayers maxMarble = result
where
initScores = Map.fromList []
startState = (initScores, fromList [0])
result = evalState (playGame numPlayers [1 .. maxMarble]) startState
main = print $ maximum $ game 411 7205900