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:

SymbolValue
I1
V5
X10
L50
C100
D500
M1000

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.

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

准备

  • 开发环境:win10+idea+jdk1.8

  • RomaUtils为实现类。

  • Main类为测试类,执行即可得到答案。

思路

  1. 实现罗马数字转阿拉伯数字
    首先将对应的关系存入map中,如<I,1>
    循环输入的罗马字符串,进行比较

    1. 如果该值比后一个值小,那么加后一个值,减去该值,游标加1;
      否则,加该值;
    2. 游标加1;
      3)循环结束后,判断最后一个值是否已经计算过,如果没有计算,加最后一个值。
      如果有异常,说明输入有误,提示错误信息。
  2. 语义转换
    将自定义变量和罗马字符存入map中,如<glob,I>
    将自定义物品的价格存入map中,如<Silver,23>
    读取输入的语句,将语句进行如下分类:
    1)按照末尾单词是否在bases中,作为第一类型输入,也就是自定义变量和罗马字符映射
    2)判断是否以小写s结束,判断是否是作为第二类型输入
    其中:倒数第二个是总价
    倒数第四个是物品名称
    第一个到倒数第五个为个数
    根据以上信息可以计算单价存入map
    3)判断末尾是否是?号为第三类输入
    4)第三类,进行按照空格划分之后判断第二个单词,按照many和mach进行分别返回处理
    how many:计算总价格
    第五个开始到倒数第3个为个数
    最后2个为名称
    总价:个数乘以单价 num * thingsPrice.get(name)
    拼接字符串,返回结果
    how much:将自定义变量->罗马字符->阿拉伯数字
    第四个到倒数第二个为自定义变量
    将自定义变量转换为罗马字符,整合为字符串
    将罗马字符串转换为阿拉伯数字即可

实现

package com.test.lihao;

import java.util.HashMap;
import java.util.Map;

public class RomaUtils {
    private static Map<Character, Integer> bases;
    private static final String unKnownMsg = "I have no idea what you are talking about";

    public RomaUtils() {
        bases = new HashMap<>();
        bases.put('I', 1);
        bases.put('V', 5);
        bases.put('X', 10);
        bases.put('L', 50);
        bases.put('C', 100);
        bases.put('D', 500);
        bases.put('M', 1000);
    }

    // 输入罗马数字字符串,输出转换后的阿拉伯字符串
    public int toArabicNumber(String romaNumber) {
        int arabicNumber = 0;
        int size = romaNumber.length();
        int i = 0;
        try {
            for (i = 0; i < size - 1; i++) {
                int left = bases.get(romaNumber.charAt(i));
                int right = bases.get(romaNumber.charAt(i + 1));
                if (left < right) {
                    arabicNumber += right - left;
                    i++;
                } else {
                    arabicNumber += left;
                }
            }
            if (i < size) {
                arabicNumber += bases.get(romaNumber.charAt(size - 1));
            }
        } catch (Exception e) {
            System.out.println("输入数字非罗马数字,错误信息为:" + e.getMessage());
        }

        return arabicNumber;
    }

    //语义转换
    //存放自定义变量和罗马字符的转换,如 glob I
    private static Map<String, String> strWithRomaChar = new HashMap<>();
    //存放自定义物品的价格,如 Silver  23
    private static Map<String, Double> thingsPrice = new HashMap<>();

    public String getArabicResultByInputRomaLanguage(String inputRoma) {
        String[] words = inputRoma.split(" ");
        int length = words.length;
        String lastWord = words[length - 1];
        //1、按照末尾单词是否在bases中,是第一类定义单词输入
        //2、判断是否以小写s结束,判断是否是作为第二类金币银币类型输入
        // 3、否则判断末尾是否是?号为第三类输入
        // 4、进行按照空格划分之后判断第二个单词,按照many和mach进行分别返回处理
        if (lastWord.length() == 1 && null != bases.get(lastWord.charAt(0))) {
            //第一类
            //glob is I
            strWithRomaChar.put(words[0], lastWord);
        } else if (lastWord.endsWith("s")) {
            //第二类 倒数第二个是总价
            //glob glob Silver is 34 Credits
            int amount = Integer.parseInt(words[length - 2]);
            //倒数第四个是东西名称
            String thingName = words[length - 4];
            //第一个到倒数第五个为个数
            String romaStr = "";
            for (int i = 0; i < length - 4; i++) {
                String tmp = strWithRomaChar.get(words[i]);
                if (null == tmp || "".equals(tmp)) {
                    System.out.println(unKnownMsg);
                    return unKnownMsg;
                }
                romaStr += tmp;

            }
            int num = toArabicNumber(romaStr);
            thingsPrice.put(thingName, amount * 1.0 / num);
        } else if (lastWord.endsWith("?")) {
            //第三类
            //how many Credits is glob prok Silver ?
            // how much is pish tegj glob glob ?
            //判断how much和howmang
            if ("many".equals(words[1])) {
                //how many
                //第五个开始到倒数第3个为个数
                String romaStr = "";
                for (int i = 4; i < length - 2; i++) {
                    String tmp = strWithRomaChar.get(words[i]);
                    if (null == tmp || "".equals(tmp)) {
                        System.out.println(unKnownMsg);
                        return unKnownMsg;
                    }
                    romaStr += tmp;
                }
                int num = toArabicNumber(romaStr);
                //最后2个为名称
                String name = words[length - 2];
                StringBuffer result = new StringBuffer();
                //glob prok Silver is 68 Credits ?
                for (int i = 4; i < length - 2; i++) {
                    result.append(words[i]).append(" ");
                }
                result.append(name).append(" is ").append((int)(num * thingsPrice.get(name))).append(" Credits");
                System.out.println(result);

            } else if ("much".equals(words[1])) {
                //how much
                //how much is pish tegj glob glob ?
                //第四个到倒数第二个
                String romaStr = "";
                for (int i = 3; i < length - 1; i++) {
                    String tmp = strWithRomaChar.get(words[i]);
                    if (null == tmp || "".equals(tmp)) {
                        System.out.println(unKnownMsg);
                        return unKnownMsg;
                    }
                    romaStr += tmp;
                }
                int resultNumber = toArabicNumber(romaStr);
                StringBuffer result = new StringBuffer();
                //pish tegj glob glob is 42
                for (int i = 3; i < length - 1; i++) {
                    result.append(words[i] + " ");
                }
                result.append(" is " + resultNumber);
                System.out.println(result);
            }

        }
        return null;
    }


}

package com.test.lihao;

public class Main {
    public static void main(String[] args) {
        RomaUtils romaUtils = new RomaUtils();
        String[] inputs = {
                "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 ?"};
        for (int i = 0; i < inputs.length; i++) {
            romaUtils.getArabicResultByInputRomaLanguage(inputs[i]);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值