Главная | Все статьи | Дневник студента

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

Время чтения статьи ~6 минут
Статья написана студентом Хекслета. Мнение автора может не совпадать с позицией редакции
Испытание «Копилка». Мои впечатления главное изображение

Предисловие:

На момент первого подхода к испытанию "Копилка" я находился в конце второго месяца обучения по профессии "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 можно составить код.

Как я шел к результату:

Забегая вперёд, скажу сразу, что мой код не то чтобы не оптимален, он действительно "кривой", "косой" и "убогий", но код работает и выдаёт ожидаемый и приемлемый результат. Теперь, собственно, как я шел к результату:

  1. В испытании рекомендуется использовать "встроенный инструмент — Counter". По началу было вообще не понятно, как его там использовать, так как ранее я не сталкивался с примерами его использования. В первом варианте кода (именно первый вариант кода и стал результирующим, но лишь потому, что его оказалось проще довести до ума) я решил обойтись без него. Сформировал как-то работающий код и отправил на проверку в систему. И не прошло… стал разбираться.

  2. Результат тестов свёлся к тому, что выводимая мною строка не соответствовала (не была равна) ожидаемой строке. Без подробностей. Просто моя строка не такая же, как ожидаемая. На этот момент я ещё не очень разбирался в том, на что ругается система проверки кода. Из того, что я сразу понял, это то, что в результатах теста отсутствуют символы "# =>", которые я вставил в графический вывод результата.

  3. Убрал лишние элементы графики, поставил в мой код тот же пример (тот же список), что и в тестах. Запустил. Внешне результат меня устраивал. Но тесты опять не прошел. Что-то в выводимой строке опять не было таким же, как в тестах. Решил отложить испытание до лучших времён.

  4. В каком-то из уроков или в каком-то испытании познакомился с инструментом " Counter" (где-то уже в курсе про словари), вспомнил про "Копилку". Снова перечитал задание и написал весьма красивый и лаконичный код, который выдавал графически приемлемый результат. Но код опять не прошел проверку. Снова отложил до лучших времён.

  5. Прошло еще некоторое время и перфекционист внутри меня не позволил мне просто оставить испытание "Копилка" не завершенным. Опять просмотрел обе версии кода и результаты проверки. Немного "поковырял" код и попытался "скормить" системе. Не получилось. Оба кода выводили практически одинаковый результат. Но дьявол кроется в деталях. При выполнении операции сравнения результатов двух моих программ я получил False. Это обстоятельство навело меня на мысль, что результат от проверяющей системы может быть не похожим ни на один из двух моих. Пошел копаться в тестах, благо это уже оказалось для меня не так сложно, как на втором месяце обучения. Вытащил из тестов строку, которой должен соответствовать вывод из программы. Сел разбираться.

  6. Написал коротенький код, который построчно (по группам из 17 символов, последним из которых должен быть перенос строки) сравнивает вывод каждой из программ и строку из тестов. Вот тут-то и полезла конкретика. Оказалось, что в моих строках было больше пробелов в последних символах строк. Проще говоря, тестовая строка делилась на подстроки из 17 символов (кроме последней), последним символом был перенос строки, в мои строки могли содержать и 18 символов в подстроках, что зависело от того, что было в предпоследней не пробельной группе символов подстроки. Мелочь, но важная.

  7. Проще всего оказалось поправить код самой первой программы, написанной почти два месяца назад. Просто "прикрутил костыли" для полного символьного соответствия ожидаемому результату.

for u in string_osn:
        u[5] = u[5][0]+u[5][1]
        string += list(u)

    stroka_0[5] = bar_char*2
И получилось! Система приняла код! Да, код не красив, но он работает!!!

Что я для себя понял после испытания:

  1. Исходные данные испытания не всегда будут подробными и исчерпывающими для написания кода.
  2. Внешне корректно работающий код не всегда по-настоящему корректен и соответствует ожиданиям.
  3. Если перед началом написания кода аккуратно описать выводимый этим кодом результат и граничные условия, будет гораздо проще оценивать результат на корректность.
  4. Даже ручное тестирование помогает довести работу кода до желаемого результата.
  5. То, что не решилось с первого раза, можно/нужно отложить на некоторое время и вернуться к решению с новыми знаниями и навыками.
  6. Не красивый, но правильно работающий код лучше, чем красивый и не работающий. Работающий код можно сделать красивым, красивый работающим не всегда.
  7. Добивается результата тот, кто не сдаётся и осмысленно повторяет попытки.

Мой код:

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='₽'))
Аватар пользователя Антон Тюрин
Антон Тюрин 18 января 2023
1
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка веб-приложений на Django
10 месяцев
с нуля
Старт 25 апреля
профессия
от 6 183 ₽ в месяц
Ручное тестирование веб-приложений
4 месяца
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка приложений на языке Java
10 месяцев
с нуля
Старт 25 апреля
профессия
от 5 025 ₽ в месяц
новый
Сбор, анализ и интерпретация данных
9 месяцев
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка веб-приложений на Laravel
10 месяцев
с нуля
Старт 25 апреля
профессия
от 5 840 ₽ в месяц
Создание веб-приложений со скоростью света
5 месяцев
c опытом
Старт 25 апреля
профессия
от 9 900 ₽ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка бэкенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 25 апреля
профессия
новый
Автоматизированное тестирование веб-приложений на JavaScript
8 месяцев
c опытом
в разработке
Старт 25 апреля
профессия
Верстка с использованием последних стандартов CSS
5 месяцев
с нуля
Старт в любое время