The challenge
In mathematics, a pandigital number is a number that in a given base has among its significant digits each digit used in the base at least once. For example, 1234567890 is a pandigital number in base 10.
For simplification, in this challenge, we will consider pandigital numbers in base 10 and with all digits used exactly once. The challenge is to calculate a sorted sequence of pandigital numbers, starting at a certain offset
and with a specified size
.
Example:
Pandigital.getSequence(0, 5)
// [1023456789, 1023456798, 1023456879, 1023456897, 1023456978]
Rules:
- We are looking for positive pandigital numbers in base 10.
- Each digit should occur
exactly once
. - A pandigital number can’t start with digit zero.
- The offset is an integer (negative, zero or positive number) (long in Java)
- The size is a positive integer number (int in Java)
- Return the
size
pandigital numbers which are not smaller than theoffset
. If there is not enoughsize
pandigital numbers, just return all of them. - Return an empty array if nothing is found.
The solution in Java code
Option 1:
import java.util.Arrays;
import java.util.stream.LongStream;
public class Pandigital {
public static long[] getSequence(final long offset, final int size) {
long from=Math.max(offset,1023456789L);
return LongStream.rangeClosed(from,9876543210L)
.filter(n->n>=offset)
.filter(Pandigital::isPandigital)
.limit(size)
.toArray();
}
private static boolean isPandigital(long n){
return (""+n).chars().distinct().count()==10;
}
}
Option 2:
import java.util.function.LongPredicate;
import java.util.stream.LongStream;
public class Pandigital {
private static final long MIN_PANDIGITAL = 1023456789L;
private static final long MAX_PANDIGITAL = 9876543210L;
private static final LongPredicate isPandigital = l ->
!String.valueOf(l).matches(".*(.).*?\\1.*");
public static long[] getSequence(final long offset, final int size) {
return LongStream
.iterate(Math.max(MIN_PANDIGITAL, offset),
l -> l <= MAX_PANDIGITAL,
l -> ++l)
.filter(isPandigital)
.limit(size)
.toArray();
}
}
Option3:
import java.util.ArrayList;
public class Pandigital {
public static long[] getSequence(final long offset, final int size) {
boolean b = true;
for (int i = 0; i < String.valueOf(offset).length(); i++) {
if (String.valueOf(offset).charAt(i) != '9') {
b = false;
break;
}
}
if (b) return new long[] {};
long x = offset;
ArrayList<Long> list = new ArrayList<>();
if (offset < 1023456789L) x = 1023456789L;
for (long i = x; list.size() != size; i++) {
String s = String.valueOf(i);
if (!s.startsWith("0") && s.contains("0")
&& s.contains("1") && s.contains("2")
&& s.contains("3") && s.contains("4")
&& s.contains("5") && s.contains("6")
&& s.contains("7") && s.contains("8")
&& s.contains("9") ) list.add(i);
}
long[] res = new long[list.size()];
for (int i = 0; i < list.size(); i++) {
res[i] = list.get(i);
}
return res;
}
}
Test cases to validate our solution
import org.junit.Test;
import static org.junit.Assert.assertArrayEquals;
public class ExampleTests {
@Test
public void simpleTest() {
long[] subject = Pandigital.getSequence(0L, 5);
long[] expected = {1023456789L, 1023456798L, 1023456879L, 1023456897L, 1023456978L};
assertArrayEquals(expected, subject);
}
@Test
public void withPandigitalOffset() {
long[] subject = Pandigital.getSequence(5432160879L, 3);
long[] expected = {5432160879L, 5432160897L, 5432160978L};
assertArrayEquals(expected, subject);
}
@Test
public void withNonPandigitalOffset() {
long[] subject = Pandigital.getSequence(9876543000L, 5);
long[] expected = {9876543012L, 9876543021L, 9876543102L, 9876543120L, 9876543201L};
assertArrayEquals(expected, subject);
}
@Test
public void withTooBigOffset() {
long[] subject = Pandigital.getSequence(9999999999L, 1);
long[] expected = {};
assertArrayEquals(expected, subject);
}
@Test
public void withNegativeOffset() {
long[] subject = Pandigital.getSequence(-123456789L, 1);
long[] expected = {1023456789L};
assertArrayEquals(expected, subject);
}
}