Короткая Java FizzBuzz с использованием рекурсии и параметров

public void fizzbuzz(int count, int max, String fizzer) {
    fizzer += (count % 3 == 0) ? "fizz":"";
    fizzer += (count % 5 == 0) ? "buzz":"";
    fizzer += (count % 3 != 0 && count % 5 != 0) ? count:"";
    if (count != max) {
        fizzer += "\n";
        fizzbuzz(count+1,max,fizzer);
    } else {
        System.out.println(fizzer);
    }
}

fizzbuzz(1,30,"");

Код выполняет fizzbuzz в диапазоне count до max. Внутри метода не инициализируются переменные.

Мне бы хотелось избавиться от max и вместо этого использовать только два аргумента для метода (String fizzer и int count), но как я могу? Я могу сделать это назад (т. Е. Работать до достижения тривиального случая count == 0, а затем остановиться), но есть ли способ перейти от ---- +: = 7 =: + ---- до 1 только с одним аргументом?

11 голосов | спросил gator 21 AMpMon, 21 Apr 2014 04:25:36 +040025Monday 2014, 04:25:36

2 ответа


4

Аспект «упражнения в письменной форме рекурсивный fizzbzz» уже был рассмотрен в других ответах. Есть проблемы с этим в Java (стековые фреймы), которые делают его менее идеальным вариантом для языка.

Другая проблема, которая возникает, - это String. Поскольку String является неизменным, каждый раз, когда он модифицируется, новый String.

From:

public void fizzbuzz(int count, int max, String fizzer) {
    fizzer += (count % 3 == 0) ? "fizz":"";
    fizzer += (count % 5 == 0) ? "buzz":"";
    fizzer += (count % 3 != 0 && count % 5 != 0) ? count:"";
    ...
}

Это создаст три новые строки, которые затем будут выброшены, когда будет создан новый. Кроме того, эта строка продолжает расти. При достаточно длинном fizzbuzz (или другом рекурсивном вызове) вы будете создавать и отбрасывать чрезмерное количество строк с увеличенной длиной.

Вместо использования неизменяемой строки (да, неизменность хорошая и один из идеалов функционального программирования), рассмотрите возможность работы с StringBuilder вместо:

public void fizzbuzz(int count, int max, StringBuilder fizzer) {
    fizzer.insert('\n');
    fizzer.insert(0, (count % 5 == 0) ? "buzz":"");
    fizzer.insert(0, (count % 3 == 0) ? "fizz":"");
    if (count % 3 != 0 && count % 5 != 0) {
        fizzer.insert(0, count);
        // insert(0, true ? 2 : "") has mixed types (int, String) - doesn't work
    }
    ...
}

Обратите внимание, что это приведет к низкой производительности из-за вызова O (N) .insert (он должен сдвинуть весь массив, который поддерживает StringBuilder). Во всем диапазоне это становится O (N 2 ). Глядя на код для вставки , однако это не будет страдать от избытка объектов (просто этот болезненный System.arraycopy)

Возможно, вы захотите использовать LinkedList, который позволяет O (1) вставлять и помещать каждый элемент в список, и иметь начальный вызов, затем ходить по списку и распечатывать все в правильном порядке.

В стороне, если вы хотите играть с рекурсивным FizzBuzz в среде Javaish, рассмотрите хороший подход Clojure или Scala, который будет играть немного лучше с рекурсией

ответил 21 PMpMon, 21 Apr 2014 22:18:10 +040018Monday 2014, 22:18:10
3

Дикое предложение, подсчитайте количество \n в вашем выпуске String и используйте это, чтобы определить, когда выходить из рекурсии!

Кроме того, я реализую fizzbuzz в одном if-else-if вместо трех тернарных операторов, основная причина в том, что мне не нужно добавлять пустой Strings. Это может быть только я, хотя.

ответил h.j.k. 21 AMpMon, 21 Apr 2014 05:15:28 +040015Monday 2014, 05:15:28

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132