算法很简单,其实就是输入一个阿拉伯数字,输出一个罗马数字。
说明:但是这个只是一个简单的版本,输入的数字不算大,不涉及相对较大数的复杂罗马数字表达(比如,上面带横线之类)。
比如:
1990 =>:1000=M, 900=CM, 90=XC; => MCMXC.
2008 => 2000=MM, 8=VIII; => MMVIII.
1666 => MDCLXVI.
1、一些提示
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1,000
2、同一个字符,最多可以重复3次。
3、40,400的可以分别用XL,CD来表达。
其它的说明,可以找度娘。
一、我的算法
fn num_as_roman(num: i32) -> String {
let data: HashMap<i32, &str> = [(0, ""),
(1, "I"),
(2, "II"),
(3, "III"),
(4, "IV"),
(5, "V"),
(6, "VI"),
(7, "VII"),
(8, "VIII"),
(9, "IX"),
(10, "X"),
(20, "XX"),
(30, "XXX"),
(40, "XL"),
(50, "L"),
(60, "LX"),
(70, "LXX"),
(80, "LXXX"),
(90, "XC"),
(100, "C"),
(200, "CC"),
(300, "CCC"),
(400, "CD"),
(500, "D"),
(600, "DC"),
(700, "DCC"),
(800, "DCCC"),
(900, "CM"),
(1000, "M"),
(2000, "MM"),
(3000, "MMM")]
.into_iter()
.map(|w| (w.0, w.1))
.collect::<HashMap<i32, &str>>();
let chars: Vec<char> = num.to_string().chars().into_iter().map(|x| x).collect();
let fact_nums = fact_num(num);
fact_nums.into_iter()
.map(|x| *(data.get(&(x.0 * x.1)).unwrap()))
.collect::<Vec<&str>>()
.join("")
}
fn fact_num(num: i32) -> Vec<(i32, i32)> {
let len = num.to_string().len() as i32;
let mut result: Vec<(i32, i32)> = Vec::new();
let mut remain: i32 = num;
for i in 0..len {
let k = len - i - 1;
let pow_value = 10_f64.powf(k as f64) as i32;
let temp = remain / pow_value;
remain = remain - temp * pow_value;
if k < 1 {
result.push((1, temp));
} else {
result.push((temp, pow_value));
}
println!("temp :{:?}, remain:{:?}", temp, remain);
}
result
}
当然,也可以用 HashMap
fn num_as_roman(num: i32) -> String {
let data: HashMap<i32, String> = [(0, ""),
(1, "I"),
(2, "II"),
(3, "III"),
(4, "IV"),
(5, "V"),
(6, "VI"),
(7, "VII"),
(8, "VIII"),
(9, "IX"),
(10, "X"),
(20, "XX"),
(30, "XXX"),
(40, "XL"),
(50, "L"),
(60, "LX"),
(70, "LXX"),
(80, "LXXX"),
(90, "XC"),
(100, "C"),
(200, "CC"),
(300, "CCC"),
(400, "CD"),
(500, "D"),
(600, "DC"),
(700, "DCC"),
(800, "DCCC"),
(900, "CM"),
(1000, "M"),
(2000, "MM"),
(3000, "MMM")]
.into_iter()
.map(|w| (w.0, w.1.to_string()))
.collect::<HashMap<i32, String>>();
let chars: Vec<char> = num.to_string().chars().into_iter().map(|x| x).collect();
let fact_nums = fact_num(num);
fact_nums.into_iter()
.map(|x| (&data).get(&(x.0 * x.1)).unwrap().to_string())
.collect::<Vec<String>>()
.join("")
}
二、精彩的算法
fn rep(c: char, n: usize) -> String {
std::iter::repeat(c).take(n).collect()
}
fn roman(d: u8, p: usize) -> String {
let nines = ["IX", "XC", "CM"];
let fives = ["V", "L", "D"];
let fours = ["IV", "XL", "CD"];
let ones = ['I', 'X', 'C', 'M'];
match d {
0 => String::from(""),
9 => String::from(nines[p]),
n if n > 5 => String::from(fives[p]) + &rep(ones[p], (n - 5) as usize),
5 => String::from(fives[p]),
4 => String::from(fours[p]),
n => rep(ones[p], n as usize),
}
}
fn num_as_roman(num: i32) -> String {
let s = num.to_string();
let l = s.len();
let mut r = String::new();
for (i, d) in s.chars().enumerate() {
let p = (l - i - 1) as usize;
r += &roman(d.to_digit(10).unwrap() as u8, p);
}
r
}
2、
const ONES: [&'static str; 10] = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"];
const TENS: [&'static str; 10] = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"];
const HUNS: [&'static str; 10] = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"];
const TOUS: [&'static str; 10] = ["", "M", "MM", "MMM", "", "", "", "", "", ""];
const DIGITS: [[&'static str; 10]; 4] = [ONES, TENS, HUNS, TOUS];
fn num_as_roman(num: i32) -> String {
[num/1000, num/100, num/10, num]
.into_iter()
.enumerate()
.map(|(i, &d)| DIGITS[3 - i][(d % 10) as usize])
.collect()
}
3、
static ROMAN_DEC: [(&'static str, i32); 13] =
[("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)];
/// Converts a number to a string representating roman numeral.
fn num_as_roman(num: i32) -> String {
let mut num = num;
let mut result = String::new();
for &(ref lit, val) in &ROMAN_DEC {
while num >= val {
result.push_str(lit);
num -= val;
}
if num == 0 { break }
}
result
}