Python 是簡單又強大的語言,因此拿來訓練非常方便
希望能夠一個禮拜寫兩題的速度紀錄每次解題的過程
除此之外,也會抽空研究python較重要的幾個模組
本次的題目網址
https://py.checkio.org/mission/roman-numerals/
建議可以先自行練習完再來看以下的邏輯解析
=========================================================
羅馬數字的記法如題目所描述
數字 | 羅馬數字 |
1 | I |
5 | V |
10 | X |
50 | L |
100 | C |
500 | D |
1000 | M |
這樣看起來直觀來說
如果題目給了3567
可以寫迴圈和if的判斷式 從最大的開始扣
3000 - 1000*3 (扣了1000三次) ==> 結果用空字串紀錄 MMM
567 - 500*1 (扣了500一次) ==> 結果用空字串紀錄 MMMD
67 < 100 跳過 100的轉換
67 - 50*1 (扣了50一次) ==> 結果用空字串紀錄 MMMDL
17 - 10*1 (扣了10一次) ==> 結果用空字串紀錄 MMMDLX
7 - 5*1 (扣了5一次) ==> 結果用空字串紀錄 MMMDLXV
2 - 1*2 (扣了1兩次) ==> 結果用空字串紀錄 MMMDLXVII
得到最後答案 3567 的羅馬數字轉換結果為 MMMDLXVII
但是依照這個邏輯解題之後發現某些題目竟然是錯誤的轉換
原因在於羅馬數字表示有個限制
就是同樣的符號不可重複超過三次 (但題目上沒有明確表示)
因此 如果遇到 4 或者 900
依照我們的邏輯會表示成 IIII 以及 LXXXX
但在維基百科裡 https://en.wikipedia.org/wiki/Roman_numerals
4 和 900 的表示方法是 IV 和 XC
就維基百科的解釋是 為了不呈現重複超過四次以上的羅馬數字
運用了另一套機制
例如 4 地表示法為 IV
I 比 V 還小而且放在V的左邊 代表相減的意思
同理 900 地表示法為 XC
因此在寫這提的時候,最重要的關鍵就是除了這幾個羅馬數字以外
還要考慮這個問題,會出現問題的相關數字
例如 4 (IV), 9 (IX) , 40 (XL) , 90 (XC),400 (CD), 900 (CM) 的對應也要考慮進去
如此一來,思考用迴圈的方式和if搭配
就算是最土炮的方式也能夠暴力解出來
def roman(data):
result= ""
while data >= 0:
if data >= 1000:
data = data - 1000
result.append('M')
if data >= 900 and data <1000:
data = data - 900
result.append('CM')
...
return result
雖然直觀,但是程式碼冗長且效率不佳
因此最後我的做法是先建立一個 dictionary 來存所有應考慮的轉換數字
再用迴圈判斷
以下是我最後的程式碼
def roman(number):
ROMANS = (('M', 1000),
('CM', 900),
('D', 500),
('CD', 400),
('C', 100),
('XC', 90),
('L', 50),
('XL', 40),
('X', 10),
('IX', 9),
('V', 5),
('IV', 4),
('I', 1))
result=""
for roman,value in ROMANS:
while number>=value:
number-=value
result+=roman
return result
總結一下這題學到的新技巧
- 需要轉換項目時,建立dictionary是個好選擇
- 羅馬數字有不重複4次的特性要注意,並利用左小右大的方式表示解決
沒有留言:
張貼留言