← Назад к вопросам
FizzBuzz
1.0 Junior🔥 151 комментариев
#Алгоритмы и структуры данных#Архитектура и паттерны
Условие
Напишите программу, которая выводит числа от 1 до 100. При этом:
- Вместо чисел, кратных 3, выводите "Fizz"
- Вместо чисел, кратных 5, выводите "Buzz"
- Вместо чисел, кратных и 3, и 5, выводите "FizzBuzz"
Пример вывода
1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16...
Дополнительные требования
- Сделать функцию, которая принимает число и возвращает результат
- Написать unit-тесты
- Сделать решение расширяемым (добавить другие делители)
Варианты реализации
- Классический if-else
- Через массив правил
- Через паттерн Strategy
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
FizzBuzz: Полное решение с расширяемостью
Решение 1: Классический if-else
function fizzBuzz(int $number): string
{
if ($number % 15 === 0) {
return 'FizzBuzz';
}
if ($number % 3 === 0) {
return 'Fizz';
}
if ($number % 5 === 0) {
return 'Buzz';
}
return (string)$number;
}
function printFizzBuzz(int $limit = 100): void
{
$result = [];
for ($i = 1; $i <= $limit; $i++) {
$result[] = fizzBuzz($i);
}
echo implode(', ', $result);
}
printFizzBuzz(100);
Проблема: Не расширяемо. Если добавить новое правило, нужно переписывать функцию.
Решение 2: Массив правил (рекомендуется)
class Rule
{
public function __construct(
private int $divisor,
private string $output
) {}
public function apply(int $number): ?string
{
return $number % $this->divisor === 0 ? $this->output : null;
}
}
class FizzBuzzGame
{
private array $rules = [];
public function __construct()
{
$this->addRule(new Rule(15, 'FizzBuzz'));
$this->addRule(new Rule(3, 'Fizz'));
$this->addRule(new Rule(5, 'Buzz'));
}
public function addRule(Rule $rule): self
{
$this->rules[] = $rule;
return $this;
}
public function evaluate(int $number): string
{
foreach ($this->rules as $rule) {
$result = $rule->apply($number);
if ($result !== null) {
return $result;
}
}
return (string)$number;
}
public function play(int $limit = 100): string
{
$results = [];
for ($i = 1; $i <= $limit; $i++) {
$results[] = $this->evaluate($i);
}
return implode(', ', $results);
}
}
$game = new FizzBuzzGame();
echo $game->play(100);
$game->addRule(new Rule(7, 'Whizz'));
Преимущества:
- Легко добавлять новые правила
- Легко тестировать отдельные правила
- Удовлетворяет принципу Open/Closed
Решение 3: Паттерн Strategy
interface FizzBuzzStrategy
{
public function evaluate(int $number): ?string;
}
class DivisibleStrategy implements FizzBuzzStrategy
{
public function __construct(
private int $divisor,
private string $output
) {}
public function evaluate(int $number): ?string
{
return $number % $this->divisor === 0 ? $this->output : null;
}
}
class DigitContainsStrategy implements FizzBuzzStrategy
{
public function __construct(
private string $digit,
private string $output
) {}
public function evaluate(int $number): ?string
{
return str_contains((string)$number, $this->digit) ? $this->output : null;
}
}
class FizzBuzzProcessor
{
private array $strategies = [];
public function addStrategy(FizzBuzzStrategy $strategy): self
{
$this->strategies[] = $strategy;
return $this;
}
public function process(int $number): string
{
$results = [];
foreach ($this->strategies as $strategy) {
$result = $strategy->evaluate($number);
if ($result !== null) {
$results[] = $result;
}
}
return !empty($results) ? implode('', $results) : (string)$number;
}
public function playGame(int $limit = 100): string
{
$output = [];
for ($i = 1; $i <= $limit; $i++) {
$output[] = $this->process($i);
}
return implode(', ', $output);
}
}
$processor = new FizzBuzzProcessor();
$processor->addStrategy(new DivisibleStrategy(3, 'Fizz'))
->addStrategy(new DivisibleStrategy(5, 'Buzz'))
->addStrategy(new DivisibleStrategy(7, 'Whizz'));
echo $processor->playGame(100);
Преимущества Strategy:
- Максимальная гибкость
- Легко создавать новые стратегии
- Можно комбинировать стратегии для одного числа
Unit-тесты
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class FizzBuzzTest extends TestCase
{
private FizzBuzzGame $game;
protected function setUp(): void
{
$this->game = new FizzBuzzGame();
}
public function testReturnNumberIfNotDivisible(): void
{
$this->assertEquals('1', $this->game->evaluate(1));
$this->assertEquals('2', $this->game->evaluate(2));
$this->assertEquals('4', $this->game->evaluate(4));
}
public function testReturnFizzForDivisibleBy3(): void
{
$this->assertEquals('Fizz', $this->game->evaluate(3));
$this->assertEquals('Fizz', $this->game->evaluate(6));
$this->assertEquals('Fizz', $this->game->evaluate(9));
}
public function testReturnBuzzForDivisibleBy5(): void
{
$this->assertEquals('Buzz', $this->game->evaluate(5));
$this->assertEquals('Buzz', $this->game->evaluate(10));
$this->assertEquals('Buzz', $this->game->evaluate(20));
}
public function testReturnFizzBuzzForDivisibleBy15(): void
{
$this->assertEquals('FizzBuzz', $this->game->evaluate(15));
$this->assertEquals('FizzBuzz', $this->game->evaluate(30));
$this->assertEquals('FizzBuzz', $this->game->evaluate(45));
}
public function testPlayGeneratesCorrectSequence(): void
{
$expected = '1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz';
$result = $this->game->play(15);
$this->assertEquals($expected, $result);
}
public function testAddingCustomRule(): void
{
$this->game->addRule(new Rule(7, 'Whizz'));
$this->assertEquals('Whizz', $this->game->evaluate(7));
$this->assertEquals('Whizz', $this->game->evaluate(14));
}
}
Сравнение подходов
| Критерий | if-else | Массив правил | Strategy |
|---|---|---|---|
| Простота | ✓✓✓ | ✓✓ | ✓ |
| Расширяемость | ✗ | ✓✓✓ | ✓✓✓ |
| Тестируемость | ✓ | ✓✓✓ | ✓✓✓ |
| Гибкость | ✗ | ✓✓ | ✓✓✓ |
| Производительность | ✓✓✓ | ✓✓ | ✓ |
Рекомендация
Для интервью используй Решение 2 (Массив правил) потому что:
- Демонстрирует понимание SOLID принципов
- Легко объяснить и реализовать
- Достаточно гибко для расширения
- Хороший баланс между простотой и функциональностью
Итоговый результат
1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, FizzBuzz...
Заключение: FizzBuzz демонстрирует знание принципов чистого кода, расширяемости и тестирования.