#python #optimization
#python #оптимизация
Вопрос:
Я решаю задачу по программированию для развлечения и для работы над своими навыками — некоторые из вас, возможно, помнят появление Code challenge в декабре прошлого года, я работаю над этим. У меня есть этот код как решение одной из проблем, которое работает, но бесполезно медленно.
inp = "1113122113"
def iterate(num):
pos = 0
new = ""
while pos < len(num):
counter = 0
d = num[pos]
for i in range(pos, len(num)):
if num[i] == d:
counter = 1
else:
break
new =str(counter)
new =str(d)
pos = counter
print len(new)
return new
for i in range (50):
inp = iterate(inp)
После 35-й итерации или около того доходит до того, что на каждую итерацию уходит несколько минут. Цель состоит в том, чтобы сгенерировать последовательность «посмотри и скажи» — так что 1 переходит в 11, затем 21, 1211, 111221, 3112211 и так далее. Мне нужно найти длину строки после 50-й итерации, но после 40 итераций она составляет 360154 символа, и мой код просто недостаточно оптимизирован для обработки строк такой длины за разумное время. Кто-нибудь может дать мне несколько советов?
Комментарии:
1. Вопросы об улучшении рабочего кода лучше подходят для проверки кода .
2. «некоторые из вас, возможно, помнят появление Code challenge в декабре прошлого года» — Извините, но я не знаю, не могли бы вы немного рассказать о том, в чем заключалась проблема? И, кстати, этот вопрос лучше подходит для проверки кода
3. Это не особенно важно, это сайт, который появился в прошлом году. Он все еще существует, поэтому я решил поработать над ним еще немного. Вы можете найти его по адресу adventofcode.com , это задача 10-го дня.
4. И спасибо за совет, я пойду спрошу о проверке кода
5. Мне не нравится этот вызов большого диапазона () в середине. Обычно я использую range для небольших циклов for , но у меня возникли проблемы с созданием действительно большого списка из range, когда мне это было не нужно.
Ответ №1:
Использование itertools.groupby
сделает это очень быстро.
from itertools import groupby
def next_say(s):
return ''.join(str(sum(1 for _ in g)) k for k, g in groupby(s))
def iterate(num):
"""Generator that yields the first num iterations"""
val = '1'
for i in range(num):
val = next_say(val)
yield val
https://docs.python.org/2/library/itertools.html#itertools.groupby
Комментарии:
1. вместо того, чтобы тратить место на ненужный список, вы можете получить тот же результат с
sum( 1 for _ in g )
помощью, также вам нужно преобразовать это в строку…2. @Copperfield Хорошие моменты, мне было интересно, как обойти этот
list
вызов.