2025年6月24日 星期二

ZeroJudge 解題筆記:a013. 羅馬數字

作者:王一哲
日期:2025年6月24日


ZeroJudge 題目連結:a013. 羅馬數字

解題想法


這題最麻煩的地方在於 900、400、90、40、9、4 的轉換,分別換成 CM、CD、XC、XL、IX、IV。程式碼寫起來很長,我想不到更精簡的寫法。

Python 程式碼


使用時間約為 17 ms,記憶體約為 3.4 MB,通過測試。
import sys

# 羅馬數字字串 s 換成整數
def rton(s):
    # 字母換成對應的整數
    cton = {'M': 1000, 'D': 500, 'C': 100, 'L': 50, 'X': 10, 'V': 5, 'I': 1}
    n = n1 = cton[s[0]]  # 第1位數
    for c in s[1:]:  # 依序讀取 s[1] ~ s[-1]
        n2 = cton[c]  # 對應的整數 n2
        if n2 > n1:  # 如果 n2 較大,n 加上 n2,減掉 2 倍 n1
            n = n - 2*n1 + n2
        else:  # 反之,直接加上 n2
            n = n + n2
        n1 = n2  # 更新 n1
    return n  # 回傳 n

# 整數換成羅馬數字
def ntor(n):
    s = ""  # 儲存結果用的空字串
    # 處理 1000 的倍數
    M = n//1000; s += "M"*M; n %= 1000
    # 處理 500 的倍數
    D = n//500; s += "D"*D; n %= 500
    # 處理 100 的倍數
    C = n//100; n %= 100
    if C == 4 and D == 1:  # 900
        s = s[:-1]  # 刪除最後一位
        s += "CM"  # 加上 "CM"
    elif C == 4 and D == 0:  # 400
        s += "CD"  # 加上 "CM"
    else: s += "C"*C  # 其它狀況,加上 C 個 "C"
    # 處理 50 的倍數
    L = n//50; n %= 50
    if L == 1: s += "L"  # 如果 L 等於 1,加上 "L"
    # 處理 10 的倍數
    X = n//10; n %= 10
    if X == 4 and L == 1:  # 90
        s = s[:-1]  # 刪除最後一位
        s += "XC"  # 加上 "XC"
    elif X == 4 and L == 0:  # 40
        s += "XL"  # 加上 "XL"
    else: s += "X"*X  # 其它狀況,加上 X 個 "X"
    # 處理 5 的倍數
    V = n//5; n %= 5
    if V == 1: s += "V"  # 如果 V 等於 1,加上 "V"
    # 處理 1
    I = n
    if I == 4 and V == 1:  # 9
        s = s[:-1]  # 刪除最後一位
        s += "IX"  # 加上 "IX"
    elif I == 4 and V == 0:  # 4
        s += "IV"  # 加上 "IV"
    else: s += "I"*I  # 其它狀況,加上 I 個 "I"
    # 回傳結果
    return s

for line in sys.stdin:
    if line.rstrip() == "#": break
    a, b = line.split()  # 羅馬數字 a, b
    na, nb = rton(a), rton(b)  # 轉成整數 na, nb
    diff = abs(na - nb)  # 差值
    print("ZERO" if diff == 0 else ntor(diff))


C++ 程式碼


使用時間約為 2 ms,記憶體約為 324 kB,通過測試。
#include <iostream>
#include <string>
#include <map>
using namespace std;

/* 羅馬數字字串 s 換成整數 */
int rton(string s) {
    // 字母換成對應的整數
    map<char, int> cton = {{'M', 1000}, {'D', 500}, {'C', 100}, {'L', 50},
                           {'X', 10}, {'V', 5}, {'I', 1}};
    int n = cton[s[0]];  //  第1位數
    int n1 = n;
    for(char c : s.substr(1)) {  // 依序讀取 s[1] ~ s[-1]
        int n2 = cton[c];  // 對應的整數 n2
        if (n2 > n1) {  // 如果 n2 較大,n 加上 n2,減掉 2 倍 n1
            n = n - 2*n1 + n2;
        } else {  // 反之,直接加上 n2
            n = n + n2;
        }
        n1 = n2;  // 更新 n1
    }
    return n;  // 回傳 n
}

/* 整數換成羅馬數字 */
string ntor(int n) {
    string s = "";  // 儲存結果用的空字串
    // 處理 1000 的倍數
    int M = n/1000;
    n %= 1000;
    string t (M, 'M');  // 要補上 M 個字母 M
    s += t;
    // 處理 500 的倍數
    int D = n/500;
    n %= 500;
    string td (D, 'D');  // 要補上 D 個字母 D
    s += td;
    // 處理 100 的倍數
    int C = n/100;
    n %= 100;
    if (C == 4 && D == 1) {  // 900
        s.pop_back();  // 刪除最後一位
        s += "CM";  // 加上 "CM"
    } else if (C == 4 && D == 0) {  // 400
        s += "CD";  // 加上 "CM"
    } else {  // 其它狀況,加上 C 個 "C"
        string tc (C, 'C');
        s += tc;
    }
    // 處理 50 的倍數
    int L = n/50;
    n %= 50;
    if (L == 1) {  // 如果 L 等於 1,加上 "L"
        string tL (L, 'L');
        s += tL;
    }
    // 處理 10 的倍數
    int X = n/10;
    n %= 10;
    if (X == 4 && L == 1) {  // 90
        s.pop_back();  // 刪除最後一位
        s += "XC";  // 加上 "XC"
    } else if (X == 4 && L == 0) {  // 40
        s += "XL";  // 加上 "XL"
    } else {  // 其它狀況,加上 X 個 "X"
        string tx (X, 'X');
        s += tx;
    }
    // 處理 5 的倍數
    int V = n/5;
    n %= 5;
    if (V == 1) s += "V";  // 如果 V 等於 1,加上 "V"
    // 處理 1
    int I = n;
    if (I == 4 && V == 1) {  // 9
        s.pop_back();  // 刪除最後一位
        s += "IX";  // 加上 "IX"
    } else if (I == 4 and V == 0) {  // 4
        s += "IV";  // 加上 "IV"
    } else {  // 其它狀況,加上 I 個 "I"
        string tv (I, 'I');
        s += tv;
    }
    // 回傳結果
    return s;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    string a, b;
    while(cin >> a) {
        if (a == "#") break;
        cin >> b;  // 羅馬數字 a, b
        int na = rton(a), nb = rton(b);  // 轉成整數 na, nb
        int diff = abs(na - nb);  // 差值
        cout << (diff == 0 ? "ZERO" : ntor(diff)) << "\n";
    }
    return 0;
}


沒有留言:

張貼留言