Zerojudge 基礎題庫a013 羅馬數字 (Python)


一、題目重述

這題真的需要好好講一下,因為題目敘述真的好長。

我重新敘述一下題目好了:
輸入: 兩個羅馬數字
輸出: 一個羅馬數字,值為輸入的兩值相減

二、解法大綱

首先,羅馬數字只是用來單純標示他的值,無法做計算
而且電腦只看得懂阿拉伯數字,所以在做計算時,須先把羅馬轉成阿拉伯

因為題目是輸入兩個羅馬數字,無法直接做相減的動作,所以第一步先把羅馬轉成阿拉伯。
轉成阿拉伯後,就可以相減了,記得加絕對值,因為題目說可能第一數比較小。

計算出答案後,最後把它變成羅馬數字,就可以了。

三、解法問題

有兩個問題,也就是題目的主要部分。

1.羅馬轉成阿拉伯

我們先來觀察一個羅馬數字:
III
我想聰明的你,這一定是三,那我問: 你怎麼知道?
我先給一下轉換表:
  • I 1 
  • V5 
  • X10 
  • L50 
  • C100 
  • D500 
  • M1000
好,回來正題,III可以看成是 I + I + I
轉換後也就是 1 + 1 + 1,答案是3

再一個羅馬數字
IV
如果你用上面的方法,1 + 5 = 6,可是答案是四耶~
那是因為羅馬數字有一個特殊的規則,
數碼限制:同一數碼最多只能連續出現三次,如40不可表示為XXXX,而要表示為XL
(羅馬數字 - 維基百科)
如果我們使用IIII來表示4,感覺I太多了,所以用IV來表示,意思是 5 - 1
換一個方式來表達,也就是 -1 + 4

那 MCDXXXVII 呢?我們先把一個一個分開來,變成:M, C, D, X, X, X, V, I, I
接下來,一一轉成數字,變成: 1000, 100, 500, 10, 10, 10, 5, 1, 1
接著,我們使用一個小伎倆:
在較大的羅馬數字的左邊記上較小的羅馬數字,表示大數字減小數字
我們先找右邊數字比自己大的,找到就把它變成負的
1000, 100, 500, 10, 10, 5, 1, 1
1000右邊是100,比1000小,不變成負的,下一個
100右邊是500,比100大,把它變成負的(100 => -100)
500右邊是10,比500小,不變成負的,下一個
就這樣一直到倒數第二個,最後數列為:
1000, -100, 500, 10, 10, 5, 1, 1
把全部加總:
1000 + (-100) + 500 + 10 + 10 + 5 + 1 + 1 = 1437
1437 就是 MCDXXXVII 啦~

2.阿拉伯轉成羅馬

接下來我們來看1437如何轉成羅馬數字
我們先把1437看成1000 + 400 + 30 + 7
1000用羅馬數字是M
400是CD
30是XXX
7是VII
所以用羅馬數字就是MCDXXXVII

我把所有可能的數字都寫在下面:

千位:
1000 => M
2000 => MM
3000 => MMM
百位:
100 => C
200 => CC
300 => CCC
400 => CD
500 => D
600 => DC
700 => DCC
800 => DCCC
900 => CM
十位:
10 => X
20 => XX
30 => XXX
40 => XL
50 => L
60 => LX
70 => LXX
80 => LXXX
90 => LC (是XC,感謝Unknown糾正 .w.)
個位:
1 => I
2 => II
3 => III
4 => IV
5 => V
6 => VI
7 => VII
8 => VIII
9 => IX

四、程式碼

好,相信你已經沒問題了
Python 程式碼:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
def translate_to_numbers(num):
    '''將羅馬數字轉換成阿拉伯數字'''
    # numbers : 轉換規則
    numbers = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
    # x1_list : 存放轉換計算過程
    x1_list = []
    # sum1 : 轉換後的阿拉伯數字
    sum1 = 0
    # 將羅馬數字轉換成串列
    for i in num:
        x1_list.append(i)
    # 將各個羅馬數字變成數字,使用numbers字典
    for i in range(len(x1_list)):  # 0 ~ x1_list end (int)
        x1_list[i] = numbers[x1_list[i]]
    # 尋找需要使用減法的數字
    for i in range(1, len(x1_list)):  # 1 ~ x1_list end (int)
        if x1_list[i - 1] < x1_list[i]:
            x1_list[i - 1] = -x1_list[i - 1]
    # 把計算過程全部加總起來,放入sum1
    for i in range(len(x1_list)):
        sum1 += x1_list[i]
    # 回傳答案
    return sum1


def roma(num):
    '''將阿拉伯數字轉換成羅馬數字'''
    # x : 問題
    x = num

    # 分別存入千、百、十、個位數到thousand,hundred,ten,one裡
    thousand = x // 1000
    hundred = x % 1000 // 100
    one = x % 10
    ten = (x % 100 - one) // 10
    
    # 將千位數以羅馬數字輸出
    if thousand != 0:
        for i in range(thousand):
            print('M', end="")
    # 將百位數以羅馬數字輸出
    if hundred != 0:
        
        if hundred <= 3:
            for i in range(hundred):
                print('C', end="")
        if hundred == 4:
            print("CD", end="")
        if hundred >= 5 and hundred != 9:
            print("D", end="")
            for i in range(hundred - 5):
                print("C", end="")
        if hundred == 9:
            print("CM", end="")
    # 將十位數以羅馬數字輸出
    if ten != 0:
        # ten output
        if ten <= 3:
            for i in range(ten):
                print('X', end="")
        if ten == 4:
            print("XL", end="")
        if ten >= 5 and ten != 9:
            print("L", end="")
            for i in range(ten - 5):
                print("X", end="")
        if ten == 9:
            print("XC", end="")
    # 將個位數以羅馬數字輸出
    if one != 0:
        
        if one <= 3:
            for i in range(one):
                print('I', end="")
        if one == 4:
            print("IV", end="")
        if one >= 5 and one != 9:
            print("V", end="")
            for i in range(one - 5):
                print("I", end="")
        if one == 9:
            print("IX", end="")


while 1:

    x1 = input()
    # 當輸入為#時結束程式
    if x1 == '#':
        break
    # 把輸入弄成我們需要的資訊(兩個羅馬數字)
    question = x1.split()
    x1 = question[0]
    x2 = question[1]
    
    # 兩個數字相減
    ans1 = translate_to_numbers(x1) - translate_to_numbers(x2)
    # 做絕對值的動作
    if ans1 < 0:
        ans1 = -ans1
    # 當答案是0時輸出ZERO
    if ans1 == 0:
        print("ZERO", end="")
    else:
        roma(ans1)
    # 換行(格式需求)
    print()



















留言

張貼留言

這個網誌中的熱門文章

Zerojudge 基礎題庫a004 文文的求婚 (Python)

紙蜻蜓的受風面積與紙蜻蜓落地時間的關係 #1 [實驗歷程與Python Matplotlib]

Zerojudge 原創/不分類題庫b882 溢位 の OωO學長?