Someone else had some code in some other language that was something like the following couple of cells.


In [1]:
roman_letter_values = (
    ('I', 1),
    ('V', 5),
    ('X', 10),
    ('L', 50),
    ('C', 100),
    ('D', 500),
    ('M', 1000),
)

In [2]:
for i, (letter, value) in enumerate(roman_letter_values):
    if i % 2 == 1:
        print(i, letter, value)


1 V 5
3 L 50
5 D 500

I know what the code above means, but I have to think about it. It was hard to understand, because the test above as repeated below, is so indirect.

if i % 2 == 1:

Compare that with the directness of the following test from cell #12.

if significant_digits(value) == 5:

In [3]:
def prime_factors(x):
    divisor = 2
    while divisor < x:
        if x % divisor == 0:
            yield divisor
            x //= divisor
            continue
        divisor += 1
    yield x

In [4]:
for letter, value in roman_letter_values:
    print(letter, value, list(prime_factors(value)))


I 1 [1]
V 5 [5]
X 10 [2, 5]
L 50 [2, 5, 5]
C 100 [2, 2, 5, 5]
D 500 [2, 2, 5, 5, 5]
M 1000 [2, 2, 2, 5, 5, 5]

In [5]:
def significant_digits(x):
    return int(''.join(reversed(str(x))))

In [6]:
def foo():
    for letter, value in roman_letter_values:
        print(letter, value, significant_digits(value))

In [7]:
foo()


I 1 1
V 5 5
X 10 1
L 50 5
C 100 1
D 500 5
M 1000 1

In [8]:
def significant_digits(x):
    return int(str(x).rstrip('0'))

In [9]:
foo()


I 1 1
V 5 5
X 10 1
L 50 5
C 100 1
D 500 5
M 1000 1

In [10]:
def significant_digits(x):
    while x % 10 == 0:
        x //= 10
    return x

In [11]:
foo()


I 1 1
V 5 5
X 10 1
L 50 5
C 100 1
D 500 5
M 1000 1

In [12]:
for letter, value in roman_letter_values:
    if significant_digits(value) == 5:
        print(letter, value)


V 5
L 50
D 500

Of the three different implementations of significant_digits() above, which do you like the most? Which do you dislike the most? How would you write significant_digits()?