Source code for tryalgo.roman_numbers

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""\
Evaluate an arithmetic expression

jill-jênn vie et christoph dürr - 2014-2019
"""

# convert roman numbers
# pylint: disable=bad-whitespace
roman = [['', 'I', 'II', 'III', 'IV',  'V',   'VI',  'VII', 'VIII', 'IX'],
         ['', 'X', 'XX', 'XXX', 'XL',  'L',   'LX',  'LXX', 'LXXX', 'XC'],
         ['', 'C', 'CC', 'CCC', 'CD',  'D',   'DC',  'DCC', 'DCCC', 'CM'],
         ['', 'M', 'MM', 'M'*3, 'M'*4, 'M'*5, 'M'*6, 'M'*7, 'M'*8,  'M'*9]]


[docs] def roman2int(s): """Decode roman number :param s: string representing a roman number between 1 and 9999 :returns: the decoded roman number :complexity: linear (if that makes sense for constant bounded input size) """ val = 0 pos10 = 1000 beg = 0 for pos in range(3, -1, -1): for digit in range(9, -1, -1): r = roman[pos][digit] if s.startswith(r, beg): # footnote 1 beg += len(r) val += digit * pos10 break pos10 //= 10 return val
# footnote 1: # in C one would write # # if (strncmp(s + beg, r, strlen(r)) == 0) # # in C++ the starts_with method does not allow a selection # of a substring in s, where the search should start. # so you need to write your own function, something like: # # bool starts_with(const string &s, const string &r, int beg) { # for (int i = 0; i < r.size(); i++) { # if (s[i + beg] != r[i]) # return false; # } # return true; # }
[docs] def int2roman(val): """Code roman number :param val: integer between 1 and 9999 :returns: the corresponding roman number :complexity: linear (if that makes sense for constant bounded input size) """ s = '' pos10 = 1000 for pos in range(3, -1, -1): digit = val // pos10 s += roman[pos][digit] val %= pos10 pos10 //= 10 return s