У меня нет большого опыта игры в Code Kata на Hackerrank, и я не фанат, который ищет хороший ранг на платформе Hackerrank. Но у меня есть время, чтобы решить одну проблему с Hackerrank.
Сегодня у меня есть интересный опыт по поиску достойного решения проблемы на Hackerrank. Сегодня я вижу эту ссылку https://www.hackerrank.com/contests/101hack48/challenges/walking-robots
И у меня есть мысль решить ее самостоятельно, я прочитал вопрос, вижу ввод и вывод, а также пример, и я собираюсь решить его, используя свои заметки.
Мне в голову не пришло ни одного решения. Я думаю, что этот вопрос - пустяковая проблема, нам не нужен какой-либо тип структуры данных и определенная алгоритмическая стратегия для ее решения.
И мне пришла в голову идея, почему бы не использовать TDD для решения такого рода проблем. Я помню, как дядя Боб однажды сказал: TDD - это создание вашего решения, которое вписывается в проблемные области. И я считаю, что TDD касается дизайна, формы и помогает мне понять проблему.
Я собираюсь установить pytest на свой виртуальный сервер и начать код с моего теста.
Первый тест называется дегенеративным тестом, если вы смотрели учебник по TDD от дяди Боба. Он всегда говорит: напишите самый простой тест и реализацию, когда сталкиваетесь с проблемой. Итак, я создаю тест под названием «test_when_there_is_just_one_robot». Что произойдет, если в одном роботе будет одна символьная инструкция? В самом деле, столкновения не произошло бы, если бы один-единственный робот двигался влево, вправо или оставался на своем месте.
def test_when_there_is_just_one_robot(): instruction = ‘r’ assert_walking_robot(instruction, 0)
После создания реализации и прохождения теста. Я перехожу на следующий уровень тестирования, чтобы масштабировать ввод. Я масштабирую входные данные в два раза больше, чем в предыдущем тесте, а именно:
def test_when_robot_walking_same_direction(): instruction = [‘rr’, ‘ll’, ‘dd’] expected = [0, 0, 0] for inst, exp in zip(instruction, expected): assert_walking_robot(inst, exp)
Я раздавил ввод в одном тестовом примере, потому что он представлял ту же цель. Чтобы проверить, не приведет ли другой тип инструкции робота к конфликту, если бы был такой же тип инструкции.
Хорошо, а что потом? Я думаю, следующая легкая часть - это создание простой комбинации, когда тип инструкции не вызовет коллизии.
def test_when_robot_is_not_crashing(): instruction = [‘ld’, ‘dr’, ‘lr’, ‘ll’, ‘rr’] for inst in instruction: assert_walking_robot(inst, 0)
Если робот идет слева, а второй робот остается на своем месте, столкновения не будет. И так далее. Я раздавил тестовый пример и собрал их в один тестовый пример.
Реализация просто должна убедиться, что тест пройден, я не думаю о каком-либо рефакторинге на этой фазе.
Далее, самый простой путь, который я мог сделать, - это масштабирование моего тестового примера. То есть, когда есть 3 робота, 2 идут вправо, а последний робот остается на своем месте. Будет столкновение с последним роботом.
def test_when_robot_is_crashing_with_stopped_robot_but_there_is_a_same_direction_robot_behind(): instruction = [‘rrd’, ‘rrrd’, ‘rrrrd’] expected = [2, 3, 4] for inst, exp in zip(instruction, expected): assert_walking_robot(inst, exp)
Извините за длинное название тестового примера, но я просто хочу масштабировать команду «rd» в более масштабный тестовый пример, «rrrd», «rrrrd».
следующий, это
def test_when_robot_is_crashing_when_there_is_random_robot_stay_on_position(): instruction = [‘rrdrr’, ‘rrrdrrr’, ‘rrrrdrrrr’, ‘drrrr’, ‘rrdrdrdr’] expected = [2, 3, 4, 0, 4] for inst, exp in zip(instruction, expected): assert_walking_robot(inst, exp)
Когда в середине инструкции есть случайно оставшийся робот. На этом этапе я мог получить образец для правильного и постоянного типа команды робота. Следующее, что мне нужно уточнить, - это левый тип команды.
То же самое и с правильным типом команды, здесь:
def test_when_robot_going_left_and_crash_the_stayed_robot(): instruction = [‘ld’, ‘lld’, ‘dl’, ‘dll’, ‘dlll’] expected = [0, 0, 1, 2, 3] for inst, exp in zip(instruction, expected): assert_walking_robot(inst, exp)
Потому что, когда робот находится слева от оставшегося робота, он столкнется n раз.
Далее мы должны объединить правого, левого и оставшегося робота в позиции. Что будет примерно так:
def test_combination_right_and_left_but_crashed_with_stayed_robot(): instruction = [‘rrdll’, ‘rrrdlll’, ‘rrdrdldll’] expected = [4, 6, 6] for inst, exp in zip(instruction, expected): assert_walking_robot(inst, exp)
Уф, я создал множество тестов, чтобы убедиться, что правый, левый и неподвижный робот станут одной интегрированной инструкцией.
Что дальше ? Есть одно условие, которое еще не рассмотрено, это условие, когда робот, идущий направо, и робот, идущий налево, сталкиваются.
def test_right_and_left_robot_are_crashed(): instruction = [‘rl’, ‘rrl’, ‘rrrl’, ‘rrrrl’, ‘rll’, ‘rlrl’, ‘rllrll’, ‘lrlrlr’] expected = [2, 3, 4, 5, 3, 4, 6, 4] for inst, exp in zip(instruction, expected): assert_walking_robot(inst, exp)
Супер хитрый пример, потому что когда дается команда «rl». Правая команда и левая команда вызывают столкновение, которое возвращает «2 точки столкновения». Используя аналогичный шаблон, я масштабирую свой тестовый пример, добавляя ‘r’ перед ‘l’. И добавление ‘l’ после ‘r’.
Наконец, я объединяю все тестовые примеры в один:
def test_combination_of_right_left_and_stayed_robots(): instruction = [‘rdl’, ‘rrdll’, ‘rldrl’] expected = [2, 4] for inst, exp in zip(instruction, expected): assert_walking_robot(inst, exp)
Когда комбинируется тип столкновения и также комбинируется весь тип команды.
def test_hackerrank(): instruction = [‘r’, ‘lrrl’, ‘rrrll’, ‘rrdlldrr’, ‘rrrdllrllrrl’] expected = [0, 3, 5, 4, 11] for inst, exp in zip(instruction, expected): assert_walking_robot(inst, exp)
Последний тестовый пример посвящен созданию теста hackerrank и вуаля!
Очень рад выполнить эту задачу с помощью данной техники (TDD), потому что я использую эту технику в офисе каждый день, выполняя офисную задачу.
И урок, который я усвоил сегодня:
- Использование TDD не так уж и плохо, когда вы сталкиваетесь с такой же проблемой, как эта, потому что это бросает вызов вашим ожиданиям и разрабатывает свое решение.
- В коде невозможно потерять смысл
- Вы можете настроить некоторые алгоритмы, которые хотите использовать, на основе тестового примера. Я дважды настраиваю свой алгоритм, потому что я застреваю в двух последних тестовых примерах, которые я был создан ранее.
- Вы можете без проблем провести рефакторинг своего кода.
Для ссылки на код ›› https://github.com/byanjati/hackerrank/blob/master/test_walking_robot.py