Skip to content

Instantly share code, notes, and snippets.

@devstopfix
Last active June 21, 2016 20:28
Show Gist options
  • Save devstopfix/0d6529fe5d4085e92cc06aeb96798e1d to your computer and use it in GitHub Desktop.
Save devstopfix/0d6529fe5d4085e92cc06aeb96798e1d to your computer and use it in GitHub Desktop.
module RomanNumeral exposing (numeral_to_number)
type Digit = I | V | X | L | C | D | M
value : Digit -> number
value d =
case d of
I -> 1
V -> 5
X -> 10
L -> 50
C -> 100
D -> 500
M -> 1000
-- todo parse String
parse : String -> List Digit
parse s = [M, X, M, I, V]
values : List Digit -> List number
values digits = List.map value digits
-- Chunk a list into a list of adjacent pairs
-- Tail is right padded with given value
chunk : comparable -> List comparable -> (List (comparable, comparable))
chunk padding list =
case list of
[] ->
[]
[x] ->
[(x, padding)]
(x::y::xs) ->
(x,y)::(chunk padding (y::xs))
-- chunk_numbers [1,2,3] == [[1,2], [2,3], [3,0]]
chunk_numbers = chunk 0
-- Accumulate (sum) a list of pairs of numbers
accumulate : List (number, number) -> number
accumulate pairs =
List.foldr
(\ (a,b) acc -> if a >= b then acc + a else acc - a )
0 pairs
numeral_to_number : String -> number
numeral_to_number s =
(parse s)
|> values
|> chunk_numbers
|> accumulate
@devstopfix
Copy link
Author

devstopfix commented Jun 14, 2016

TODO:

  1. parse String to list of Digits

We need an error type:

type DigitList = List Digit | Invalid

@devstopfix
Copy link
Author

Solution using pattern matching:

module RomanNumeral exposing (numeral_to_number)

import String exposing (toList)

value : List Char -> number
value lc = 
  case lc of
    ('C' :: 'M' :: xs) ->
      900 + value xs

    ('C' :: 'D' :: xs) ->
      400 + value xs

    ('X' :: 'C' :: xs) ->
      90 + value xs

    ('X' :: 'L' :: xs) ->
      40 + value xs

    ('I' :: 'X' :: xs) ->
      9 + (value xs)

    ('I' :: 'V' :: xs) ->
      4 + value xs

    ('M' :: xs) ->
      1000 + value xs

    ('D' :: xs) ->
      500 + value xs

    ('C' :: xs) ->
      100 + value xs

    ('L' :: xs) ->
      50 + value xs

    ('X' :: xs) ->
      10 + value xs

    ('V' :: xs) ->
      5 + value xs

    ('I' :: xs) ->
      1 + value xs

    _ ->
      0

numeral_to_number : String -> number
numeral_to_number s =
  s
  |> toList
  |> value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment