icyrock.com

HomeOld blogOld blog 2

PureScript solution to Project Euler problem 65

2023-03-11 09:28

Problem details at Project Euler problem 65 page.

Test

module Euler065Test (euler65suite) where

import Prelude

import Effect.Aff (Milliseconds(..), delay)
import Euler065 (euler65)
import Test.Unit (TestSuite, suite, test)
import Test.Unit.Assert as Assert

euler65suite :: TestSuite
euler65suite =
  suite "Euler 65" do
    test "Warmup" do
      delay (Milliseconds 0.0)
      Assert.equal 17 (euler65 10)

    test "Real" do
      delay (Milliseconds 0.0)
      Assert.equal 272 (euler65 100)

Solution

module Euler065 where

import Prelude

import Data.Array.NonEmpty (concatMap, foldl1, range, reverse, take)
import Data.Array.NonEmpty.Internal (NonEmptyArray(..))
import Data.BigInt (BigInt, digitsInBase, fromInt)
import Data.Foldable (sum)
import Data.Ratio (Ratio, numerator, (%))

terms :: Int -> NonEmptyArray BigInt
terms n = 
  let f j = NonEmptyArray (map fromInt [1, 1, j * 2])
      r = concatMap f $ range 2 (4 + n / 3)
  in NonEmptyArray $ take n (NonEmptyArray (map fromInt [2, 1, 2]) <> r)

convergent :: Int -> Ratio BigInt
convergent n =
  let rts = (_ % fromInt 1) <$> reverse (terms n)
      r1 = fromInt 1 % fromInt 1
      f a e = e + r1 / a
  in foldl1 f rts

euler65 :: Int -> Int
euler65 = sum <<< _.value <<< digitsInBase 10 <<< numerator <<< convergent