Доработка программы по поиску ближайшего нуля
Прохожу курсы по Python. Пишу программу по поиску ближайшего нуля.
Если кратко, то есть набор чисел: 4, 5, 0, 3, 2, 0, а должно на выходе быть 2, 1, 0, 1, 1, 0
Преподаватель порекомендовал для улучшения кода использовать некую "векторизацию циклов". Как рассчитать через эту векторизацию до первого нуля и от последнего я сделал, а вот как мне правильно (и по питоновски), сделать расчёт между нулями сделать не могу. Сделал кое как расчёт между нулями в правую сторону, но как рассчитать влево + как это все объединить? Ну и наверное min надо применить, но как?
def distance_counter(land_numbers):
zeros_numbers = [k for k, v in enumerate(land_numbers) if v == '0']
distances = [None] * len(land_numbers)
first = zeros_numbers[0]
last = zeros_numbers[-1]
# тут я застрял
for left, right in zip(zeros_numbers[:-1], zeros_numbers[1:]):
distances[left:] = [home - left for home in range(left, right)]
# считаем до первого 0
distances[:zeros_numbers[0]] = [first - home for home in range(zeros_numbers[0])]
# считаем от последнего 0
distances[zeros_numbers[-1]:] = [home - last for home in range(zeros_numbers[-1], len(land_numbers))]
return distances
if __name__ == '__main__':
#input()
numbers = '1 0 1 4 0 4 4 5 0 5 4 5'
land_numbers = numbers.split()
print(*distance_counter(land_numbers))
Думал сделать как-то так:
for left, right in zip(zeros_numbers[:-1], zeros_numbers[1:]):
distances[left:right:] = min([home - left for home in range(left, right)], [right - home for home in range(left, right)])
Но так минимальные значения не высчитываются. Да и выглядит как то криво все это (
Данная конструкция
for left, right in zip(zeros_numbers[:-1], zeros_numbers[1:]):
distances[left:right] = zip([right - home for home in range(left, right)], [home - left for home in range(left, right)])
возвращает
1 (3, 0) (2, 1) (1, 2) (4, 0) (3, 1) (2, 2) (1, 3) 0 1 2 3
вроде бы остается только выбрать минимальные, но min что-то не пашет (
В общем, сделал вот так:
distances[left:] = map(min, zip([right - home for home in range(left, right)], [home - left for home in range(left, right)]))
так работает, но тесты валятся по времени (те решение занимает много времени и не подходит)
Ответы (1 шт):
Не вижу ничего сложного. Генерируем возрастающий список на половину расстояния от 'left' до 'right' и вставляем его правее 'left'. Потом его переворачиваем и вставляем левее 'right'.
def distance_counter(land_numbers):
zeros_numbers = [k for k, v in enumerate(land_numbers) if v == '0']
distances = [0] * len(land_numbers)
# тут кто-то застрял
for left, right in zip(zeros_numbers, zeros_numbers[1:]):
fill = range(1, (right - left) // 2 + 1)
distances[left+1:left+1+len(fill)] = fill
distances[right-len(fill):right] = fill[::-1]
# считаем до первого 0
distances[:zeros_numbers[0]] = range(zeros_numbers[0], 0, -1)
# считаем от последнего 0
distances[zeros_numbers[-1]:] = range(len(land_numbers) - zeros_numbers[-1])
return distances