## The challenge

Consider the numbers `6969` and `9116`. When you rotate them `180 degrees` (upside down), these numbers remain the same. To clarify, if we write them down on a paper and turn the paper upside down, the numbers will be the same. Try it and see! Some numbers such as `2` or `5` don’t yield numbers when rotated.

Given a range, return the count of upside down numbers within that range. For example, `solve(0,10) = 3`, because there are only `3` upside down numbers `>= 0 and < 10`. They are `0, 1, 8`.

More examples in the test cases.

## The solution in Java code

Option 1 (using `IntStream`):

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 `````` ``````import java.util.stream.IntStream; import org.apache.commons.lang3.StringUtils; public class UpsideDown { public int solve(int x, int y) { return (int) IntStream.range(x, y) .filter(i -> !StringUtils.containsAny(String.valueOf(i), "23457")) .filter(i -> new StringBuilder(i + "").reverse().toString() .replaceAll("6", "2") .replaceAll("9", "6") .replaceAll("2", "9") .equals(String.valueOf(i))) .count(); } } ``````

Option 2 (using `UnaryOperator`):

 `````` 1 2 3 4 5 6 7 8 9 10 11 `````` ``````import java.util.function.UnaryOperator; import static java.util.stream.IntStream.range; public class UpsideDown { public int solve(int x, int y) { UnaryOperator upside = s -> new StringBuilder( s.replaceAll("[23457]", "0").replace('6', '_').replace('9', '6').replace('_', '9')).reverse() .toString(); return (int) range(x, y).filter(i -> i == Integer.parseInt(upside.apply(i + ""))).count(); } } ``````

Option 3 (using `streams`):

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 `````` ``````import java.util.stream.*; public class UpsideDown { public int solve(int x, int y) { return (int) IntStream.range(x, y).boxed().filter(z -> { String s = String.valueOf(z); if(s.matches(".*[23457].*")) return false; int l = s.length(); if(l % 2 == 1) { if(s.substring(l/2, l/2+1).matches(".*[69].*")) return false; } int[] d = s.chars().map(Character::getNumericValue).toArray(); for(int i = 0; i < l/2; i++) { if(d[i] != d[l-1-i]) { if(d[i] == 6 && d[l-1-i] == 9) continue; if(d[i] == 9 && d[l-1-i] == 6) continue; return false; } else { if(d[i] == 6 || d[i] == 9) return false; } } return true; }).count(); } } ``````

## Test cases to validate our solution

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 `````` ``````import org.junit.Test; import static org.junit.Assert.assertEquals; import org.junit.runners.JUnit4; public class UpsideDownTest { UpsideDown sol = new UpsideDown(); @Test public void basicTests() { assertEquals(3, sol.solve(0,10)); assertEquals(4, sol.solve(10,100)); assertEquals(12, sol.solve(100,1000)); assertEquals(20, sol.solve(1000,10000)); assertEquals(6, sol.solve(10000,15000)); assertEquals(9, sol.solve(15000,20000)); assertEquals(15, sol.solve(60000,70000)); assertEquals(55, sol.solve(60000,130000)); } } ``````