icyrock.com

Home

PureScript solution to Project Euler problem 19

2019-Apr-27 20:13
purescriptproject-euler

Problem details at Project Euler problem 19 page.

Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module Euler019Test (euler19suite) where
 
import Prelude
 
import Euler019 (euler19)
import Test.Unit (TestSuite, suite, test)
import Test.Unit.Assert as Assert
 
euler19suite :: TestSuite
euler19suite =
  suite "Euler 19" do
    test "Warmup" do
      Assert.equal 2 (euler19 1900 1900)
      Assert.equal 3 (euler19 2000 2001)
      Assert.equal 4 (euler19 2015 2016)
      Assert.equal 4 (euler19 2018 2019)
    test "Real" do
      Assert.equal 171 (euler19 1901 2000)

Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module Euler019 where
 
import Prelude
 
import Data.Array (drop, filter, length, range, scanl, take)
import Data.Foldable (foldl)
 
leap :: Int -> Boolean
leap y = (y `mod` 4 == 0) && (y `mod` 100 /= 0 || y `mod` 400 == 0)
 
monthDays :: Int -> Array Int
monthDays y = [31, if leap y then 29 else 28, 31, 30, 31, 30,
  31, 31, 30, 31, 30, 31]
 
daysAll :: Int -> Int -> Int -> Array Int
daysAll day ybeg yend =
  let f a y = a <> (if y == yend then take 11 (monthDays y) else monthDays y)
  in foldl f [day] (range ybeg yend)
 
cumAll :: Int -> Int -> Array Int
cumAll ybeg yend =
  let g a b = (a + b) `mod` 7
      ca = scanl g 0 (daysAll 0 1900 yend)
      mths = 12 * (ybeg - 1900)
  in drop mths ca
 
euler19 :: Int -> Int -> Int
euler19 ybeg yend = length $ filter (_ == 6) (cumAll ybeg yend)