Испытание «Копилка». Мои впечатления

Предисловие:
На момент первого подхода к испытанию "Копилка" я находился в конце второго месяца обучения по профессии "Python-разработчик", и мой опыт использования языка Python лишь немного выходил за пределы этих двух месяцев. На момент успешного завершения испытания "Копилка" я находился в конце четвертого месяца обучения по профессии "Python-разработчик", и на мой взгляд мой опыт и навыки значительно подросли.
Описание испытания:
Испытание "Копилка" относится к курсу "Python: Списки" (https://ru.hexlet.io/courses/python-lists?utm_source=hexlet&utm_medium=blog&utm_campaign=all-courses&utm_content=ispytanie-kopilka-moi-vpechatleniya&utm_term=post_180123). На сегодняшний день (25.10.2022г.) испытание проходило 310 студентов, из которых 64% самостоятельно с ним справилось. Суть испытания в том, чтобы написать функцию, которая выводит результат обработки списка чисел в виде гистограммы с числовыми подписями. В задании приведено графическое представление результата с минимальным его описанием в виде текста, а также подсказка о том, через какой функционал языка Python можно составить код.
Как я шел к результату:
Забегая вперёд, скажу сразу, что мой код не то чтобы не оптимален, он действительно "кривой", "косой" и "убогий", но код работает и выдаёт ожидаемый и приемлемый результат. Теперь, собственно, как я шел к результату:
-
В испытании рекомендуется использовать "встроенный инструмент — Counter". По началу было вообще не понятно, как его там использовать, так как ранее я не сталкивался с примерами его использования. В первом варианте кода (именно первый вариант кода и стал результирующим, но лишь потому, что его оказалось проще довести до ума) я решил обойтись без него. Сформировал как-то работающий код и отправил на проверку в систему. И не прошло… стал разбираться.
-
Результат тестов свёлся к тому, что выводимая мною строка не соответствовала (не была равна) ожидаемой строке. Без подробностей. Просто моя строка не такая же, как ожидаемая. На этот момент я ещё не очень разбирался в том, на что ругается система проверки кода. Из того, что я сразу понял, это то, что в результатах теста отсутствуют символы "# =>", которые я вставил в графический вывод результата.
-
Убрал лишние элементы графики, поставил в мой код тот же пример (тот же список), что и в тестах. Запустил. Внешне результат меня устраивал. Но тесты опять не прошел. Что-то в выводимой строке опять не было таким же, как в тестах. Решил отложить испытание до лучших времён.
-
В каком-то из уроков или в каком-то испытании познакомился с инструментом " Counter" (где-то уже в курсе про словари), вспомнил про "Копилку". Снова перечитал задание и написал весьма красивый и лаконичный код, который выдавал графически приемлемый результат. Но код опять не прошел проверку. Снова отложил до лучших времён.
-
Прошло еще некоторое время и перфекционист внутри меня не позволил мне просто оставить испытание "Копилка" не завершенным. Опять просмотрел обе версии кода и результаты проверки. Немного "поковырял" код и попытался "скормить" системе. Не получилось. Оба кода выводили практически одинаковый результат. Но дьявол кроется в деталях. При выполнении операции сравнения результатов двух моих программ я получил False. Это обстоятельство навело меня на мысль, что результат от проверяющей системы может быть не похожим ни на один из двух моих. Пошел копаться в тестах, благо это уже оказалось для меня не так сложно, как на втором месяце обучения. Вытащил из тестов строку, которой должен соответствовать вывод из программы. Сел разбираться.
-
Написал коротенький код, который построчно (по группам из 17 символов, последним из которых должен быть перенос строки) сравнивает вывод каждой из программ и строку из тестов. Вот тут-то и полезла конкретика. Оказалось, что в моих строках было больше пробелов в последних символах строк. Проще говоря, тестовая строка делилась на подстроки из 17 символов (кроме последней), последним символом был перенос строки, в мои строки могли содержать и 18 символов в подстроках, что зависело от того, что было в предпоследней не пробельной группе символов подстроки. Мелочь, но важная.
-
Проще всего оказалось поправить код самой первой программы, написанной почти два месяца назад. Просто "прикрутил костыли" для полного символьного соответствия ожидаемому результату.
for u in string_osn:
u[5] = u[5][0]+u[5][1]
string += list(u)
stroka_0[5] = bar_char*2
И получилось! Система приняла код! Да, код не красив, но он работает!!!
Что я для себя понял после испытания:
- Исходные данные испытания не всегда будут подробными и исчерпывающими для написания кода.
- Внешне корректно работающий код не всегда по-настоящему корректен и соответствует ожиданиям.
- Если перед началом написания кода аккуратно описать выводимый этим кодом результат и граничные условия, будет гораздо проще оценивать результат на корректность.
- Даже ручное тестирование помогает довести работу кода до желаемого результата.
- То, что не решилось с первого раза, можно/нужно отложить на некоторое время и вернуться к решению с новыми знаниями и навыками.
- Не красивый, но правильно работающий код лучше, чем красивый и не работающий. Работающий код можно сделать красивым, красивый работающим не всегда.
- Добивается результата тот, кто не сдаётся и осмысленно повторяет попытки.
Мой код:
coins = (10,10,1,1,1,1,20,20,20,20,20,2,2,2,2,2,2,3,3,5,5)
def visualize(coins, bar_char='₽'):
unic_coin = sorted(set(coins))
k = []
for j in range(len(unic_coin)):
k.append([unic_coin[j], 0])
#print(k)
for a in range(len(unic_coin)):
for i in coins:
if unic_coin[a] == i:
k[a][1] += 1
counter = []
for b in range(len(unic_coin)):
counter.append(k[b][1])
counter_2 = []
for b in range(len(unic_coin)):
counter_2.append(k[b][1])
string = []
stroka_0 = ([bar_char*2 + ' ']*len(unic_coin) + ['\n']) # stroka_0 = ([bar_char*2 + ' ']*len(unic_coin) + ['\n'])
stroka_1 = (['--']*len(unic_coin) + ['-']*(len(unic_coin)-1) + ['\n']) # stroka_1 = (['--']*len(unic_coin) + ['-']*(len(unic_coin)-1) + ['\n'])
stroka_2 = list(unic_coin)
stroka_22 = []
for z in stroka_2:
if len(str(z)) == 1:
stroka_22 = stroka_22 + [str(z) + ' ']
else:
stroka_22 = stroka_22 + [str(z) + ' ']
stroka_22[-1] = stroka_22[-1][0:2]
#print(stroka_22[-1])
string_osn = []
for r in range(len(unic_coin)):
string_osn.append([' ']*(len(unic_coin)-1) + [' '] + ['\n']) # string_osn.append([' ']*(len(unic_coin)-1) + [' '] + ['\n'])
h = 0
maximum = []
max_z = 0
for j in range(len(unic_coin)):
if counter == []:
break
maximum = [i for i, v in enumerate(counter_2) if v == max(counter)]
if max(counter) + 1 < max_z:
h +=1
for p in maximum:
if len(str(counter_2[p])) == 1:
string_osn[h][p] = str(counter_2[p]) + ' '
elif len(str(counter_2[p])) == 2:
string_osn[h][p] = str(counter_2[p]) + ' '
for y in range(h+1, len(unic_coin)):
string_osn[y][p] = bar_char*2 + ' '
max_z = max(counter)
counter.remove(counter_2[p])
h +=1
#print(string_osn)
for u in string_osn:
u[5] = u[5][0]+u[5][1]
string += list(u)
stroka_0[5] = bar_char*2
Ss = ''.join(string) + ''.join(stroka_0) + ''.join(stroka_1) + ''.join(stroka_22)
#print(list(Ss))
#print(list(stroka_0))
return Ss
print(visualize(coins, bar_char='₽'))
Антон Тюрин
3 года назад