I want to generate 4 random numbers and they can't have repeated digits.
For instance 4567
, (it doesn't have a repeated value like 4557
).
I want them to be random.
Is there any way to achieve this?
I want to generate 4 random numbers and they can't have repeated digits.
For instance 4567
, (it doesn't have a repeated value like 4557
).
I want them to be random.
Is there any way to achieve this?
This will generate 4 digit random numbers with no repeating digits.
It works by generating 4 unique digits in the same fashion that one might shuffle a deck of cards in a computer game. It then simply builds up the four digit number by multiplication and addition.
If the number is less than 1000
, then that means a 0
was used and was at the beginning. So just choose another digit to adjust.
Random r = new Random();
for (int k = 0; k < 10; k++) {
int val = gen(r);
System.out.println(val);
}
static int[] base = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public static int gen(Random r) {
int val = 0;
int s=10;
for (int i = 0; i < 4; i++) {
int n = r.nextInt(s);
val = val * 10 + base[n];
int save = base[n];
base[n] = base[--s];
base[s] = save;
}
return val < 1000 ? val * 10 + base[r.nextInt(s)] : val;
}
Here is a more straightforward way of doing it. The philosophy is the same as above. It may not be quite as efficient as the previous due to the shuffling of all the digits.
// generate four digit numbers that have distinct digits.
List<Integer> digits = Arrays.asList(0,1,2,3,4,5,6,7,8,9);
Collections.shuffle(digits);
// now just use the first four of the shuffled list
if (digits.get(0) == 0) {
// for a 4 digit number, first digit can't be zero
// so choose another.
digits.set(0, digits.get(4));
}
// now use simple arithmetic to create the four digit number.
int n = 0;
for (int d : digits.subList(0,4)) {
n = n * 10 + d;
}
System.out.println(n);
I'm obsessed with streams nowadays. But streams are pretty slow. To show the slowness I wrote following main method. "generateWithLoop" method covers @WJS's answer.
public static void main(String[] args) {
long nanoStart = System.nanoTime();
generateWithStreams();
long nanoEnd = System.nanoTime();
System.out.println("Elapsed time with Streams : " + (nanoEnd - nanoStart) + " nano seconds");
nanoStart = System.nanoTime();
generateWithLoop();
nanoEnd = System.nanoTime();
System.out.println("Elapsed time with Loop : " + (nanoEnd - nanoStart) + " nano seconds");
}
Console output :
Elapsed time with Streams : 81367089 nano seconds
Elapsed time with Loop : 75093 nano seconds
With stream :
public static void generateWithStreams() {
List<Integer> orderedList = getOrderedList();
for (int i = 0; i < 4; i++) {
List<Integer> shuffledList = getShuffledList(orderedList);
System.out.println(get4DigitNumber(shuffledList));
}
}
public static List<Integer> getOrderedList() {
return IntStream.range(0, 10).boxed().collect(Collectors.toList());
}
public static List<Integer> getShuffledList(List<Integer> list) {
return list.stream().sorted((o1, o2) -> ThreadLocalRandom.current().nextInt(-1, 2)).collect(Collectors.toList());
}
public static Integer get4DigitNumber(List<Integer> shuffledList) {
final Integer LIMIT = shuffledList.get(0).equals(0) ? 5 : 4;
return shuffledList.stream().limit(LIMIT).reduce(0, (sum, current) -> sum * 10 + current);
}
With loop :
public static void generateWithLoop() {
Random r = new Random();
for (int k = 0; k < 4; k++) {
int val = gen(r);
System.out.println(val);
}
}
static int[] base = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public static int gen(Random r) {
int val = 0;
int s = 10;
for (int i = 0; i < 4; i++) {
int n = r.nextInt(s);
val = val * 10 + base[n];
int save = base[n];
base[n] = base[--s];
base[s] = save;
}
return val < 1000 ? val * 10 + base[r.nextInt(s)] : val;
}
public static void main(String[] args) {
List<Integer> list= new ArrayList<>();
for(int j = 0; j < 10; j++){
list.add(j);
}
Collections.shuffle(list);
String randomDigit= "";
for(int j = 0; j < 4; j++){
randomDigit+= list.get(j).toString();
}
System.out.println(randomDigit);
}
This is converting the string to int. But this will work you can use it.
Steps:
List
that will hold each individual number of the generated
4-digit numberEventually the size of the list is now 4; combine these 4 individuals into a String
, and convert to Integer
.
List<Integer> myNumber = new ArrayList<Integer>();
Random r = new Random();
// Generate a random number between 1 and 9 for units place
myNumber.add(r.nextInt(9) + 1);// adding 1 to avoid 0 in the units place
// Generate a random number between 0 and 9 for 10's and upcoming places
do {
Integer num = r.nextInt(10);
// Check the list doesn't contain that number
if (!myNumber.contains(num)) {
myNumber.add(num);
}
}while (myNumber.size() < 4);
StringBuilder numStr = new StringBuilder();
for (int i = 0; i < myNumber.size(); i++)
numStr.append(myNumber.get(i));
System.out.println(Integer.parseInt(numStr.toString()));
A solution using stream
and Lambdas from Java-8 onwards:
public static void main(String[] args) {
Map<String, String> collect = IntStream.rangeClosed(1, 9).boxed()
.flatMap(x -> IntStream.rangeClosed(0, 9).boxed()
.flatMap(y -> IntStream.rangeClosed(0, 9).boxed()
.flatMap(z -> IntStream.rangeClosed(0, 9).boxed()
.flatMap(w -> IntStream.rangeClosed(1, 9).boxed().map(s -> s.toString()).filter(e -> noneRepete(x, y, z, w))
.map(k -> x.toString() + y.toString() + z.toString() + w.toString())))))
.collect(Collectors.toMap(Function.identity(), s -> s, (a, b) -> a));
collect.keySet().forEach(System.out::println);
}
public static boolean noneRepete(Integer a, Integer b, Integer c, Integer d) {
if (! a.equals(b) && ! a.equals(c) && ! a.equals(d) && a !=0) {
if (! b.equals(c) && ! b.equals(d)) {
return ! c.equals(d);
}
}
return false;
}
Explanation:
Here we are flattening the stream of Integers from 1 to 9(first digit cannot be 0). while in further we are flattening stream of Integers from 0 to 9. The above process goes 2 more time thus making it a four digit, we are having a custom filter which is making sure that all four digits are unique.
At last we are collecting them as keys and values making sure the digits are unique and key itself in a map is unique.