CHAR_TO_INT = [ ('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), ] def tests(): assert(numeral_to_integer("XXXXIIIIIIIII") == 49) assert(numeral_to_integer("XLIIIIIIIII") == 49) assert(numeral_to_integer("XXXXVIIII") == 49) assert(numeral_to_integer("XLVIIII") == 49) assert(numeral_to_integer("XXXXIX") == 49) assert("XLIX" == integer_to_numeral(49)) assert("MCMXXXVII" == integer_to_numeral(1937)) def integer_to_numeral(integer): i = 0 s = '' while integer > 0: char, value = CHAR_TO_INT[i] while integer >= value: s += char integer -= value i += 1 assert(integer == 0) return s def numeral_to_integer(numeral): i, r = 0, 0 while numeral and i < len(CHAR_TO_INT): char, value = CHAR_TO_INT[i] len_char = len(char) while len(numeral) >= len_char and numeral[:len_char] == char: r += value numeral = numeral[len_char:] i += 1 assert(not numeral) return r def save_characters(numeral): initial_chars = len(numeral) i = numeral_to_integer(numeral) new_numeral = integer_to_numeral(i) new_chars = len(new_numeral) return initial_chars - new_chars def euler_089(): tests() with open("../txt/e089.txt") as f: numerals = map(lambda l: l.strip(), f.readlines()) return sum(map(save_characters, numerals)) if __name__ == "__main__": solution = euler_089() print("e089.py: " + str(solution)) assert(solution == 743)