3
\$\begingroup\$

Previous Question: Armstrong numbers in a given range using Java 8

Updated program for getting all Armstrong Numbers between 1 and 10_000_000 as per the suggestions in this answer.

public class ArmstrongNumbers {
 public static void main(String[] args) {
 IntStream.range(1, 10_000_000)
 .filter((n) -> {
 int size = Integer.toString(n).length();
 return Integer.toString(n)
 .chars()
 .map(d -> d - '0')
 .mapToDouble(v -> Math.pow(v, size))
 .sum() == n;
 }).forEach(System.out::println);
 }
}

Output:

1
2
3
4
5
6
7
8
9
153
370
371
407
1634
8208
9474
54748
92727
93084
548834
1741725
4210818
9800817
9926315

Comments:

  • Was able to replace the while loop with a stream.
  • Code isn't shorter but is more readable.

Can this program be made even shorter? Any other suggestions also welcome.

asked Jul 13, 2016 at 11:00
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Looking at the code for Integer.toString, it seems to be a lot of work to convert an integer to a string. At the moment, you're doing the conversion twice.

However, getting the length of a string, via String.length, is a simple getter. As such, you'd probably be better off with storing the string representation in a variable, and calling .length() on that.

public static void main(String[] args) {
 IntStream.range(1, 10_000_000)
 .filter((n) -> {
 final String number = Integer.toString(n);
 return number.chars()
 .map(d -> d - '0')
 .mapToDouble(v -> Math.pow(v, number.length()))
 .sum() == n;
 }).forEach(System.out::println);
}

Also, good job coming up with the idea of substracting '0' from each character to cast it back to a number: that's a far better idea than what I had in mind (using complicated parse functions).

You could, in theory, perform this step at .mapToDouble, via Math.pow((v - '0'), number.length()) but I'm not sure whether that helps the readability. It does make things a lot shorter, I guess.

A potential performance upgrade after this would be to consider storing the result of Math.pow in a lookup table; whenever you surpass the current digit length, multiply each value of the lookup table by its index and continue. Right now, this doesn't seem very relevant to me, but later, this might be an issue.

answered Jul 13, 2016 at 12:07
\$\endgroup\$
0
\$\begingroup\$

There's not much to improve, but there are a couple of minor inconsistencies:

 .filter((n) -> {
 .map(d -> d - '0')
 .mapToDouble(v -> Math.pow(v, size))

I would ditch the parentheses in the first lambda, as you have in the other two.


 }).forEach(System.out::println);

I would insert a newline before the ., as you have on the other chained method calls.

answered Jul 13, 2016 at 13:45
\$\endgroup\$
2
  • \$\begingroup\$ is this formatting intentional? It's kinda hard to read. \$\endgroup\$ Commented Jul 13, 2016 at 14:06
  • \$\begingroup\$ @Pimgd, it's just a combination of blockquote (because I'm quoting OP's code rather than writing anything new) and pre (because it's code). I don't find it hard to read, but maybe it's a matter of taste. You could always look into user stylesheets if you have an idea for how to make it look better. \$\endgroup\$ Commented Jul 13, 2016 at 14:55

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.