// This program searches for the first five perfect numbers.  It uses
// a functional programming approach including a specification that
// the computation can be performed in parallel to speed it up.
 
import java.util.stream.*;

public class Perfect {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        IntStream.iterate(1, n -> n + 1)
            .parallel()
            .unordered()
            .filter(n -> n == sumDivisors(n))
            .limit(5)
            .forEach(System.out::println);
        double elapsed = (System.currentTimeMillis() - start)
                          / 1000.0;
        System.out.println();
        System.out.println("time = " + elapsed);
    }

    // pre: n >= 1
    // post: returns the sum of the proper divisors of n (i.e., not
    //       including n itself)
    public static int sumDivisors(int n) {
        int root = (int) Math.sqrt(n);
        int sum = IntStream.range(2, root + 1)
            .filter(x -> n % x == 0)
            .map(x -> x + n / x)
            .sum();
        if (n == root * root) {
            sum = sum - root;
        }
        return sum + 1;
    }
}
