dtonhofer

dtonhofer

Functional Programming in Java, Second Edition: p.135 code for "primes" using a self-modifying filter

This is no particular interest but here is some code that uses the “execute around” pattern to build a timer to time the “primes generator”, as well as a second primes generator that uses a self-modifying stream filter, a closure that accumulates all the primes found so far so as to perform divisibility testing, which is evidently faster than the “try to divide by every x between 2 and sqrt(n)”.

import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;
import static org.junit.jupiter.api.Assertions.assertEquals;

class SimpleTimer {

    public final long duration_ms;
    public final List<Integer> result;

    private SimpleTimer(List<Integer> result, long duration_ms) {
        this.result = Collections.unmodifiableList(result);
        this.duration_ms = duration_ms;
    }

    public static SimpleTimer timeIt(Supplier<List<Integer>> supplier) {
        long start = System.currentTimeMillis();
        List<Integer> result = supplier.get();
        long stop = System.currentTimeMillis();
        return new SimpleTimer(result, stop - start);
    }

}

class Primes {

    public static boolean isPrime(final int number) {
        return number > 1 &&
                IntStream.rangeClosed(2, (int) Math.sqrt(number))
                        .noneMatch(divisor -> number % divisor == 0);
    }

    private static int primeAfter(final int number) {
        if (isPrime(number + 1)) {
            return number + 1;
        }
        return primeAfter(number + 1);
    }

    public static List<Integer> primes(final int fromNumber, final int count) {
        return Stream.iterate(primeAfter(fromNumber - 1), Primes::primeAfter)
                .limit(count)
                .collect(toList());
    }

}

class PrimesSieveNoDoubles {

    private enum What {found_divisor, surpassed_sqrt, possibly_prime}

    // This is actually a little bit *slower* than a version that computes sqrt(x)
    // to determine whether to stop instead of using integer division to check whether
    // the dividend has become smaller than the divisor.

    public static List<Integer> primes(int limit) {
        final var store = new LinkedList<Integer>();
        Predicate<Integer> p = x -> {
            What what = What.possibly_prime;
            Iterator<Integer> iter = store.iterator();
            while (what == What.possibly_prime && iter.hasNext()) {
                int somePrime = iter.next();
                // it is faster to compute remainder and divisor next to one another always
                // than compute the divisor inside the "else", apparently due to compiler optimizations
                int remainder = x % somePrime;
                int dividend = x / somePrime;
                if (remainder == 0) {
                    // System.out.println(x + " = " + somePrime + "*n, not a prime");
                    what = What.found_divisor;
                } else {
                    // int divisor = x / somePrime;
                    if (dividend < somePrime) {
                        what = What.surpassed_sqrt;
                    }
                }
            }
            if (what == What.surpassed_sqrt || what == What.possibly_prime) {
                // System.out.println(x + " is prime");
                store.addLast(x);
                return true;
            } else {
                return false;
            }
        };
        List<Integer> result = Stream.iterate(2, x -> x + 1).
                filter(p).
                limit(limit).
                collect(toList());
        // add the end of the collect, the result and the store have the same content
        // this comparison takes a few ms
        assertEquals(store,result);
        return result;
    }

}

public class Primality {

    private final static int limit = 1_000_000;

    @Test
    void runBookPrimes() {
        List<Integer> l1 = Primes.primes(1, 10);
        List<Integer> l2 = Primes.primes(100, 5);
        assertEquals(List.of(2, 3, 5, 7, 11, 13, 17, 19, 23, 29),l1);
        assertEquals(List.of(101, 103, 107, 109, 113),l2);
        System.out.println("10 primes from 1: " + l1);
        System.out.println("5 primes from 100: " + l2);
    }

    @Test
    void runBookPrimesWithTimer() {
        // not an actual test, just printout
        final SimpleTimer timeIt = SimpleTimer.timeIt(() -> Primes.primes(2, limit));
        final List<Integer> result = timeIt.result;
        final String range = (result.isEmpty()) ? "" : "in range [" + result.get(0) + "," + result.get(result.size() - 1) + "] ";
        System.out.println("Using book code: finding " + result.size() + " primes " + range + "took " + timeIt.duration_ms + " ms");
    }

    @Test
    void runPrimesSieveWithTimer() {
        // not an actual test, just printout
        final SimpleTimer timeIt = SimpleTimer.timeIt(() -> PrimesSieveNoDoubles.primes(limit));
        final List<Integer> result = timeIt.result;
        final String range = (result.isEmpty()) ? "" : "in range [" + result.get(0) + "," + result.get(result.size() - 1) + "] ";
        System.out.println("Using primes sieve w/o doubles: finding " + result.size() + " primes " + range + "took " + timeIt.duration_ms + " ms");
    }
}

Where Next?

Popular Pragmatic Bookshelf topics Top

jimschubert
In Chapter 3, the source for index introduces Config on page 31, followed by more code including tests; Config isn’t introduced until pag...
New
herminiotorres
Hi @Margaret , On page VII the book tells us the example and snippets will be all using Elixir version 1.11 But on page 3 almost the en...
New
New
brunogirin
When trying to run tox in parallel as explained on page 151, I got the following error: tox: error: argument -p/–parallel: expected one...
New
Henrai
Hi, I’m working on the Chapter 8 of the book. After I add add the point_offset, I’m still able to see acne: In the image above, I re...
New
a.zampa
@mfazio23 I’m following the indications of the book and arriver ad chapter 10, but the app cannot be compiled due to an error in the Bas...
New
ggerico
I got this error when executing the plot files on macOS Ventura 13.0.1 with Python 3.10.8 and matplotlib 3.6.1: programming_ML/code/03_...
New
SlowburnAZ
Getting an error when installing the dependencies at the start of this chapter: could not compile dependency :exla, "mix compile" failed...
New
dachristenson
I just bought this book to learn about Android development, and I’m already running into a major issue in Ch. 1, p. 20: “Update activity...
New
roadbike
From page 13: On Python 3.7, you can install the libraries with pip by running these commands inside a Python venv using Visual Studio ...
New

Other popular topics Top

PragmaticBookshelf
Stop developing web apps with yesterday’s tools. Today, developers are increasingly adopting Clojure as a web-development platform. See f...
New
DevotionGeo
I know that these benchmarks might not be the exact picture of real-world scenario, but still I expect a Rust web framework performing a ...
New
brentjanderson
Bought the Moonlander mechanical keyboard. Cherry Brown MX switches. Arms and wrists have been hurting enough that it’s time I did someth...
New
DevotionGeo
I know that -t flag is used along with -i flag for getting an interactive shell. But I cannot digest what the man page for docker run com...
New
New
AstonJ
Just done a fresh install of macOS Big Sur and on installing Erlang I am getting: asdf install erlang 23.1.2 Configure failed. checking ...
New
PragmaticBookshelf
Rails 7 completely redefines what it means to produce fantastic user experiences and provides a way to achieve all the benefits of single...
New
PragmaticBookshelf
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
PragmaticBookshelf
Author Spotlight Mike Riley @mriley This month, we turn the spotlight on Mike Riley, author of Portable Python Projects. Mike’s book ...
New
Fl4m3Ph03n1x
Background Lately I am in a quest to find a good quality TTS ai generation tool to run locally in order to create audio for some videos I...
New

Latest in Functional Programming in Java, Second Edition

Functional Programming in Java, Second Edition Portal

Sub Categories: