package fundamentals.string.convert.lc013_romantointeger;

import java.util.HashMap;
import java.util.Map;

/**
 * Given a roman numeral, convert it to an integer.
 * Input is guaranteed to be within the range from 1 to 3999.
 */
public class Solution {

    // 4AC
    public int romanToInt(String s) {
        Map<Character, Integer> r2i = new HashMap<>();
        r2i.put('I', 1);
        r2i.put('V', 5);
        r2i.put('X', 10);
        r2i.put('L', 50);
        r2i.put('C', 100);
        r2i.put('D', 500);
        r2i.put('M', 1000);

        int num = 0, n = s.length();
        for (int i = n - 1; i >= 0; i--) {
            if (i < n - 1 && r2i.get(s.charAt(i)) < r2i.get(s.charAt(i + 1)))
                num -= r2i.get(s.charAt(i));
            else num += r2i.get(s.charAt(i));
        }
        return num;
    }

    private static Map<Character,Integer> roman = new HashMap<>();

    static {
        roman.put('I', 1);
        roman.put('V', 5);
        roman.put('X', 10);
        roman.put('L', 50);
        roman.put('C', 100);
        roman.put('D', 500);
        roman.put('M', 1000);
    }

    // My 3AC: map is overkill, switch is adequate!
    public int romanToInt3(String s) {
        int prev = 0, num = 0;
        for (int i = s.length() - 1; i >= 0; i--) {
            int cur = r2i(s.charAt(i));
            num += (cur >= prev) ? cur : -cur;
            prev = cur;
        }
        return num;
    }

    private int r2i(char c) {
        switch (c) {
            case 'I': return 1;
            case 'V': return 5;
            case 'X': return 10;
            case 'L': return 50;
            case 'C': return 100;
            case 'D': return 500;
            case 'M': return 1000;
            default: return 0; // assume never happen
        }
    }

    // My 2AC: much easier to understand now!
    public int romanToInt2(String s) {
        Map<Character,Integer> map = new HashMap<>();
        map.put('I', 1);
        map.put('V', 5);
        map.put('X', 10);
        map.put('L', 50);
        map.put('C', 100);
        map.put('D', 500);
        map.put('M', 1000);

        // Subtract if less than prev, since IIV is impossible
        int prev = 0, num = 0;
        for (int i = s.length() - 1; i >= 0; i--) {
            int cur = map.get(s.charAt(i));
            num += (cur >= prev) ? cur : -cur;  // Nice -cur! Note >=
            prev = cur;
        }
        return num;
    }

    // My 1AC: bad dealing with cur and last
    public int romanToInt1(String s) {
        if (s.isEmpty()) {
            return 0;
        }

        int integer = roman.get(s.charAt(s.length() - 1));
        for (int i = s.length() - 2; i >= 0; i--) {
            int cur = roman.get(s.charAt(i));
            int last = roman.get(s.charAt(i + 1));
            integer = (cur >= last) ? (integer + cur) : (integer - cur); // error1: must >=, DCXXI=621 not 601
        }
        return integer;
    }

}

@@ -289,32 +289,67 @@
 Int(String s) %7B%0A
+        if (s.isEmpty()) return 0;%0A
         Map%3CChar
@@ -354,17 +354,16 @@
 aracter,
- 
 Integer%3E
@@ -588,29 +588,52 @@
 nt n
-um
  = 
-0
+s.length()
 , n
+um
  = 
-s.length(
+r2i.get(s.charAt(n - 1)
 );%0A 
@@ -656,17 +656,17 @@
 i = n - 
-1
+2
 ; i %3E= 0
@@ -694,21 +694,8 @@
 if (
-i %3C n - 1 && 
 r2i.
@@ -738,16 +738,18 @@
 i + 1)))
+ %7B
 %0A       
@@ -801,14 +801,34 @@
     
+ %7D
  else 
+%7B%0A                
 num 
@@ -844,32 +844,46 @@
 t(s.charAt(i));%0A
+            %7D%0A
         %7D%0A      

roman to integer