2020年2月27日 星期四

[zerojudge]a013. 羅馬數字

a013. 羅馬數字

這題是現在遇到最有難度的問題,不花點時間想想還真解不出來。 羅馬數字的規則:

羅馬數字 數目
I 1
V 5
X 10
L 50
C 100
D 500
M 1,000

加法規則

依據上表由大到小加起來表示數目
e.g.
  • 1 = I
  • 3 = III
  • 5 = V
  • 7 = VII
  • 110 = CX

減法規則

依據上表由小到大組成,表示大數目減小數目,遇到4、9時適用
e.g.
  • 4 = 5 - 1 = IV
  • 9 = 10 - 1 = IX
  • 40 = 50 - 10 = XL
  • 99 = 90 + 9 = (100 - 10) + (10 - 1) = XC + IX = XCIX
  • 110 = CX
羅馬字和整數的表格轉換成一個字串roman和整數陣列num,
roman = "IVXLCDM"
num = {1, 5, 10, 50, 100, 500, 1000}
每個字元的位置對應到num的值,num[roman.indexOf(要查詢的字元)]。


解題分兩個部份:

一、羅馬轉整數

讀入字串後依據左到右的順序,判斷是大到小還是小到大進而決定適用哪種規則。判斷的方法是字元兩個兩個比對,0號和1號比,1號和2號比…以此類推。 為了避免最後一個字元沒有可以比對的對象,在字串後面加上一個"I"。 如果是小到大即加法規則,把加進結果中。大到小就相減再加進結果。

二、整數轉羅馬

把整數的每個位數分開,像是把1998拆成{1, 9, 9, 8}接著存入陣列中。 這個簡單,只要一直除10就好。 因為羅馬數字是從大的開始書寫,所以逆向處理陣列(e.g. 1->9->9->8變成8->9->9->1),
轉換結果會有幾種:
  • 9: 10-1
  • 6~8: 5+(1~3)
  • 5: 5
  • 4: 5-1
  • 0~3: 0~3
陣列的索引(index,中文是叫做索引嗎我忘了)也代表了位數(個十百千),索引的值*2可以對應到num,個位數索引是0,對應到num的I(1), 0+1=1對應到num的V(5),0+2對應到num的X(10), 十位數索引是1,乘二=2,對應到num的X(10),2+1=3對應到num的L(50)…以此類推。

程式碼如下:

  1. /* a013:羅馬數字
  2. *
  3. * 2020/2/27
  4. *
  5. */
  6.  
  7. import java.util.Scanner;
  8.  
  9. public class Pa013{
  10.  
  11. static String roman = "IVXLCDM";
  12. static int[] num = {1, 5, 10, 50, 100, 500, 1000};
  13.  
  14. public static void main(String [] args){
  15. Scanner scanner = new Scanner(System.in);
  16.  
  17. while(scanner.hasNext()){
  18. String word = scanner.next();
  19. if(word.equals("#")) return;
  20. int a = romanToInt(word);
  21. int b = romanToInt(scanner.next());
  22. System.out.println(intToRoman(Math.abs(a - b)));
  23. }
  24. }
  25.  
  26. public static int romanToInt(String s){
  27. s += "I";
  28. int result = 0;
  29.  
  30. for(int i = 1; i < s.length(); i++){
  31. int current = num[roman.indexOf(s.charAt(i - 1))];
  32. int next = num[roman.indexOf(s.charAt(i))];
  33.  
  34. if(current >= next){
  35. result += current;
  36. }else{
  37. i++;
  38. result += next - current;
  39. }
  40. }
  41. return result;
  42. }
  43.  
  44. public static String intToRoman(int val){
  45. if(val == 0) return "ZERO";
  46.  
  47. int[] nums = new int[(int)Math.log10(val) + 1];
  48. String result = "";
  49.  
  50. for(int i = 0; i < nums.length; i++){
  51. nums[i] = val % 10;
  52. val /= 10;
  53. }
  54.  
  55. for(int i = nums.length - 1; i >= 0; i--){
  56. if(nums[i] == 9){
  57. result += roman.charAt(i * 2);
  58. result += roman.charAt(i * 2 + 2);
  59. }else if(nums[i] >= 5){
  60. result += roman.charAt(i * 2 + 1);
  61. for(int j = 0; j < nums[i] - 5; j++){
  62. result += roman.charAt(i * 2);
  63. }
  64. }else if(nums[i] == 4){
  65. result += roman.charAt(i * 2);
  66. result += roman.charAt(i * 2 + 1);
  67. }else{
  68. for(int j = 0; j < nums[i]; j++){
  69. result += roman.charAt(i * 2);
  70. }
  71. }
  72. }
  73.  
  74. return result;
  75. }
  76. }

沒有留言:

張貼留言