September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,9 +1,3 @@
|
|||
on run
|
||||
map(romanValue, {"MCMXC", "MDCLXVI", "MMVIII"})
|
||||
|
||||
--> {1990, 1666, 2008}
|
||||
end run
|
||||
|
||||
-- romanValue :: String -> Int
|
||||
on romanValue(s)
|
||||
script roman
|
||||
|
|
@ -18,7 +12,7 @@ on romanValue(s)
|
|||
-- If this glyph:value pair matches the head of the list
|
||||
-- return the value and the tail of the list
|
||||
-- transcribe :: (String, Number) -> Maybe (Number, [String])
|
||||
on lambda(lstPair)
|
||||
on |λ|(lstPair)
|
||||
set lstR to characters of (item 1 of lstPair)
|
||||
if isPrefixOf(lstR, xs) then
|
||||
-- Value of this matching glyph, with any remaining glyphs
|
||||
|
|
@ -26,7 +20,7 @@ on romanValue(s)
|
|||
else
|
||||
{}
|
||||
end if
|
||||
end lambda
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
if length of xs > 0 then
|
||||
|
|
@ -41,8 +35,40 @@ on romanValue(s)
|
|||
toArabic(characters of s) of roman
|
||||
end romanValue
|
||||
|
||||
-- TEST -----------------------------------------------------------------------
|
||||
on run
|
||||
map(romanValue, {"MCMXC", "MDCLXVI", "MMVIII"})
|
||||
|
||||
-- GENERIC LIBRARY FUNCTIONS
|
||||
--> {1990, 1666, 2008}
|
||||
end run
|
||||
|
||||
|
||||
-- GENERIC FUNCTIONS ----------------------------------------------------------
|
||||
|
||||
-- concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
on concatMap(f, xs)
|
||||
set lst to {}
|
||||
set lng to length of xs
|
||||
tell mReturn(f)
|
||||
repeat with i from 1 to lng
|
||||
set lst to (lst & |λ|(item i of xs, i, xs))
|
||||
end repeat
|
||||
end tell
|
||||
return lst
|
||||
end concatMap
|
||||
|
||||
-- drop :: Int -> a -> a
|
||||
on drop(n, a)
|
||||
if n < length of a then
|
||||
if class of a is text then
|
||||
text (n + 1) thru -1 of a
|
||||
else
|
||||
items (n + 1) thru -1 of a
|
||||
end if
|
||||
else
|
||||
{}
|
||||
end if
|
||||
end drop
|
||||
|
||||
-- isPrefixOf :: [a] -> [a] -> Bool
|
||||
on isPrefixOf(xs, ys)
|
||||
|
|
@ -59,54 +85,30 @@ on isPrefixOf(xs, ys)
|
|||
end if
|
||||
end isPrefixOf
|
||||
|
||||
-- drop :: Int -> a -> a
|
||||
on drop(n, a)
|
||||
if n < length of a then
|
||||
if class of a is text then
|
||||
text (n + 1) thru -1 of a
|
||||
else
|
||||
items (n + 1) thru -1 of a
|
||||
end if
|
||||
else
|
||||
{}
|
||||
end if
|
||||
end drop
|
||||
|
||||
-- concatMap :: (a -> [b]) -> [a] -> [b]
|
||||
on concatMap(f, xs)
|
||||
script append
|
||||
on lambda(a, b)
|
||||
a & b
|
||||
end lambda
|
||||
end script
|
||||
|
||||
foldl(append, {}, map(f, xs))
|
||||
end concatMap
|
||||
|
||||
-- foldl :: (a -> b -> a) -> a -> [b] -> a
|
||||
on foldl(f, startValue, xs)
|
||||
tell mReturn(f)
|
||||
set v to startValue
|
||||
set lng to length of xs
|
||||
repeat with i from 1 to lng
|
||||
set v to lambda(v, item i of xs, i, xs)
|
||||
end repeat
|
||||
return v
|
||||
end tell
|
||||
end foldl
|
||||
|
||||
-- map :: (a -> b) -> [a] -> [b]
|
||||
on map(f, xs)
|
||||
tell mReturn(f)
|
||||
set lng to length of xs
|
||||
set lst to {}
|
||||
repeat with i from 1 to lng
|
||||
set end of lst to lambda(item i of xs, i, xs)
|
||||
set end of lst to |λ|(item i of xs, i, xs)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end map
|
||||
|
||||
-- Lift 2nd class handler function into 1st class script wrapper
|
||||
-- mReturn :: Handler -> Script
|
||||
on mReturn(f)
|
||||
if class of f is script then
|
||||
f
|
||||
else
|
||||
script
|
||||
property |λ| : f
|
||||
end script
|
||||
end if
|
||||
end mReturn
|
||||
|
||||
-- uncons :: [a] -> Maybe (a, [a])
|
||||
on uncons(xs)
|
||||
if length of xs > 0 then
|
||||
|
|
@ -115,15 +117,3 @@ on uncons(xs)
|
|||
missing value
|
||||
end if
|
||||
end uncons
|
||||
|
||||
-- Lift 2nd class handler function into 1st class script wrapper
|
||||
-- mReturn :: Handler -> Script
|
||||
on mReturn(f)
|
||||
if class of f is script then
|
||||
f
|
||||
else
|
||||
script
|
||||
property lambda : f
|
||||
end script
|
||||
end if
|
||||
end mReturn
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
use framework "Foundation"
|
||||
|
||||
-- INTEGER VALUE OF ROMAN NUMBER STRING ---------------------------------------
|
||||
|
||||
-- fromRoman :: String -> Int
|
||||
on fromRoman(s)
|
||||
script subtractIfLower
|
||||
on |λ|(rn, L)
|
||||
set {r, n} to rn
|
||||
if L ≥ r then -- Digit values that increase (right to left),
|
||||
{L, n + L} -- are added
|
||||
else
|
||||
{L, n - L} -- Digit values that go down, are subtracted.
|
||||
end if
|
||||
end |λ|
|
||||
end script
|
||||
|
||||
snd(foldr(subtractIfLower, {0, 0}, map(my charVal, characters of s)))
|
||||
end fromRoman
|
||||
|
||||
-- charVal :: Char -> Int
|
||||
on charVal(C)
|
||||
set V to keyValue({I:1, V:5, X:10, L:50, C:100, D:500, M:1000}, ¬
|
||||
toUpper(C))
|
||||
if nothing of V then
|
||||
0
|
||||
else
|
||||
just of V
|
||||
end if
|
||||
end charVal
|
||||
|
||||
-- TEST -----------------------------------------------------------------------
|
||||
on run
|
||||
map(fromRoman, {"MDCLXVI", "MCMXC", "MMVIII", "MMXVI", "MMXVII"})
|
||||
|
||||
--> {1666, 1990, 2008, 2016, 2017}
|
||||
end run
|
||||
|
||||
|
||||
-- GENERIC FUNCTIONS ----------------------------------------------------------
|
||||
|
||||
-- foldr :: (a -> b -> a) -> a -> [b] -> a
|
||||
on foldr(f, startValue, xs)
|
||||
tell mReturn(f)
|
||||
set V to startValue
|
||||
set lng to length of xs
|
||||
repeat with I from lng to 1 by -1
|
||||
set V to |λ|(V, item I of xs, I, xs)
|
||||
end repeat
|
||||
return V
|
||||
end tell
|
||||
end foldr
|
||||
|
||||
-- keyValue :: Record -> String -> Maybe String
|
||||
on keyValue(rec, strKey)
|
||||
set ca to current application
|
||||
set V to (ca's NSDictionary's dictionaryWithDictionary:rec)'s objectForKey:strKey
|
||||
if V is not missing value then
|
||||
{nothing:false, just:item 1 of ((ca's NSArray's arrayWithObject:V) as list)}
|
||||
else
|
||||
{nothing:true}
|
||||
end if
|
||||
end keyValue
|
||||
|
||||
-- map :: (a -> b) -> [a] -> [b]
|
||||
on map(f, xs)
|
||||
tell mReturn(f)
|
||||
set lng to length of xs
|
||||
set lst to {}
|
||||
repeat with I from 1 to lng
|
||||
set end of lst to |λ|(item I of xs, I, xs)
|
||||
end repeat
|
||||
return lst
|
||||
end tell
|
||||
end map
|
||||
|
||||
-- Lift 2nd class handler function into 1st class script wrapper
|
||||
-- mReturn :: Handler -> Script
|
||||
on mReturn(f)
|
||||
if class of f is script then
|
||||
f
|
||||
else
|
||||
script
|
||||
property |λ| : f
|
||||
end script
|
||||
end if
|
||||
end mReturn
|
||||
|
||||
-- snd :: (a, b) -> b
|
||||
on snd(xs)
|
||||
if class of xs is list and length of xs = 2 then
|
||||
item 2 of xs
|
||||
else
|
||||
missing value
|
||||
end if
|
||||
end snd
|
||||
|
||||
-- toUpper :: String -> String
|
||||
on toUpper(str)
|
||||
set ca to current application
|
||||
((ca's NSString's stringWithString:(str))'s ¬
|
||||
uppercaseStringWithLocale:(ca's NSLocale's currentLocale())) as text
|
||||
end toUpper
|
||||
|
|
@ -0,0 +1 @@
|
|||
{1666, 1990, 2008, 2016, 2017}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
'This code will create a GUI Form and Objects and carry out the Roman Numeral convertion as you type
|
||||
'The input is case insensitive
|
||||
'A basic check for invalid charaters is made
|
||||
|
||||
hTextBox As TextBox 'To allow the creation of a TextBox
|
||||
hValueBox As ValueBox 'To allow the creation of a ValueBox
|
||||
|
||||
Public Sub Form_Open() 'Form opens..
|
||||
|
||||
SetUpForm 'Go to the SetUpForm Routine
|
||||
hTextBox.text = "MCMXC" 'Put a Roman numeral in the TextBox
|
||||
|
||||
End
|
||||
|
||||
Public Sub TextBoxInput_Change() 'Each time the TextBox text changes..
|
||||
Dim cRomanN As Collection = ["M": 1000, "D": 500, "C": 100, "L": 50, "X": 10, "V": 5, "I": 1] 'Collection of nemerals e.g 'M' = 1000
|
||||
Dim cMinus As Collection = ["IV": -2, "IX": -2, "XL": -20, "XC": - 20, "CD": -200, "CM": -200] 'Collection of the 'one less than' numbers e.g. 'IV' = 4
|
||||
Dim sClean, sTemp As String 'Various string variables
|
||||
Dim siCount As Short 'Counter
|
||||
Dim iTotal As Integer 'Stores the total of the calculation
|
||||
|
||||
hTextBox.Text = UCase(hTextBox.Text) 'Make any text in the TextBox upper case
|
||||
|
||||
For siCount = 1 To Len(hTextBox.Text) 'Loop through each character in the TextBox
|
||||
If InStr("MDCLXVI", Mid(hTextBox.Text, siCount, 1)) Then 'If a Roman numeral exists then..
|
||||
sClean &= Mid(hTextBox.Text, siCount, 1) 'Put it in 'sClean' (Stops input of non Roman numerals)
|
||||
End If
|
||||
Next
|
||||
|
||||
hTextBox.Text = sClean 'Put the now clean text in the TextBox
|
||||
|
||||
For siCount = 1 To Len(hTextBox.Text) 'Loop through each character in the TextBox
|
||||
iTotal += cRomanN[Mid(hTextBox.Text, siCount, 1)] 'Total up all the characters, note 'IX' will = 11 not 9
|
||||
Next
|
||||
|
||||
For Each sTemp In cMinus 'Loop through each item in the cMinus Collection
|
||||
If InStr(sClean, cMinus.Key) > 0 Then iTotal += Val(sTemp) 'If a 'Minus' value is in the string e.g. 'IX' which has been calculated at 11 subtract 2 = 9
|
||||
Next
|
||||
|
||||
hValueBox.text = iTotal 'Display the total
|
||||
|
||||
End
|
||||
|
||||
Public Sub SetUpForm() 'Create the Objects for the Form
|
||||
Dim hLabel1, hLabel2 As Label 'For 2 Labels
|
||||
|
||||
Me.height = 150 'Form Height
|
||||
Me.Width = 300 'Form Width
|
||||
Me.Padding = 20 'Form padding (border)
|
||||
Me.Text = "Roman Numeral converter" 'Text in Form header
|
||||
Me.Arrangement = Arrange.Vertical 'Form arrangement
|
||||
|
||||
hLabel1 = New Label(Me) 'Create a Label
|
||||
hLabel1.Height = 21 'Label Height
|
||||
hLabel1.expand = True 'Expand the Label
|
||||
hLabel1.Text = "Enter a Roman numeral" 'Put text in the Label
|
||||
|
||||
hTextBox = New TextBox(Me) As "TextBoxInput" 'Set up a TextBox with an Event Label
|
||||
hTextBox.Height = 21 'TextBox height
|
||||
hTextBox.expand = True 'Expand the TextBox
|
||||
|
||||
hLabel2 = New Label(Me) 'Create a Label
|
||||
hLabel2.Height = 21 'Label Height
|
||||
hLabel2.expand = True 'Expand the Label
|
||||
hLabel2.Text = "The decimal equivelent is: -" 'Put text in the Label
|
||||
|
||||
hValueBox = New ValueBox(Me) 'Create a ValueBox
|
||||
hValueBox.Height = 21 'ValuBox Height
|
||||
hValueBox.expand = True 'Expand the ValueBox
|
||||
hValueBox.ReadOnly = True 'Set ValueBox to Read Only
|
||||
|
||||
End
|
||||
|
|
@ -1,16 +1,29 @@
|
|||
import Data.List (mapAccumL, isPrefixOf)
|
||||
import Control.Arrow ((***))
|
||||
|
||||
romanValue :: String -> Int
|
||||
romanValue s = sum . snd $ mapAccumL tr s
|
||||
[("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
|
||||
("C", 100), ("XC", 90) ,("L", 50), ("XL", 40),
|
||||
("X", 10), ("IX", 9), ("V", 5), ("IV", 4),
|
||||
("I", 1)]
|
||||
where
|
||||
tr s (k, v) =
|
||||
until (\(s, _) -> not $ isPrefixOf k s)
|
||||
(\(s, n) -> (drop (length k) s, n + v)) (s, 0)
|
||||
romanValue =
|
||||
let tr s (k, v) =
|
||||
until (not . isPrefixOf k . fst) (drop (length k) *** (v +)) (s, 0)
|
||||
in sum .
|
||||
snd .
|
||||
flip
|
||||
(mapAccumL tr)
|
||||
[ ("M", 1000)
|
||||
, ("CM", 900)
|
||||
, ("D", 500)
|
||||
, ("CD", 400)
|
||||
, ("C", 100)
|
||||
, ("XC", 90)
|
||||
, ("L", 50)
|
||||
, ("XL", 40)
|
||||
, ("X", 10)
|
||||
, ("IX", 9)
|
||||
, ("V", 5)
|
||||
, ("IV", 4)
|
||||
, ("I", 1)
|
||||
]
|
||||
|
||||
main :: IO ()
|
||||
main = mapM_ (putStrLn . show . romanValue)
|
||||
["MDCLXVI", "MCMXC", "MMVIII", "MMXVI", "MMXVII"]
|
||||
main =
|
||||
mapM_ (print . romanValue) ["MDCLXVI", "MCMXC", "MMVIII", "MMXVI", "MMXVII"]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
fromRoman :: String -> Int
|
||||
fromRoman =
|
||||
sum .
|
||||
liftM2 (:) fst snd .
|
||||
mapAccumR
|
||||
(\l r ->
|
||||
( if l <= r
|
||||
then r
|
||||
else (-r)
|
||||
, l))
|
||||
0 .
|
||||
fmap charVal
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import qualified Data.Map.Strict as M
|
||||
|
||||
fromRoman :: String -> Int
|
||||
fromRoman xs = partialSum + lastDigit
|
||||
where
|
||||
(partialSum, lastDigit) = foldl accumulate (0, 0) (evalRomanDigit <$> xs)
|
||||
accumulate (partial, lastDigit) newDigit
|
||||
| newDigit <= lastDigit = (partial + lastDigit, newDigit)
|
||||
| otherwise = (partial - lastDigit, newDigit)
|
||||
|
||||
mapRoman :: M.Map Char Int
|
||||
mapRoman =
|
||||
M.fromList
|
||||
[ ('I', 1)
|
||||
, ('V', 5)
|
||||
, ('X', 10)
|
||||
, ('L', 50)
|
||||
, ('C', 100)
|
||||
, ('D', 500)
|
||||
, ('M', 1000)
|
||||
]
|
||||
|
||||
evalRomanDigit :: Char -> Int
|
||||
evalRomanDigit c =
|
||||
let mInt = M.lookup c mapRoman
|
||||
in case mInt of
|
||||
Just x -> x
|
||||
_ -> error $ c : " is not a roman digit"
|
||||
|
||||
main :: IO ()
|
||||
main = print $ fromRoman <$> ["MDCLXVI", "MCMXC", "MMVIII", "MMXVI", "MMXVII"]
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
fromRoman :: String -> Int
|
||||
fromRoman =
|
||||
snd .
|
||||
foldr
|
||||
(\l (r, n) ->
|
||||
( l
|
||||
, (if l >= r
|
||||
then (+)
|
||||
else (-))
|
||||
n
|
||||
l))
|
||||
(0, 0) .
|
||||
fmap evalRomanDigit
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import qualified Data.Map.Strict as M (Map, fromList, lookup)
|
||||
import Data.Maybe (isNothing, isJust, fromJust, catMaybes)
|
||||
import Data.List (mapAccumL)
|
||||
|
||||
mapRoman :: M.Map String Int
|
||||
mapRoman =
|
||||
M.fromList
|
||||
[ ("M", 1000)
|
||||
, ("CM", 900)
|
||||
, ("D", 500)
|
||||
, ("CD", 400)
|
||||
, ("C", 100)
|
||||
, ("XC", 90)
|
||||
, ("L", 50)
|
||||
, ("XL", 40)
|
||||
, ("X", 10)
|
||||
, ("IX", 9)
|
||||
, ("V", 5)
|
||||
, ("IV", 4)
|
||||
, ("I", 1)
|
||||
]
|
||||
|
||||
fromRoman :: String -> Int
|
||||
fromRoman s =
|
||||
let value k = M.lookup k mapRoman
|
||||
in sum . catMaybes . snd $
|
||||
mapAccumL
|
||||
(\mi (l, r, i) ->
|
||||
let mValue = value [l, r] -- mapRoman lookup of [left, right] Chars
|
||||
(lastPair, pairValue)
|
||||
| isJust mValue = (Just i, mValue) -- Pair match: index updated
|
||||
| isNothing mi || i - fromJust mi > 1 = (mi, value [l])
|
||||
| otherwise = (mi, Nothing) -- Left Char was counted in pair
|
||||
in (lastPair, pairValue))
|
||||
Nothing -- Accumulator – maybe Index to last matched Char pair
|
||||
(zip3 s (tail s ++ " ") [0 ..]) -- Indexed character pairs
|
||||
|
||||
main :: IO ()
|
||||
main = print $ fromRoman <$> ["MDCLXVI", "MCMXC", "MMVIII", "MMXVI", "MMXVII"]
|
||||
|
|
@ -1,19 +1,18 @@
|
|||
var Roman = {
|
||||
Values: [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400],
|
||||
['C', 100], ['XC', 90], ['L', 50], ['XL', 40],
|
||||
['X', 10], ['IX', 9], ['V', 5], ['IV', 4],
|
||||
['I', 1]],
|
||||
|
||||
Values: [['CM', 900], ['CD', 400], ['XC', 90], ['XL', 40], ['IV', 4],
|
||||
['IX', 9], ['V', 5], ['X', 10], ['L', 50],
|
||||
['C', 100], ['M', 1000], ['I', 1], ['D', 500]],
|
||||
UnmappedStr : 'Q',
|
||||
parse: function(str) {
|
||||
var result = 0
|
||||
for (var i=0; i<Roman.Values.length; ++i) {
|
||||
var pair = Roman.Values[i]
|
||||
var key = pair[0]
|
||||
var value = pair[1]
|
||||
var regex = RegExp('^' + key)
|
||||
var regex = RegExp(key)
|
||||
while (str.match(regex)) {
|
||||
result += value
|
||||
str = str.replace(regex, '')
|
||||
str = str.replace(regex, Roman.UnmappedStr)
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
(() => {
|
||||
// romanValue :: String -> Int
|
||||
const romanValue = s =>
|
||||
s.length ? (() => {
|
||||
const parse = [].concat(
|
||||
...glyphs.map(g => 0 === s.indexOf(g) ? (
|
||||
[dctTrans[g], s.substr(g.length)]
|
||||
) : [])
|
||||
);
|
||||
return parse[0] + romanValue(parse[1]);
|
||||
})() : 0;
|
||||
|
||||
// dctTrans :: {romanKey: Integer}
|
||||
const dctTrans = {
|
||||
M: 1E3,
|
||||
CM: 900,
|
||||
D: 500,
|
||||
CD: 400,
|
||||
C: 100,
|
||||
XC: 90,
|
||||
L: 50,
|
||||
XL: 40,
|
||||
X: 10,
|
||||
IX: 9,
|
||||
V: 5,
|
||||
IV: 4,
|
||||
I: 1
|
||||
};
|
||||
|
||||
// glyphs :: [romanKey]
|
||||
const glyphs = Object.keys(dctTrans);
|
||||
|
||||
// TEST -------------------------------------------------------------------
|
||||
return ["MCMXC", "MDCLXVI", "MMVIII", "MMMM"].map(romanValue);
|
||||
})();
|
||||
|
|
@ -0,0 +1 @@
|
|||
[1990,1666,2008,4000]
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
(() => {
|
||||
|
||||
// Folding from right to left,
|
||||
// lower leftward characters are subtracted,
|
||||
// others are added.
|
||||
|
||||
// fromRoman :: String -> Int
|
||||
const fromRoman = s =>
|
||||
snd(foldr(
|
||||
([r, n], l) => [l, l >= r ? n + l : n - l], [0, 0],
|
||||
map(charVal, stringChars(s))
|
||||
));
|
||||
|
||||
// charVal :: Char -> Maybe Int
|
||||
const charVal = k => {
|
||||
const v = {
|
||||
I: 1,
|
||||
V: 5,
|
||||
X: 10,
|
||||
L: 50,
|
||||
C: 100,
|
||||
D: 500,
|
||||
M: 1000
|
||||
}[k];
|
||||
return v !== undefined ? v : 0;
|
||||
};
|
||||
|
||||
// GENERIC FUNCTIONS ------------------------------------------------------
|
||||
|
||||
// foldr (a -> b -> b) -> b -> [a] -> b
|
||||
const foldr = (f, a, xs) => xs.reduceRight(f, a);
|
||||
|
||||
// map :: (a -> b) -> [a] -> [b]
|
||||
const map = (f, xs) => xs.map(f);
|
||||
|
||||
// snd :: (a, b) -> b
|
||||
const snd = tpl => Array.isArray(tpl) ? tpl[1] : undefined;
|
||||
|
||||
// stringChars :: String -> [Char]
|
||||
const stringChars = s => s.split('');
|
||||
|
||||
// show :: a -> String
|
||||
const show = (...x) =>
|
||||
JSON.stringify.apply(
|
||||
null, x.length > 1 ? [x[1], null, x[0]] : x
|
||||
);
|
||||
|
||||
// TEST -------------------------------------------------------------------
|
||||
return show(
|
||||
map(fromRoman, ["MDCLXVI", "MCMXC", "MMVIII", "MMXVI", "MMXVII"])
|
||||
);
|
||||
})();
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// version 1.0.6
|
||||
|
||||
fun romanDecode(roman: String): Int {
|
||||
if (roman.isEmpty()) return 0
|
||||
var n = 0
|
||||
var last = 'O'
|
||||
for (c in roman) {
|
||||
when (c) {
|
||||
'I' -> n += 1
|
||||
'V' -> if (last == 'I') n += 3 else n += 5
|
||||
'X' -> if (last == 'I') n += 8 else n += 10
|
||||
'L' -> if (last == 'X') n += 30 else n += 50
|
||||
'C' -> if (last == 'X') n += 80 else n += 100
|
||||
'D' -> if (last == 'C') n += 300 else n += 500
|
||||
'M' -> if (last == 'C') n += 800 else n += 1000
|
||||
}
|
||||
last = c
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val romans = arrayOf("I", "III", "IV", "VIII", "XLIX", "CCII", "CDXXXIII", "MCMXC", "MMVIII", "MDCLXVI")
|
||||
for (roman in romans) println("${roman.padEnd(10)} = ${romanDecode(roman)}")
|
||||
}
|
||||
16
Task/Roman-numerals-Decode/SPL/roman-numerals-decode.spl
Normal file
16
Task/Roman-numerals-Decode/SPL/roman-numerals-decode.spl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
r2a(r)=
|
||||
n = [1,5,10,50,100,500,1000]
|
||||
a,m = 0
|
||||
> i, #.size(r)..1, -1
|
||||
v,c = n[#.pos("IVXLCDM",#.mid(r,i))]
|
||||
? v<m, v = -v
|
||||
? c>m, m = c
|
||||
a += v
|
||||
<
|
||||
<= a
|
||||
.
|
||||
|
||||
t = ["MMXI","MIM","MCMLVI","MDCLXVI","XXCIII","LXXIIX","IIIIX"]
|
||||
> i, 1..#.size(t,1)
|
||||
#.output(t[i]," = ",r2a(t[i]))
|
||||
<
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
func roman2arabic(roman) {
|
||||
|
||||
var arabic = 0;
|
||||
var last_digit = 1000;
|
||||
|
||||
static m = Hash.new(
|
||||
|
||||
var arabic = 0
|
||||
var last_digit = 1000
|
||||
|
||||
static m = Hash(
|
||||
I => 1,
|
||||
V => 5,
|
||||
X => 10,
|
||||
|
|
@ -11,18 +11,18 @@ func roman2arabic(roman) {
|
|||
C => 100,
|
||||
D => 500,
|
||||
M => 1000,
|
||||
);
|
||||
|
||||
roman.uc.split('').map{m{_} \\ 0}.each { |digit|
|
||||
last_digit < digit && (
|
||||
arabic -= (2 * last_digit);
|
||||
);
|
||||
arabic += (last_digit = digit);
|
||||
)
|
||||
|
||||
roman.uc.chars.map{m{_} \\ 0}.each { |digit|
|
||||
if (last_digit < digit) {
|
||||
arabic -= (2 * last_digit)
|
||||
}
|
||||
arabic += (last_digit = digit)
|
||||
}
|
||||
|
||||
return arabic;
|
||||
|
||||
return arabic
|
||||
}
|
||||
|
||||
|
||||
%w(MCMXC MMVIII MDCLXVI).each { |roman_digit|
|
||||
"%-10s == %d\n".printf(roman_digit, roman2arabic(roman_digit));
|
||||
"%-10s == %d\n".printf(roman_digit, roman2arabic(roman_digit))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ func roman2arabic(digit) {
|
|||
:I: '1+',
|
||||
]).split('+').map{.to_i}.sum;
|
||||
}
|
||||
|
||||
|
||||
%w(MCMXC MMVIII MDCLXVI).each { |roman_num|
|
||||
say "#{roman_num}\t-> #{roman2arabic(roman_num)}";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
BEGIN
|
||||
|
||||
INTEGER PROCEDURE FROMROMAN(S); TEXT S;
|
||||
BEGIN
|
||||
PROCEDURE P(INTVAL, NUM); INTEGER INTVAL; TEXT NUM;
|
||||
BEGIN
|
||||
INTEGER NLEN;
|
||||
NLEN := NUM.LENGTH;
|
||||
WHILE INDEX + NLEN - 1 <= SLEN AND THEN
|
||||
S.SUB(INDEX, NLEN) = NUM DO
|
||||
BEGIN
|
||||
RESULT := RESULT + INTVAL;
|
||||
INDEX := INDEX + NLEN;
|
||||
END WHILE;
|
||||
END P;
|
||||
INTEGER RESULT, INDEX, SLEN;
|
||||
SLEN := S.LENGTH;
|
||||
INDEX := 1;
|
||||
P( 1000, "M" );
|
||||
P( 900, "CM" );
|
||||
P( 500, "D" );
|
||||
P( 400, "CD" );
|
||||
P( 100, "C" );
|
||||
P( 90, "XC" );
|
||||
P( 50, "L" );
|
||||
P( 40, "XL" );
|
||||
P( 10, "X" );
|
||||
P( 9, "IX" );
|
||||
P( 5, "V" );
|
||||
P( 4, "IV" );
|
||||
P( 1, "I" );
|
||||
FROMROMAN := RESULT;
|
||||
END FROMROMAN;
|
||||
|
||||
TEXT T;
|
||||
FOR T :- "MCMXC", "MMVIII", "MDCLXVI" DO
|
||||
BEGIN
|
||||
OUTTEXT("ROMAN """);
|
||||
OUTTEXT(T);
|
||||
OUTTEXT(""" => ");
|
||||
OUTINT(FROMROMAN(T), 0);
|
||||
OUTIMAGE;
|
||||
END FOR;
|
||||
|
||||
END PROGRAM;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
func rtoa( str1: String) -> Int {
|
||||
var str = str1
|
||||
var result = 0
|
||||
|
||||
for (value, letter) in
|
||||
|
||||
[ ( 1000, "M"),
|
||||
( 900, "CM"),
|
||||
( 500, "D"),
|
||||
( 400, "CD"),
|
||||
( 100, "C"),
|
||||
( 90, "XC"),
|
||||
( 50, "L"),
|
||||
( 40, "XL"),
|
||||
( 10, "X"),
|
||||
( 9, "IX"),
|
||||
( 5, "V"),
|
||||
( 3, "IIV"),
|
||||
( 4, "IV"),
|
||||
( 1, "I")]
|
||||
{
|
||||
while str.hasPrefix(letter) {
|
||||
|
||||
let first = str.startIndex
|
||||
let count = letter.characters.count
|
||||
str.removeSubrange(first ..< str.index(first, offsetBy: count))
|
||||
result += value
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
print(rtoa("MDCLXVI")) // 1666
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
Main:
|
||||
!------------------------------------------------
|
||||
! CALLS THE romToDec FUNCTION WITH THE ROMAN
|
||||
! NUMERALS AND RETURNS ITS DECIMAL EQUIVELENT.
|
||||
!
|
||||
|
||||
PRINT "MCMXC = "; romToDec("MCMXC") !1990
|
||||
PRINT "MMVIII = "; romToDec("MMVIII") !2008
|
||||
PRINT "MDCLXVI = "; romToDec("MDCLXVI") !1666
|
||||
PRINT:PRINT
|
||||
PRINT "Here are other solutions not from the TASK:"
|
||||
PRINT "MCMXCIX = "; romToDec("MCMXCIX") !1999
|
||||
PRINT "XXV = "; romToDec("XXV") !25
|
||||
PRINT "CMLIV = "; romToDec("CMLIV") !954
|
||||
PRINT "MMXI = "; romToDec("MMXI") !2011
|
||||
PRINT:PRINT
|
||||
PRINT "Without error checking, this also is 2011, but is wrong"
|
||||
PRINT "MMIIIX = "; romToDec("MMIIIX") !INVAID, 2011
|
||||
|
||||
STOP
|
||||
|
||||
|
||||
FUNCTION romToDec(roman AS STRING) AS INTEGER
|
||||
!------------------------------------------------------
|
||||
! FUNCTION THAT CONVERTS ANY ROMAN NUMERAL TO A DECIMAL
|
||||
!
|
||||
prenum=0!num=0
|
||||
ln=LEN(roman)
|
||||
FOR i=ln TO 1 STEP -1
|
||||
x$=MID(roman,i,1)
|
||||
n=1000
|
||||
SELECT CASE x$
|
||||
CASE "M":n=n/1
|
||||
CASE "D":n=n/2
|
||||
CASE "C":n=n/10
|
||||
CASE "L":n=n/20
|
||||
CASE "X":n=n/100
|
||||
CASE "V":n=n/200
|
||||
CASE "I":n=n/n
|
||||
CASE ELSE:n=0
|
||||
END SELECT
|
||||
IF n < preNum THEN num=num-n ELSE num=num+n
|
||||
preNum=n
|
||||
next i
|
||||
|
||||
romToDec=num
|
||||
|
||||
END FUNCTION
|
||||
16
Task/Roman-numerals-Decode/Zkl/roman-numerals-decode.zkl
Normal file
16
Task/Roman-numerals-Decode/Zkl/roman-numerals-decode.zkl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
var romans = L(
|
||||
L("M", 1000), L("CM", 900), L("D", 500), L("CD", 400), L("C", 100),
|
||||
L("XC", 90), L("L", 50), L("XL", 40), L("X", 10), L("IX", 9),
|
||||
L("V", 5), L("IV", 4), L("I", 1));
|
||||
fcn toArabic(romanNumber){ // romanNumber needs to be upper case
|
||||
if (not RegExp("^[CDILMVX]+$").matches(romanNumber))
|
||||
throw(Exception.ValueError("Not a Roman number: %s".fmt(romanNumber)));
|
||||
reg value = 0;
|
||||
foreach R,N in (romans){
|
||||
while (0 == romanNumber.find(R)){
|
||||
value += N;
|
||||
romanNumber = romanNumber[R.len(),*];
|
||||
}
|
||||
}
|
||||
return(value);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue