How to Solve a Pandigital Sequence in Java


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 the offset. If there is not enough size 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);
    }

}