1
\$\begingroup\$

I've been tasked with finding the distance between two letters in the alphabet. Below is my solution. My main concerns are if there is any shorter way to do this, and if there are any edge cases I'm not. Thanks!

import string

LETTERS = string.ascii_lowercase

def shortest_distance_between_letters(a: str, b: str) -> int:
    """
    Returns the shortest distance between letters. This include wrapping
    around the letters. See below examples for clarification.

    >>> call('a', 'c')
    2 # 'a' -> 'b' -> 'c'
    >>> call('b', 'x')
    4 # 'b' -> 'a' -> 'z' -> 'y' -> 'x'
    """
    if a == b:
        return 0
    first = a if ord(a) < ord(b) else b
    second = b if ord(b) > ord(a) else a
    return min(
        LETTERS.index(second) - LETTERS.index(first),
        (len(LETTERS) - LETTERS.index(second)) + LETTERS.index(first)
    )
\$\endgroup\$

2 Answers 2

7
\$\begingroup\$

You don't need list.index(). Just compute the difference between the two ord() values.

You don't need to worry about first or second. Just find the absolute difference and then do some arithmetic to handle the wrap-around.

Next steps: handle invalid inputs. Depending on your use case you might want to raise a ValueError if the inputs are not in LETTERS. If you do this, don't rely on assert, for reasons detailed here.

import string

LETTERS = string.ascii_lowercase
N_LETTERS = len(LETTERS)

def shortest_distance_between_letters(a, b):
    diff = abs(ord(a) - ord(b))
    return min(diff, N_LETTERS - diff)
\$\endgroup\$
4
\$\begingroup\$

I think there are some things that become easier, if you directly transform to the indices and use Modular arithmetic.

If you look at the definition of modulo % (in python) then you do not need the sorting of smaller and larger.

def shortest_distance_between_letters(a, b):
    assert a in LETTERS and b in LETTERS
    ia, ib, L = LETTERS.index(a), LETTERS.index(b), len(LETTERS)
    D = (ib - ia) % L
    return D if D <= L // 2 else L - D

This has the advantage that you do not need to special case for a == b and requires less statements.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.