Как сделать перебор списка цифр (названий) и остановиться, если цифра совпадает с числом?

Есть список названий цифр:

nums = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]

Если n = 20 и я сделаю:

n = 20
n_list = []
for i in str(n):
    n_list.append(nums[int(i)])

То получу:

twozero

Далее, я получу seven, сделав:

nums[len("".join(n_list))]

В seven 5 букв, соответственно, дальше я получу five. В five 4 буквы, значит дальше я получу four. В four 4 буквы, значит я снова получу 4. На этом цикл заканчивается.

Я не понимаю как сделать так, чтобы это считалось в цикле

То есть конечный результат должен получиться такой:

['twozero', 'seven', 'five', 'four']

Ответы (2 шт):

Автор решения: Алексей Р
nums = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
n, out, digit = 20, [], None
x = ''.join(nums[int(i)] for i in str(n))  # стартовое значение X
while x != digit:  # цикл, пока x не равен digit
    out.append(x)  # добавляем очередной x в итоговый список
    digit, x = x, nums[len(x)]  # х сохраняем в digit, а новый х извлекаем из списка nums
print(out)
['twozero', 'seven', 'five', 'four']

В случае, если длина x будет превышать наибольший индекс списка nums (например, если задать n=100, то x будет onezerozero, а len(x)==11), возникнет ошибка IndexError: list index out of range. Здесь возможны как минимум варианты - а) добавить в список значений 'ten', 'eleven', 'twelve', ... или б) остановить вычисления, сообщив о такой ситуации.

Что интересно, все вычисления на протестированном диапазоне 0-100 (включительно) завершаются либо на four (~90%) либо ошибкой (~10%). Это и закономерно, поскольку среди рассмотренных цифр только у four кол-во символов равно самому числу:

def fun(n):
    nums = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]
    out, digit = [], None
    x = ''.join(nums[int(i)] for i in str(n))  # стартовое значение X
    while x != digit:  # цикл, пока x не равен digit
        out.append(x)  # добавляем очередной x в итоговый список
        pos = len(x)
        if pos > len(nums) - 1:
            return out + ['IndexError']
        digit, x = x, nums[pos]  # х сохраняем в digit, а новый х извлекаем из списка nums
    return out


stat = {}
for n in range(101):
    res = fun(n)
    if res[-1] in stat:
        stat[res[-1]] += 1
    else:
        stat[res[-1]] = 1
    print(res)
print(stat)
...
['ninefour', 'eight', 'five', 'four']
['ninefive', 'eight', 'five', 'four']
['ninesix', 'seven', 'five', 'four']
['nineseven', 'nine', 'four']
['nineeight', 'nine', 'four']
['ninenine', 'eight', 'five', 'four']
['onezerozero', 'IndexError']
{'four': 91, 'IndexError': 10}
→ Ссылка
Автор решения: Stanislav Volodarskiy

Выражение step = ''.join(nums[int(d)] for d in str(n)) превращает число n в строку из числительных. "Обратное" преобразование из строки в число: n = len(step). Повторяется всё в цикле, который прерывается по условию сохранения длины len(step) == n:

nums = [
    'zero', 'one', 'two', 'three', 'four',
    'five', 'six', 'seven', 'eight', 'nine'
]


def steps(n):
    steps = []
    while True:
        step = ''.join(nums[int(d)] for d in str(n))
        steps.append(step)
        if len(step) == n:
            return steps
        n = len(step)


print(steps(int(input())))
$ echo 20 | py temp.py
['twozero', 'seven', 'five', 'four']

$ echo 33 | py temp.py
['threethree', 'onezero', 'seven', 'five', 'four']
→ Ссылка