Problem Three: Merchant’s Guide to the Galaxy
You decided to give up on earth after the latest financial collapse left 99.99% of the earth’s population with 0.01% of the wealth. Luckily, with the scant sum of money that is left in your account, you are able to afford to rent a spaceship, leave earth, and fly all over the galaxy to sell common metals and dirt (which apparently is worth a lot).
Buying and selling over the galaxy requires you to convert numbers and units, and you decided to write a program to help you.
The numbers used for intergalactic transactions follows similar convention to the roman numerals and you have painstakingly collected the appropriate translation between them.
Roman numerals are based on seven symbols:
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1,000
Numbers are formed by combining symbols together and adding the values. For example, MMVI is 1000 + 1000 + 5 + 1 = 2006. Generally, symbols are placed in order of value, starting with the largest values. When smaller values precede larger values, the smaller values are subtracted from the larger values, and the result is added to the total. For example MCMXLIV = 1000 + (1000 − 100) + (50 − 10) + (5 − 1) = 1944.
• The symbols “I”, “X”, “C”, and “M” can be repeated three times in succession, but no more. (They may appear four times if the third and fourth are separated by a smaller value, such as XXXIX.) “D”, “L”, and “V” can never be repeated.
• “I” can be subtracted from “V” and “X” only. “X” can be subtracted from “L” and “C” only. “C” can be subtracted from “D” and “M” only. “V”, “L”, and “D” can never be subtracted.
• Only one small-value symbol may be subtracted from any large-value symbol.
• A number written in [16]Arabic numerals can be broken into digits. For example, 1903 is composed of 1, 9, 0, and 3. To write the Roman numeral, each of the non-zero digits should be treated separately. Inthe above example, 1,000 = M, 900 = CM, and 3 = III. Therefore, 1903 = MCMIII.
(Source: Wikipedia ( [17]http://en.wikipedia.org/wiki/Roman_numerals)
Input to your program consists of lines of text detailing your notes on the conversion between intergalactic units and roman numerals.
You are expected to handle invalid queries appropriately.
Test input:
glob is I
prok is V
pish is X
tegj is L
glob glob Silver is 34 Credits
glob prok Gold is 57800 Credits
pish pish Iron is 3910 Credits
how much is pish tegj glob glob ?
how many Credits is glob prok Silver ?
how many Credits is glob prok Gold ?
how many Credits is glob prok Iron ?
how much wood could a woodchuck chuck if a woodchuck could chuck wood ?
Test Output:
pish tegj glob glob is 42
glob prok Silver is 68 Credits
glob prok Gold is 57800 Credits
glob prok Iron is 782 Credits
I have no idea what you are talking about
import java.util.*;
public class MyTest {
/**
* 初始化罗马符号和数值的对应关系
*/
HashMap<Character,Integer> initMap = new HashMap<>();
{
initMap.put('I',1);
initMap.put('V',5);
initMap.put('X',10);
initMap.put('L',50);
initMap.put('C',100);
initMap.put('D',500);
initMap.put('M',1000);
}
/**
* 计算方法
* @param inputRomanValue
* @return
* @throws Exception
*/
public int calculate(String inputRomanValue) throws Exception {
// 判断是否是空串
if (inputRomanValue.equals("")){
return 0;
}
char[] romans = inputRomanValue.toCharArray();
int result = 0;
int repeatI = 0,repeatX = 0,repeatC = 0,repeatM = 0,repeatD = 0,repeatL = 0,repeatV = 0;
for (int i = 0; i <= romans.length - 1; i++) {
Character currentKey = null;
int currentValue = 0;
Character nextKey = null;
int nextValue = 0;
for(Character key:initMap.keySet()){
if(key == romans[i]){
currentKey = key;
currentValue = initMap.get(key);
}
}
// The symbols "I", "X", "C", and "M" can be repeated three times in succession
if('I' == romans[i]){
repeatI++;
}else if('X' == romans[i]){
repeatX++;
}else if('C' == romans[i]){
repeatC++;
}else if('M' == romans[i]){
repeatM++;
}else if('D' == romans[i]){
repeatD++;
}else if('L' == romans[i]){
repeatL++;
}else if('V' == romans[i]){
repeatV++;
}
if(repeatI > 3 || repeatX > 3 ||repeatC > 3 ||repeatM > 3){
throw new Exception("Not allow " + currentKey + " repeated more than 3 times");
}
// "D", "L", and "V" can never be repeated.
if(repeatD > 1 || repeatL > 1 ||repeatV > 1){
throw new Exception("Not allow " + currentKey + " repeated more than 1 times");
}
//如果是最后一个则退出循环
if (i >= romans.length - 1) {
result += currentValue;
break;
}
// 获取当前位置的下一个值
for(Character key:initMap.keySet()){
if(key == romans[i+1]){
nextKey = key;
nextValue = initMap.get(key);
}
}
if (currentValue == 0) {
throw new Exception("unexpected roman char:"+romans[i]);
}
if (nextValue == 0) {
throw new Exception("unexpected roman char:"+romans[i + 1]);
}
//判断当前值和下一个值的大小
if (currentValue >= nextValue) {
result += currentValue;
}else {
// "I" can be subtracted from "V" and "X" only.
if(currentKey == 'I' && nextKey != 'V' && nextKey != 'X'){
throw new Exception("Not allow " + nextKey + " subtract" + currentKey);
}
// "X" can be subtracted from "L" and "C" only.
if(currentKey == 'X' && nextKey != 'L' && nextKey != 'C'){
throw new Exception("Not allow " + nextKey + " subtract" + currentKey);
}
// "C" can be subtracted from "D" and "M" only.
if(currentKey == 'C' && nextKey != 'D' && nextKey != 'M'){
throw new Exception("Not allow " + nextKey + " subtract" + currentKey);
}
// "V", "L", and "D" can never be subtracted.
if('V' == romans[i] || 'L' == romans[i] || 'D' == romans[i]){
throw new Exception("Not allow " + currentKey + " subtracted");
}
result += nextValue - currentValue;
i++;
}
}
return result;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 从键盘接收数据
// 判断是否还有输入
MyTest test = new MyTest();
while (true){
if (scan.hasNextLine()) {
String inputRomanValue = scan.nextLine();
try {
System.out.println("Their money is " + inputRomanValue + ".");
System.out.println("My money is " + test.calculate(inputRomanValue) + ".");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}