aboutsummaryrefslogtreecommitdiffstats
path: root/day21/part1.hs
diff options
context:
space:
mode:
Diffstat (limited to 'day21/part1.hs')
-rw-r--r--day21/part1.hs54
1 files changed, 54 insertions, 0 deletions
diff --git a/day21/part1.hs b/day21/part1.hs
new file mode 100644
index 0000000..2c60e49
--- /dev/null
+++ b/day21/part1.hs
@@ -0,0 +1,54 @@
+module Part1 (simulate1, makeState1) where
+
+import Debug.Trace (traceShow)
+import Utils
+
+data State = State
+ { positions :: [Int],
+ scores :: [Int],
+ die :: Int,
+ dieRolledTotal :: Int
+ }
+ deriving (Show)
+
+makeState1 = State
+
+rollDie :: State -> (Int, State)
+rollDie prevState = (die prevState, prevState {die = die prevState `mod` 100 + 1})
+
+setAtIndex :: Int -> b -> [b] -> [b]
+setAtIndex i value lst = zip [0 ..] lst $> map (\(i', value') -> if i == i' then value else value')
+
+position player state = positions state !! player
+
+score player state = scores state !! player
+
+move player prevState =
+ let (dieRoll1, state1) = rollDie prevState
+ (dieRoll2, state2) = rollDie state1
+ (dieRoll3, state3) = rollDie state2
+ state = state3 {dieRolledTotal = dieRolledTotal state3 + 3}
+
+ newPos = (position player state + dieRoll1 + dieRoll2 + dieRoll3 - 1) `mod` 10 + 1
+ newScore = score player state + newPos
+ in state
+ { positions = setAtIndex player newPos (positions state),
+ scores = setAtIndex player newScore (scores state)
+ }
+
+checkWinCondition state
+ | (scores state !! 0) >= 1000 = Left (1, scores state !! 1, dieRolledTotal state)
+ | (scores state !! 1) >= 1000 = Left (0, scores state !! 0, dieRolledTotal state)
+ | otherwise = Right state
+
+takeTurn :: Int -> State -> Either (Int, Int, Int) State
+takeTurn player state = do
+ let movedState = move player state
+ checkWinCondition movedState
+
+simulate1 state player =
+ let turnTaken = takeTurn player state
+ nextPlayer = (player + 1) `mod` 2
+ in case turnTaken of
+ Right newState -> simulate1 newState nextPlayer
+ Left result -> result