icyrock.com

Home

PureScript solution to Project Euler problem 17

2019-Feb-15 23:10
purescriptproject-euler

Problem details at Project Euler problem 17 page.

Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module Euler017Test (euler17suite) where
 
import Prelude
 
import Data.String (length)
import Euler017 (euler17, write)
import Test.Unit (TestSuite, suite, test)
import Test.Unit.Assert as Assert
 
euler17suite :: TestSuite
euler17suite =
  suite "Euler 17" do
    test "Warmup" do
      Assert.equal 19 (euler17 5)
    test "Warmup 2" do
      Assert.equal 23 (length $ write 342)
    test "Warmup 3" do
      Assert.equal 20 (length $ write 115)
    test "Real" do
      Assert.equal 21124 (euler17 1000)

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
module Euler017 (euler17, write) where
 
import Prelude
 
import Data.Array (range)
import Data.Foldable (sum)
import Data.Map (Map, fromFoldable, lookup)
import Data.Maybe (fromMaybe)
import Data.String (length)
import Data.Tuple (Tuple(..))
 
wordMap :: Map Int String
wordMap = fromFoldable
  [ Tuple 1    "one"
  , Tuple 2    "two"
  , Tuple 3    "three"
  , Tuple 4    "four"
  , Tuple 5    "five"
  , Tuple 6    "six"
  , Tuple 7    "seven"
  , Tuple 8    "eight"
  , Tuple 9    "nine"
  , Tuple 10   "ten"
  , Tuple 11   "eleven"
  , Tuple 12   "twelve"
  , Tuple 13   "thirteen"
  , Tuple 14   "fourteen"
  , Tuple 15   "fifteen"
  , Tuple 16   "sixteen"
  , Tuple 17   "seventeen"
  , Tuple 18   "eighteen"
  , Tuple 19   "nineteen"
  , Tuple 20   "twenty"
  , Tuple 30   "thirty"
  , Tuple 40   "forty"
  , Tuple 50   "fifty"
  , Tuple 60   "sixty"
  , Tuple 70   "seventy"
  , Tuple 80   "eighty"
  , Tuple 90   "ninety"
  , Tuple 100  "hundred"
  , Tuple 1000 "thousand"
  ]
 
word :: Int -> String
word n = fromMaybe "" (lookup n wordMap)
 
write :: Int -> String
write n
  | 1 <= n && n <= 19 = word n
  | 20 <= n && n <= 99 = word tens <> word ones
    where ones = n `mod` 10
          tens = n - ones
  | 100 <= n && n <= 999 = word hundreds <> word 100 <> twoDigit
    where rem = n `mod` 100
          twoDigit = if rem == 0 then "" else "and" <> write rem
          hundreds = n / 100
  | otherwise = word 1 <> word 1000
 
euler17 :: Int -> Int
euler17 n = sum $ length <$> write <$> range 1 n