icyrock.com

HomeOld blogOld blog 2

PureScript solution to Project Euler problem 72

2023-10-03 19:38

Problem details at Project Euler problem 72 page.

Test

module Euler072Test (euler72suite) where

import Prelude

import Data.BigInt (fromInt, fromString)
import Data.Maybe (Maybe(..))
import Effect.Aff (Milliseconds(..), delay)
import Euler072 (euler72)
import Test.Unit (TestSuite, suite, test)
import Test.Unit.Assert as Assert

euler72suite :: TestSuite
euler72suite =
  suite "Euler 72" do
    test "Warmup" do
      delay (Milliseconds 0.0)
      Assert.equal (fromInt 21) (euler72 8)

    test "Real" do
      delay (Milliseconds 0.0)
      Assert.equal (fromString "303963552391") (Just $ euler72 1_000_000)

Solution

module Euler072 where

import Prelude

import Control.Monad.Rec.Class (Step(..), tailRec)
import Data.Array (fromFoldable, range, zip)
import Data.BigInt (BigInt, fromInt)
import Data.Foldable (foldl, sum)
import Data.Map as Map
import Data.Maybe (Maybe(..))

phi :: Int -> Array BigInt
phi dm =
  let r = fromInt <$> range 2 dm
      mi = Map.fromFoldable $ zip r r
      g {m, d, n}
        | n <= fromInt dm = Loop
           {m: Map.update (\v -> Just $ v * (d - fromInt 1) / d) n m, d, n: n + d}
        | otherwise = Done m
      f m d
        | Map.lookup d m == Just d = tailRec g {m, d, n: d}
        | otherwise = m
      mr = foldl f mi r
  in (fromFoldable <<< Map.values) mr

euler72 :: Int -> BigInt
euler72 = sum <<< phi