Как посчитать количество конечных нулей в целом числе, используя Java 8 Stream / Lambda? - PullRequest
0 голосов
/ 29 января 2019

Как посчитать количество конечных нулей в целом числе, используя Java 8 Stream / Lambda?

По сути, логика должна быть следующей: сохранить целое число, деленное на 10, пока остаток равен 0 (частное будет подано в следующее деление) и подсчитать вхождение (я).

например

12300 % 10 == 0 true

1230 % 10 == 0 true

123 % 10 == 0 false

Ответ: 2

Примечание: Я предпочитаю не включать строку: -)

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Вот еще один способ: -

private static int countTrailingZeroes(int n) {
    int length = n == 0 ? 1 : (int) (Math.log10(n) + 1); //number of digits in n
    return IntStream.rangeClosed(0, length)
            .map(i -> length - i)           //reverse stream
            .map(o -> (int) Math.pow(10, o))
            .filter(o -> n % o == 0)
            .boxed()
            .findFirst()
            .map(i -> (int) Math.log10(i))  //number of digits minus 1
            .orElse(0);
}

@ Правка Хольгера:

private static int countTrailingZeroes(int n) {
    int length = n == 0 ? 1 : (int) (Math.log10(n) + 1); //number of digits in n
    return IntStream.rangeClosed(0, length)
            .map(i -> length - i)           //reverse stream
            .filter(o -> n % (int) Math.pow(10, o) == 0)
            .findFirst()
            .orElse(0);
}
0 голосов
/ 30 января 2019

Учитывая, что у вас нет Java9 метода takeWhile, это также может помочь:

static final int[] POWERS_OF_10 = { 1000000000, 100000000, 10000000,
        1000000, 100000, 10000, 1000, 100, 10 };

static int trailingZeros(int number) {
    return Arrays.stream(POWERS_OF_10)      // reversed stream of of 10^n
                 .map(pow -> number % pow)  // stream of rests
                 .reduce(0, (count, rest) -> (rest == 0) ? count + 1 : 0);
}
0 голосов
/ 29 января 2019

Если это чисто гипотетический вопрос, вот чисто гипотетический ответ о том, как вы можете это сделать:

static int countZeroes(int value) {
    if(value == 0) // we need to handle this case explicitly
        return 1; 
    IntStream s = IntStream.iterate(value, v -> v / 10);
    return (int) takeWhile(s, v -> v > 0 && v % 10 == 0)
            .count();

}

Он использует вспомогательную функцию takeWhile, которая доступна в Java 9, но не вJava 8 так должна эмулироваться следующим образом:

// In Java 9 there is a standard takeWhile
// https://docs.oracle.com/javase/9/docs/api/java/util/stream/Stream.html#takeWhile-java.util.function.Predicate-
// but in Java 8 I have to emulate it
static IntStream takeWhile(IntStream s, final IntPredicate pr) {
    final Spliterator.OfInt origSp = s.spliterator();

    Spliterator.OfInt filtered = new Spliterators.AbstractIntSpliterator(origSp.estimateSize(), 0) {
        boolean lastPredicate = true;

        @Override
        public boolean tryAdvance(final IntConsumer action) {
            if (!lastPredicate)
                return false;

            origSp.tryAdvance((int v) -> {
                lastPredicate = pr.test(v);
                if (lastPredicate) {
                    action.accept(v);
                }
            });
            return lastPredicate;
        }
    };

    return StreamSupport.intStream(filtered, false);
}

Идея состоит в том, что

IntStream.iterate(value, v1 -> v1 / 10).takeWhile(v -> v > 0)

должен генерировать поток цифр вырезывания в конце один за другим, а затем вы можете применитьtakeWhile(v -> v % 10 == 0).count() для подсчета количества нулей и, наконец, вы можете объединить эти два takeWhile в один.

...