const _romanMap = <String, int>{
  'T': 10000,
  'A': 5000,
  'P': 100000,
  'E': 100000, // not used but kept for completeness
  'M': 1000,
  'D': 500,
  'C': 100,
  'L': 50,
  'X': 10,
  'V': 5,
  'I': 1,
};

String intToRoman(int n) {
  final buffer = StringBuffer();
  void emit(int value, String numeral) {
    while (n >= value) {
      buffer.write(numeral);
      n -= value;
    }
  }

  emit(10000, 'T');
  if (n >= 9000) {
    buffer.write('MT');
    n -= 9000;
  }
  if (n >= 5000) {
    buffer.write('A');
    n -= 5000;
  }
  if (n >= 4000) {
    buffer.write('MA');
    n -= 4000;
  }

  emit(1000, 'M');
  _subtract(ref: n, target: 900, numeral: 'CM', buffer: buffer);
  _subtract(ref: n, target: 500, numeral: 'D', buffer: buffer);
  _subtract(ref: n, target: 400, numeral: 'CD', buffer: buffer);

  emit(100, 'C');
  _subtract(ref: n, target: 90, numeral: 'XC', buffer: buffer);
  _subtract(ref: n, target: 50, numeral: 'L', buffer: buffer);
  _subtract(ref: n, target: 40, numeral: 'XL', buffer: buffer);

  emit(10, 'X');
  _subtract(ref: n, target: 9, numeral: 'IX', buffer: buffer);
  _subtract(ref: n, target: 5, numeral: 'V', buffer: buffer);
  _subtract(ref: n, target: 4, numeral: 'IV', buffer: buffer);
  emit(1, 'I');
  return buffer.toString();
}

void _subtract({
  required int ref,
  required int target,
  required String numeral,
  required StringBuffer buffer,
}) {
  if (ref >= target) {
    buffer.write(numeral);
    ref -= target;
  }
}

int romanToInt(String n) {
  var result = 0;
  var i = 0;
  while (i < n.length) {
    final one = _romanMap[n[i]] ?? 0;
    final two = i + 1 < n.length ? _romanMap[n[i + 1]] ?? 0 : 0;
    if (two > one) {
      result += (two - one);
      i += 2;
    } else {
      result += one;
      i += 1;
    }
  }
  return result;
}
