2023-05-04 14:31
Problem details at Project Euler problem 67 page.
module Euler067Test (euler67suite) where
import Prelude
import Data.Maybe (Maybe(..))
import Effect.Aff (Milliseconds(..), delay)
import Effect.Class (liftEffect)
import Euler067 (euler67)
import Test.Unit (TestSuite, suite, test)
import Test.Unit.Assert as Assert
euler67suite :: TestSuite
euler67suite =
suite "Euler 67" do
test "Warmup" do
delay (Milliseconds 0.0)
Assert.equal (pure $ Just 23) =<< (liftEffect $ euler67 "etc/067-triangle-warmup.txt")
test "Real" do
delay (Milliseconds 0.0)
Assert.equal (pure $ Just 7273) =<< (liftEffect $ euler67 "etc/067-triangle-real.txt")
module Euler067 where
import Prelude
import Data.Array (concat, drop, foldl, fromFoldable, zip)
import Data.Either (Either)
import Data.Foldable (maximum)
import Data.Int (fromString)
import Data.Maybe (Maybe, maybe)
import Data.String.CodeUnits (fromCharArray)
import Data.Tuple (fst, snd)
import Effect (Effect)
import Node.Encoding (Encoding(..))
import Node.FS.Sync (readTextFile)
import Parsing (ParseError, Parser, fail, runParser)
import Parsing.Combinators (sepBy1, sepEndBy1)
import Parsing.Combinators.Array (many)
import Parsing.String (char)
import Parsing.String.Basic (digit)
parser :: Parser String (Array (Array Int))
parser =
let pint = maybe (fail "not int") pure =<< (fromString <<< fromCharArray) <$> many digit
pints = fromFoldable <$> sepBy1 pint (char ' ')
in fromFoldable <$> sepEndBy1 pints (char '\n')
parse :: String -> Either ParseError (Array (Array Int))
parse = flip runParser parser
calcOne :: Array Int -> Array Int -> Array Int
calcOne xs ys =
let es = concat [[0], xs, [0]]
ps = zip es (drop 1 es)
maxt t = max (fst t) (snd t)
zs = map maxt ps
ns = zip ys zs
sumt t = fst t + snd t
in map sumt ns
calc :: Array (Array Int) -> Maybe Int
calc = maximum <<< foldl calcOne [0]
euler67 :: String -> Effect (Either ParseError (Maybe Int))
euler67 file = (map calc <$> parse) <$> readTextFile UTF8 file