Ошибка при итерации по списку Python
У вас на столе лежат камни, размещенные в ряд. Каждый из них может быть красным, зеленым или синим и представлен символом R, G или B соответственно. Помоги найти минимальное количество камней, которые он должен убрать со стола, чтобы после этого каждая пара лежащих рядом камней содержала камни разного цвета.
Вот код функции (выдает ошибку list index out of range, хотя указываю длинна списка -1):
def color_stones(stones: str):
spisok = []
len_spisok = len(spisok)
new_spisok = []
len_new_spisok = len(new_spisok)
for i in stones:
spisok.append(i)
for i in (0, len(spisok)-1):
if spisok[i+1] == spisok[i]:
new_spisok.append(spisok[i])
return len_new_spisok - len_spisok
print(color_stones("RRGB")) # == 1 # "R" убираем, остается "RGB"
print(color_stones("RRGGB")) # == 2 # "R" и "G" убираем, остается "RGB"
print(color_stones("RRRRGB")) # == 3 # "RRR" убираем, остается "RGB"
print(color_stones("RGBRGBRGGB")) # == 1 # "G" убираем, остается "RGBRGBRGB"
print(color_stones("RGGRGBBRGRR")) # == 3 # "G", "B" и "R" убираем, остается "RGRGBRGR"
print(color_stones("RRRRGGGGBBBB")) # == 9 # "RRR", "GGG" и "BBB" убираем, остается "RGB"
Ответы (1 шт):
Автор решения: Stanislav Volodarskiy
→ Ссылка
Первое впечатление:
def color_stones(stones: str):
spisok = []
len_spisok = len(spisok) # всегда ноль, перенести --
new_spisok = [] # |
len_new_spisok = len(new_spisok) # всегда ноль, перенести --+--
for i in stones: # | |
spisok.append(i) # | |
# <------------------------ |
for i in (0, len(spisok)-1): # пропущен range |
if spisok[i+1] == spisok[i]: # |
new_spisok.append(spisok[i]) # |
# <---------------------------
return len_new_spisok - len_spisok # не разница, а len_new_spisok
Рабочий код и новые замечания:
def color_stones(stones: str):
spisok = []
new_spisok = [] # используется только длина
for i in stones:
spisok.append(i) # совпадает со stones
len_spisok = len(spisok) # не используется
for i in range(0, len(spisok)-1): # ноль можно опустить
if spisok[i+1] == spisok[i]:
new_spisok.append(spisok[i])
len_new_spisok = len(new_spisok)
return len_new_spisok
Окончательный код:
def color_stones(stones: str):
len_new_spisok = 0
for i in range(len(stones) - 1):
if stones[i + 1] == stones[i]:
len_new_spisok += 1
return len_new_spisok
Явное использование индексов может при вести к ошибкам. Лучше без них:
def color_stones(stones: str):
it = iter(stones)
next(it, None)
c = 0
for a, b in zip(stones, it):
if a == b:
c += 1
return c
Да и счётчики явные тоже код не красят:
def color_stones(stones: str):
it = iter(stones)
next(it, None)
return sum(1 for a, b in zip(stones, it) if a == b)
# кто не боится приведений bool -> int пишут так:
# return sum(a == b for a, b in zip(stones, it))
Другой подход к решению задачи. Разберитесь сами как это работает - будет интересно:
import itertools
def color_stones(stones: str):
return len(stones) - sum(1 for _ in itertools.groupby(stones))