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
):
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
):
import java.util.function.UnaryOperator;
import static java.util.stream.IntStream.range;
public class UpsideDown {
public int solve(int x, int y) {
UnaryOperator<String> 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
):
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
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));
}
}