re: Challenge: find 'Kaprekar numbers' VIEW POST

Ok, here's a Java 8 version:

import java.util.function.IntPredicate;
import java.util.stream.IntStream;

public class FirstEightKaprekarNumbers {

public static void main(String... args) {

IntPredicate isKaprekar = i -> {
String square = String.valueOf(i*i);
String padded = (square.length() % 2 == 0) ? square : "0" + square;
int halfLen = padded.length() / 2;
int left = Integer.parseInt(padded.substring(0, halfLen));
int right = Integer.parseInt(padded.substring(halfLen));
return i == left + right;
};

IntStream.iterate(1, i -> i + 1).filter(isKaprekar).limit(8).forEach(System.out::println);
}
}

As Heiko points out, the solution was incorrect, because the split was always done in the middle of the string...

So, here's a (hopefully correct) Java 9 solution (Java 9 because I use takeWhile):

import java.util.function.IntPredicate;
import java.util.stream.IntStream;

public class FirstSixteenKaprekarNumbers {

public static void main(String... args) {

IntPredicate isKaprekar = i -> {
long square = i * i;
// first, generate a stream of possible 10-base divisors (if the left side is zero, we're done):
return IntStream.iterate(10, div -> div * 10).takeWhile(div -> square / div > 0)
// then, filter out zero right sides:
.filter(div -> square % div > 0)
// finally, see if the sum of the parts match the original number:
.anyMatch(div -> i == square / div + square % div);
};

IntStream.concat(IntStream.of(1), IntStream.iterate(2, i -> i + 1).filter(isKaprekar))
.limit(16)
.forEach(System.out::println);

// 1, 9, 45, 55, 99, 297, 703, 999, 2223, 2728, 4879, 4950, 5050, 5292, 7272, 7777
}
}

I chose to output the first 16 numbers so we can see the output includes numbers 4879 and 5292.

I really like to see your use of Streams and lambdas solving this problem. Nice occasion for me to learn a little bit more about them.

code of conduct - report abuse  