-- Convert numbers to Roman
-- Sometimes, complicated if and case constructs can be encoded as data,
-- thus leaving the algorithm itself a simple 'map' operation
-- In the following example, the variable 'digitPattern' encodes the
-- 'subtraction rule' and 'five rule' of the roman number system
-- which otherwise would have to be encoded with tedious 'if' and 'case'
-- See jsfiddle.net / rplantiko/ehL5qwpq/ for the original JS version
toRoman n =
let
digitPattern = [ [], [0], [0,0], [0,0,0], [0,1],
[1], [1,0], [1,0,0], [1,0,0,0], [0,2]]
symbols = "IVXLCDMↁↂ"
r
( n
, s
) | n
< 10 = map (\x
->symbols
!!(x
+2*s
)) (digitPattern
!!n
) | n
>= 10 = r
( div n
10, s
+1) ++ r
( mod n
10, s
) in r(n,0)
main
= print(toRoman
3896 )
LS0gQ29udmVydCBudW1iZXJzIHRvIFJvbWFuCgotLSBTb21ldGltZXMsIGNvbXBsaWNhdGVkIGlmIGFuZCBjYXNlIGNvbnN0cnVjdHMgY2FuIGJlIGVuY29kZWQgYXMgZGF0YSwKLS0gdGh1cyBsZWF2aW5nIHRoZSBhbGdvcml0aG0gaXRzZWxmIGEgc2ltcGxlICdtYXAnIG9wZXJhdGlvbgotLSBJbiB0aGUgZm9sbG93aW5nIGV4YW1wbGUsIHRoZSB2YXJpYWJsZSAnZGlnaXRQYXR0ZXJuJyBlbmNvZGVzIHRoZQotLSAnc3VidHJhY3Rpb24gcnVsZScgYW5kICdmaXZlIHJ1bGUnIG9mIHRoZSByb21hbiBudW1iZXIgc3lzdGVtCi0tIHdoaWNoIG90aGVyd2lzZSB3b3VsZCBoYXZlIHRvIGJlIGVuY29kZWQgd2l0aCB0ZWRpb3VzICdpZicgYW5kICdjYXNlJwoKLS0gU2VlIGpzZmlkZGxlLm5ldCAvIHJwbGFudGlrby9laEw1cXdwcS8gZm9yIHRoZSBvcmlnaW5hbCBKUyB2ZXJzaW9uCgp0b1JvbWFuIG4gPSAKICBsZXQgCiAgICBkaWdpdFBhdHRlcm4gPSBbIFtdLCAgICBbMF0sICAgWzAsMF0sICAgWzAsMCwwXSwgWzAsMV0sCiAgICAgICAgICAgICAgICAgICAgIFsxXSwgWzEsMF0sIFsxLDAsMF0sIFsxLDAsMCwwXSwgWzAsMl1dCiAgICBzeW1ib2xzID0gIklWWExDRE3ihoHihoIiCiAgICByKCBuLCBzICkgfCBuIDwgMTAgICA9IG1hcCAoXHgtPnN5bWJvbHMhISh4KzIqcykpIChkaWdpdFBhdHRlcm4hIW4pICAKICAgICAgICAgICAgICB8IG4gPj0gMTAgID0gciggZGl2IG4gMTAsIHMrMSkgKysgciggbW9kIG4gMTAsIHMpCiAgaW4gcihuLDApICAgICAgICAgICAgCgptYWluID0gcHJpbnQodG9Sb21hbiAzODk2ICk=