Надеюсь, все знакомы с этой задачей, но если нет, то можно прочитать статью для контекста и попробовать себя на литкоде (задача уровня easy).
В феврале этого года я создал репозиторий fizz-buzz-world, который оформил так, чтобы в него можно было легко контрибьютить: написал несколько своих решений, добавил простых тестов на логику и организовал понятный ридми-файл с призывом добавлять свои реализации классической задачи.
Цель была простая - собирать нетривиальные решения Fizz Buzz на Go.
Решаем без ифов
Например, вот несколько моих решений без единого if’а:
|
|
А вот еще одно:
|
|
Очевидно, что на собеседовании лучше обойтись классическим вариантом, чтобы не пугать интервьюера (ведь ему это еще проверять).
Счастливое число
На прошлой неделе репозиторий fizz-buzz-world обогатился новым решением.
Хочу выразить признательность автору: пул-реквест был отлично оформлен и задокументирован, а предлагаемое решение крайне неочевидное и очень интересное. Подробнее читайте в ридми от него.
В основе реализации лежит “счастливое число” (не путать с числом из теории чисел), которое подсчитано для данной задачи, и в Go версии 1.23.2 оно равно: 176064004
Зная его, решение выглядит следующим образом:
|
|
Раскрываем магию
Чтобы реализовать подобное решение, в первую очередь, нам важно иметь возможность создавать генератор псевдослучайных чисел.
На помощь приходит random seed, который обозначает число, на основании которого генератор всегда производит одну и ту же пвсевдослучайную последовательность.
В Go есть функция rand.NewSource. С ней мы можем задать нужный нам “seed”. Это и будет нашим “счастливым числом”.
Основной задачей становится поиск такого числа. Полная реализация доступна здесь, мы лишь рассмотрим одну функцию, из которой станет понятна идея дальнейшего решения:
|
|
“yep” - массив, который содержит правильные индексы ответов первых 15 итераций. Если по указанному индексу выбрать строку из массива возможных вариантов: {"", Fizz, Buzz, FizzBuzz}, то мы получим корректное значение на выбранном шаге, а именно:
|
|
То есть нам нужно подобрать такое число, при котором на каждой итерации для первых 15 элементов мы “случайно” будем получать правильный ответ, а вернее индекс, по которому сможет найти ответ.
Когда нужное число подобрано, то нам остается лишь записать ответ для этих итераций, а затем повторно сгенерировать “произвольную” последовательность, которая фактически ее продублирует, а мы повторим данную историю еще столько раз, сколько нам потребуется.
Реинициализируем рандомайзер с заданным сидом каждые 15 итераций (внимание на “if i%15 == 1”):
|
|
Такой вот интересный подход к решению задачи. Конечно, выглядит как некий хак, но правильный ответ мы получаем, хоть и нетривиально.
Поделитесь своим решением
Если у вас есть интересные идеи как еще можно решить Fizz Buzz, то предлагаю контрибьютить.
Пишите на других языках, но знаете оригинальный метод решения? Создавайте issue - будем переводить ваше решение на Go и собирать самые безумные решения этой задачи вместе ;)
Читайте оригинальный пост и присоединяйтесь к обсуждению в Телеграм: @time2code