Skip to content

Instantly share code, notes, and snippets.

@3v0k4
Created December 28, 2018 17:21
Show Gist options
  • Select an option

  • Save 3v0k4/57bf37be74bf7ffe9aa41c8e736e2f1a to your computer and use it in GitHub Desktop.

Select an option

Save 3v0k4/57bf37be74bf7ffe9aa41c8e736e2f1a to your computer and use it in GitHub Desktop.
AdventOfCode 2018 PureScript - Day 9
module Main where
import Prelude
import Effect (Effect)
import Effect.Console (logShow)
import RRBList ((!!), length, insertAt, deleteAt, singleton)
import RRBList.Types (List)
import Data.Foldable (maximumBy)
import Data.Maybe (Maybe(..), fromJust)
import Math ((%))
import Data.Int (rem, toNumber, floor)
import Data.Map (Map, empty, insert, lookup, toUnfoldable)
import Partial.Unsafe (unsafePartial)
import Data.Tuple (Tuple, snd)
import Data.Function (on)
import Data.Int53 (Int53, fromInt)
nPlayers :: Int
nPlayers = 477
type Game =
{ index :: Int
, marbles :: List Int
, scores :: Map Int Int53
}
init :: Game
init =
{ index: 0
, marbles: singleton 0
, scores: empty
}
insertMarble :: Int -> Game -> Game
insertMarble marble game
| marble `isMultipleOf` 23 = insertMarbleMult marble game
| otherwise = insertMarbleNonMult marble game
insertMarbleMult :: Int -> Game -> Game
insertMarbleMult marble game@{ marbles, index, scores } =
game { marbles = newMarbles, index = newIndex, scores = newScores }
where newIndex = calculateIndex marbles (index - 7)
newMarbles = unsafePartial fromJust (deleteAt newIndex marbles)
player = marble `rem` nPlayers
points = marble + (unsafePartial fromJust (marbles !! newIndex))
newScores = updateScores player points scores
insertMarbleNonMult :: Int -> Game -> Game
insertMarbleNonMult marble game@{ marbles, index, scores } =
game { marbles = newMarbles, index = newIndex }
where newIndex = calculateIndex marbles (index + 2)
newMarbles = unsafePartial fromJust $ insertAt newIndex marble marbles
calculateIndex :: forall a. List a -> Int -> Int
calculateIndex xs i =
floor $ toNumber (l + (floor (toNumber i % toNumber l))) % toNumber l
where l = length xs
isMultipleOf :: Int -> Int -> Boolean
isMultipleOf x y = toNumber x % toNumber y == 0.0
updateScores :: Int -> Int -> Map Int Int53 -> Map Int Int53
updateScores player points scores =
case lookup player scores of
Just v -> insert player (v + fromInt points) scores
Nothing -> insert player (fromInt points) scores
playTurn :: Int -> Int -> Game -> Maybe (Tuple Int Int53)
playTurn maxMarble n game
| n == maxMarble - 1 = maximumBy (compare `on` snd) (toUnfoldable game.scores :: List (Tuple Int Int53))
| otherwise = playTurn maxMarble (n + 1) (insertMarble n game)
main :: Effect Unit
main = do
logShow $ playTurn 70851 1 init
logShow $ playTurn 7085100 1 init
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment