Merchant‘s Guide to the Galaxy

leehao_howard發表於2021-01-02

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]);
        }
    }
}

相關文章