Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -1,3 +1,5 @@
Create a function that takes a Roman numeral as its argument and returns its value as a numeric decimal integer. You don't need to validate the form of the Roman numeral.
Modern Roman numerals are written by expressing each decimal digit of the number to be encoded separately, starting with the leftmost digit and skipping any 0s. So 1990 is rendered "MCMXC" (1000 = M, 900 = CM, 90 = XC) and 2008 is rendered "MMVIII" (2000 = MM, 8 = VIII). The Roman numeral for 1666, "MDCLXVI", uses each letter in descending order.
Modern Roman numerals are written by expressing each decimal digit of the number to be encoded separately, starting with the leftmost digit and skipping any 0s.
So 1990 is rendered "MCMXC" (1000 = M, 900 = CM, 90 = XC) and 2008 is rendered "MMVIII" (2000 = MM, 8 = VIII).
The Roman numeral for 1666, "MDCLXVI", uses each letter in descending order.

View file

@ -4,3 +4,11 @@
(partition-by identity)
(map (partial apply +))
(reduce #(if (< %1 %2) (+ %1 %2) (- %1 %2)))))
;; alternative
(def numerals { \I 1, \V 5, \X 10, \L 50, \C 100, \D 500, \M 1000})
(defn from-roman [s]
(->> s .toUpperCase
(map numerals)
(reduce (fn [[sum lastv] curr] [(+ sum curr (if (< lastv curr) (* -2 lastv) 0)) curr]) [0,0])
first))

View file

@ -1,6 +1,6 @@
import std.regex, std.algorithm;
immutable int[string] w2s;
immutable uint[string] w2s;
pure nothrow static this() {
w2s = ["IX": 9, "C": 100, "D": 500, "CM": 900, "I": 1,
@ -8,7 +8,7 @@ pure nothrow static this() {
"V": 5, "X": 10, "IV": 4];
}
int toArabic(in string s) /*pure nothrow*/ {
uint toArabic(in string s) /*pure nothrow*/ @safe /*@nogc*/ {
return s
.matchAll("CM|CD|XC|XL|IX|IV|[MDCLXVI]".regex)
.map!(m => w2s[m.hit])

View file

@ -0,0 +1,111 @@
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
local
numbers: ARRAY [STRING]
do
numbers := <<"MCMXC", "MMVIII", "MDCLXVI",
-- 1990 2008 1666
"MMMCLIX", "MCMLXXVII", "MMX">>
-- 3159 1977 2010
across numbers as n loop
print (n.item +
" in Roman numerals is " +
roman_to_decimal (n.item).out +
" in decimal Arabic numerals.")
print ("%N")
end
end
feature -- Roman numerals
roman_to_decimal (a_str: STRING): INTEGER
-- Decimal representation of Roman numeral `a_str'
require
is_roman (a_str)
local
l_pos: INTEGER
cur: INTEGER -- Value of the digit read in the current iteration
prev: INTEGER -- Value of the digit read in the previous iteration
do
from
l_pos := 0
Result := 0
prev := 1 + max_digit_value
until
l_pos = a_str.count
loop
l_pos := l_pos + 1
cur := roman_digit_to_decimal (a_str.at (l_pos))
if cur <= prev then
-- Add nonincreasing digit
Result := Result + cur
else
-- Subtract previous digit from increasing digit
Result := Result - prev + (cur - prev)
end
prev := cur
end
ensure
Result >= 0
end
is_roman (a_string: STRING): BOOLEAN
-- Is `a_string' a valid sequence of Roman digits?
do
Result := across a_string as c all is_roman_digit (c.item) end
end
feature {NONE} -- Implementation
max_digit_value: INTEGER = 1000
is_roman_digit (a_char: CHARACTER): BOOLEAN
-- Is `a_char' a valid Roman digit?
local
l_char: CHARACTER
do
l_char := a_char.as_upper
inspect l_char
when 'I', 'V', 'X', 'L', 'C', 'D', 'M' then
Result := True
else
Result := False
end
end
roman_digit_to_decimal (a_char: CHARACTER): INTEGER
-- Decimal representation of Roman digit `a_char'
require
is_roman_digit (a_char)
local
l_char: CHARACTER
do
l_char := a_char.as_upper
inspect l_char
when 'I' then
Result := 1
when 'V' then
Result := 5
when 'X' then
Result := 10
when 'L' then
Result := 50
when 'C' then
Result := 100
when 'D' then
Result := 500
when 'M' then
Result := 1000
end
ensure
Result > 0
end
end

View file

@ -27,7 +27,7 @@ func parseRoman(s string) (r int, err error) {
for i := len(is) - 1; i >= 0; i-- {
// read roman digit
c := is[i]
k := c == 0x305 // unicode overbar combining character
k := c == '\u0305' // unicode overbar combining character
if k {
if i == 0 {
return 0, errors.New(
@ -39,11 +39,11 @@ func parseRoman(s string) (r int, err error) {
cv := m[c]
if cv == 0 {
if c == 0x0305 {
return 0, errors.New(fmt.Sprintf(
"Overbar combining character invalid at position %d", i))
return 0, fmt.Errorf(
"Overbar combining character invalid at position %d", i)
} else {
return 0, errors.New(fmt.Sprintf(
"Character unrecognized as Roman digit: %c", c))
return 0, fmt.Errorf(
"Character unrecognized as Roman digit: %c", c)
}
}
if k {

View file

@ -2,23 +2,22 @@ package main
import (
"fmt"
"strings"
)
var m = map[string]int{
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000,
var m = map[rune]int{
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000,
}
// function, per task description
func from_roman(roman string) (arabic int) {
last_digit := 1000
for _, r := range strings.Split(roman, "") {
for _, r := range roman {
digit := m[r]
if last_digit < digit {
arabic -= 2 * last_digit

View file

@ -12,9 +12,3 @@ def roman_value(roman):
if __name__=='__main__':
for value in "MCMXC", "MMVIII", "MDCLXVI":
print('%s = %i' % (value, roman_value(value)))
""" Output:
MCMXC = 1990
MMVIII = 2008
MDCLXVI = 1666
"""

View file

@ -0,0 +1,13 @@
romanToArabic <- function(roman) {
romanLookup <- c(I=1L, V=5L, X=10L, L=50L, C=100L, D=500L, M=1000L)
rSplit <- strsplit(toupper(roman), character(0)) # Split input vector into characters
toArabic <- function(item) {
digits <- romanLookup[item]
if (length(digits) > 1L) {
smaller <- (digits[-length(digits)] < digits[-1L])
digits[smaller] <- - digits[smaller]
}
sum(digits)
}
vapply(rSplit, toArabic, integer(1))
}

View file

@ -0,0 +1 @@
romanToArabic(c("MCMXII", "LXXXVI"))

View file

@ -0,0 +1 @@
as.integer(as.roman(c("MCMXII", "LXXXVI"))

View file

@ -9,6 +9,14 @@ def fromRoman( r:String ) : Int = {
} }
}
// Here is a another version that does a simple running sum:
def fromRoman2(s: String) : Int = {
val numerals = Map('I' -> 1, 'V' -> 5, 'X' -> 10, 'L' -> 50, 'C' -> 100, 'D' -> 500, 'M' -> 1000)
s.toUpperCase.map(numerals).foldLeft((0,0)) {
case ((sum, last), curr) => (sum + curr + (if (last < curr) -2*last else 0), curr) }._1
}
}
// A small test
def test( roman:String ) = println( roman + " => " + fromRoman( roman ) )

View file

@ -0,0 +1,12 @@
(use gauche.collection) ;; for fold2
(define (char-val char)
(define i (string-scan "IVXLCDM" char))
(* (expt 10 (div i 2)) (expt 5 (mod i 2))))
(define (decode roman)
(fold2
(lambda (n sum prev-val)
(values ((if (< n prev-val) - +) sum n) (max n prev-val)))
0 0
(map char-val (reverse (string->list roman)))))

View file

@ -0,0 +1,3 @@
(for-each
(^s (format #t "~7d: ~d\n" s (decode s)))
'("MCMLVI" "XXC" "MCMXC" "XXCIII" "IIIIX" "MIM" "LXXIIX"))