Refining a random number generator for Sudoku [duplicate] - java

This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
Closed 8 years ago.
I'm working on building one of my fist apps and I'm building a Sudoku mobile game. I've built the random number generator I just cant figure out how to write it so that it only generates numbers between 1-9 (not zero) and each of numbers are only generated once. Here is what I have so far:
package randomNumber;
import java.util.Random;
public class OneToNine {
public static final void main(String... aArgs) {
log ("generating random integers in range 1-9");
Random randomGenerator = new Random();
for (int idx = 1; idx <= 9; ++idx) {
int randomInt = randomGenerator.nextInt(9);
log ("Generated : " + randomInt);
}
log("Done. ");
}
private static void log (String aMessage) {
System.out.println(aMessage);
}
}

Rather than worry about generating the numbers in a random order, you should adjust your approach to shuffling the numbers. You know you will have the numbers 1-9 so do something like this:
public ArrayList<Integer> getRandomOrderedNums(){
ArrayList<Integer> numbers = new ArrayList<Integer>();
for(Integer i = 1; i < 10; i++){
numbers.add(i);
}
Collections.shuffle(numbers);
}

For your second part, to see if the numbers are repeated, you can easily use a data structure such as a HashSet, which is the most efficient to check for repeated values. Let me know if you're not fully comfortable with them. Using the hashset, you can come up with a random number, and check if the set contains this number, and if it does, try again.
With regards to the random number, you can just do randomGenerator.nextInt(9) + 1 so it'll always be from 1-9 (inclusive).

You might want to use a function like this:
public static int getRandInt(int max, int min) {
return new Random().nextInt((max - min) + 1) + min;
}

Related

Random Number generator in a range and then print length of the sequence [duplicate]

This question already has answers here:
How do I generate random integers within a specific range in Java?
(72 answers)
Closed 3 years ago.
I want the application to create a sequence that generates a series of random numbers from 0 to 9 util a 0 is generated and then display the length of the sequence of the numbers. Right now my program only prints 0 or 9 as I don't know the random number generator method.My question is how do I generate a random integer between 0 and 9(inclusive) unit a 0 is generated.
import java.util.Random;
import java.util.ArrayList;
public class Sequence {
public static void main(String[] args) {
ArrayList<Integer> lista = new ArrayList<Integer>();
lista.add(0, 9);
Random r = new Random();
System.out.println(lista.get(r.nextInt(lista.size())));
}
}
Consider using a while-loop:
import java.util.Random;
class Sequence {
public static void main(String[] args) {
Random r = new Random();
int count = 0;
int num = -1;
System.out.println("The sequence is:");
while (num != 0) {
num = r.nextInt(10);
System.out.print(num + " ");
count++;
}
System.out.printf("%nThe length of the sequence is: %d%n", count);
}
}
Example Output:
The sequence is:
3 9 3 9 4 0
The length of the sequence is: 6
Alternatively if you need to store the sequence in a collection:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
class Sequence {
public static void main(String[] args) {
Random r = new Random();
List<Integer> result = new ArrayList<>();
int num = -1;
while (num != 0) {
num = r.nextInt(10);
result.add(num);
}
System.out.printf("The sequence is: %s%n", result);
System.out.printf("The length of the sequence is: %d%n", result.size());
}
}
Consider the following code:
ArrayList<Integer> nums = new ArrayList<>();
Random r = new Random();
int num = r.nextInt(10);
while(num != 0)
{
nums.add(num);
num = r.nextInt(10);
}
System.out.println(nums.size());
To avoid the List never generating because num's first generated random number is 0, consider using an if statement and reassign the value accordingly.
Your current implementation is currently doing the following:
Creating a list with 1 element with the value of 9
Your call to Random is evaluating to Random.nextInt(1) which will always return 0 as the parameter to nextInt() is an exclusive upper bound from 0 to that bound.
In short, your implementation will always return, the first item in your list, which is 9
If you want to get a random number between 0 and 9 then you need to call Random.nextInt() with an upper bound of 10, i.e. Random.nextInt(10).
To generate a sequence you need to a while loop that terminates when a 0 is returned from random.
Finally, as you don't seem to care about the sequence generated and just the length you can dispense with the List.
So you could try something like the following:
public static void main(String[] args) {
Random r = new Random();
int count = 0;
while (r.nextInt(10) != 0) {
count++;
}
System.out.println("Sequence Length = " + count);
}
A while loop would be very useful for this. Examine how you say you want numbers to be generated until a 0 is generated. When you want something to happen over and over until a condition is met, use a while loop. Here's an example of a while loop that would run until a 0 is generated:
ArrayList<Integer> lista = new ArrayList<Integer>();
Random myRandom = new Random();
int next = myRandom.nextInt(10);
//We use 10 because nextInt() is non-inclusive for the upper bound. It will generate 0 to 9
while(next != 0) {
lista.add(next);
next = myRandom.nextInt(10)
}
lista.add(next); //When we get here, a 0 has been generated. Add it to the list.
//To display the length of the list, print out lista.size()
System.out.println(lista.size());
I'm assuming you want the sequence to stop when a 0 is generated and still add that 0 to the list. If not, exclude the add(next) after the loop.

Random element generation without duplicates Java [duplicate]

This question already has answers here:
Creating random numbers with no duplicates
(20 answers)
best way to pick a random subset from a collection?
(10 answers)
Closed 7 years ago.
I am trying to get this code to run without duplicates but am having no success researching this area.
Its the start of a question I am doing which will ask the user to input the missing element. However, when I generate random elements I am getting duplicates
import java.util.Random;
public class QuestionOneA2 {
public static void main(String[] args) {
String[] fruit = {"orange", "apple", "pear", "bannana", "strawberry", "mango"};
Random numberGenerator = new Random();
for (int i = 0; i < 5; i++) {
int nextRandom = numberGenerator.nextInt(6);
System.out.println(fruit[nextRandom]);
}
}
}
There are many different approaches you can consider, depending on how flexible the algorithm should be.
Taking 5 random elements from a list of 6, is the same as selection 1 element from the list of 6 that you don't choose. This is a very inflexible, but very easy.
Another approach could be to delete the element from the list, and decrease the maximum random number. In this cause I would advice to not use a String[].
When you generate a random number, I suggest adding it into an array.
Then, when you generate your next number, do some sort of search (google for something efficient) to check if that number is already in the array and thus, has been used already.
If it is, generate a new one, if its not, use it.
You can do this by nesting it in a while loop.
Although, from what I can tell from your question, you would be better off just creating a copy of your fruit array using an ArrayList and then, when you generate a random number to select a fruit, simply remove this fruit from this new list and decrement the range of random numbers you are generating.
You can use a Set to validate if the random generated number is duplicate or not. You just have to keep generating randomNumber until you find a unique random and then add it to the Set to prevent the duplicates.
Here is a quick code snippet:
public static void main(String[] args) {
String[] fruit = {"orange", "apple", "pear", "bannana", "strawberry", "mango"};
Random numberGenerator = new Random();
/* Generate A Random Number */
int nextRandom = numberGenerator.nextInt(6);
Set<Integer> validate = new HashSet<>();
/* Add First Randomly Genrated Number To Set */
validate.add(nextRandom);
for (int i = 0; i < 5; i++) {
/* Generate Randoms Till You Find A Unique Random Number */
while(validate.contains(nextRandom)) {
nextRandom = numberGenerator.nextInt(6);
}
/* Add Newly Found Random Number To Validate */
validate.add(nextRandom);
System.out.println(fruit[nextRandom]);
}
}
Output:
mango
apple
strawberry
pear
orange
You can wrap int into 'Interger' and add it to Set. Set holds no duplicates so there will be only unique values in it. So then just check if a Set already has given Integer with Set.contains(Integer).
my personal solution :
private static int[] randomIndexes(int len) {
int[] indexes = new int[len];
for (int i = 0; i < len; i++) {
indexes[i] = i;
}
for (int i = len - 1, j, t; i > 0; i--) {
j = RANDOM.nextInt(i);
t = indexes[j];
indexes[j] = indexes[i];
indexes[i] = t;
}
return indexes;
}
See it in action : https://gist.github.com/GautierLevert/a6881cff798e5f53b3fb
If I understand you correctly, then you want to choose n-1 elements at random from a list of n elements. If yes, then I recommend to choose just one at random and take all the others.
Arrays.shuffle(fruit);
int notThis = numberGenerator.nextInt(6);
for(int i = 0; i < fruit.length; i++)
if(i!=notThis) System.out.println(fruit[i]);
Copy your array into List<String>, then shuffle it, then just pick elements one by one:
List<String> copy = new ArrayList<>(Arrays.asList(fruit));
Collections.shuffle(copy);
for (String f : copy)
System.out.println(f);
I think it will be easier using an ArrayList, and also controlling the generation of the random number as shown below.
import java.util.Random;
public class QuestionOneA2 {
public static void main(String[] args) {
List<String> fruits = new ArrayList<>();
fruits.add("orange");
fruits.add("apple");
fruits.add("pear");
fruits.add("bannana");
fruits.add("strawberry");
fruits.add("mango");
Random numberGenerator = new Random();
int nextRandom;
for (int i = 0; i < 6 ; i++) {
nextRandom = numberGenerator.nextInt(6 - i);
System.out.println(fruits.get(nextRandom));
fruits.remove(nextRandom);
}
}
}
fruit.remove(fruit[nextRandom]);
Maybe, is it the remove sub-method?

random numbers previously established (java)

The following code shows 4 int variables:
int xy1 = 724329;
int xy2 = 714385;
int xy3 = 715440;
int xy4 = 696492;
I'm pretending to code an app that, by opening it, shows one of those numbers (NOT numbers between them) on java console, randomly. I know that Math.Random class can be used to solve these kind of issues, but I don't know what is the proper way to do so.
So, thanks.
Well it sounds like you just want a collection of possible values, and an index between 0 and 3 inclusive:
int[] values = { 724329, 714385, 715440, 696492 };
Random random = new Random(); // Ideally initialize once for the entire app
int index = random.nextInt(4);
int value = values[index];
Place them into an array and use Random to select a number between 0-3 and use it as a key to select the value from the array.
Try this one.
This line
r.nextInt(nums.length)
selects an integer from 0 to nums.length-1.
Then I print out the randomly selected number from the nums array.
I repeat this 20 times just for demonstration purposes.
import java.util.Random;
public class Test015 {
public static void main(String[] args) {
int[] nums = {724329, 714385, 715440, 696492};
Random r = new Random();
for (int i=0; i<20; i++){
int index = r.nextInt(nums.length);
System.out.println("Number randomly chosen: " + nums[index]);
}
}
}

How to generate random numbers with non-repeating digits in Java? [duplicate]

This question already has answers here:
Non repeating random numbers
(2 answers)
Closed 8 years ago.
When using the random utility in java, you get some numbers like this: 1271, 34556, 177, etc... What is the simplest way to make it so the digits don't repeat?
You could shuffle the array [1,2,3,4,5,6,7,8,9] and read that as a number.
If you don't want to fix the number of digits, or allow a non-leading zero, it gets more complicated (if you care about some sort of equal distribution).
You could initialize a List with the digits 0-9. Then randomize this list and poll a random amount of elements (between 1 and 9) from this list. Concatenate the digits and you have your number with non-repeating digits.
How about creating a loop that checks if the generated random number meets your requirements.
final Random rnd = new Random();
int n;
do {
n = rnd.nextInt(1000);
} while(containsRepeatingDigits(n));
containsRepeatingDigits can look like this:
boolean containsRepeatingDigits(final int n) {
final boolean digits[] = new boolean[10];
for(char c : String.valueOf(n).toCharArray()) {
final int i = c-'0';
if(digits[i])
return true;
digits[i] = true;
}
return false;
}
You could check if the random number has repeating digits and generate a new one if it does. It's written in C#, but you should be able to convert this to Java real easy.
private static Random rand = new Random();
public static int GenerateNumberNonRepeat()
{
int number;
do
{
number = rand.Next();
} while (IsRepeating(number));
return number;
}
public static bool IsRepeating(int number)
{
string textual = number.ToString();
for (int i = 0; i < textual.Length; i++)
{
for (int j = i + 1; j < textual.Length; j++)
{
if (textual[i] == textual[j])
return true;
}
}
return false;
}
Another way to generate those numbers is to generate arbitrary number, and in case that it contains repeating digits either generate a new one, or remove the repeating digits (by e.g. increment the number until there are no more repeating numbers).
In contrast to proposed shuffle/select approach this has the advantage, that you keep (more or less) the distribution of the original rng.
This code may help you
Set set = new HashSet<Integer>();
Random rand= new Random();
public int getNonRepeatingRandomNumber() {
int intV = rand.nextInt();
if(set.contains(intV)) {
return getNonRepeatingRandomNumber();
}
else {
set.add(intV);
return intV;
}
}

Why won't this create multiple sets of random numbers? [duplicate]

This question already has answers here:
Random Number Generator: mainly how to stop repetition of numbers. Java
(6 answers)
Closed 9 years ago.
Ok so the objective is to generate 6 random numbers per line/row. With x number of rows (set by the user via UserInput). Each row MUST have unique numbers (non-duplicated numbers). I'm pretty sure the numbers are unique, however I can't seem to get it to have multiple rows, and I cannot figure out for the life of me what part is preventing multiple rows.
package rtg;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class Array {
public static void main(String[] args) {
String name;
int noTickets;
int[] numbers = new int[6];
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
int ticketCount = 1;
System.out.println("Please input your name");
name = UserInput.readString();
System.out.println("Please input the number of tickets you want");
noTickets = UserInput.readInt();
System.out.println("___________________________________________\n___________________________________________");
System.out.println("___________________________________________\n___________________________________________");
System.out.println("Name: " +name+ "\nNumber of Tickets: " +noTickets+ "\nNumbers: ");
for (ticketCount = 1; ticketCount <= noTickets; ++ticketCount){
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
int i = 0;
for (Integer n : randomNumbers) {
numbers[i++] = n;
}
System.out.print( Arrays.toString(numbers) + "\n");
}
}
}
EDIT Thanks a lot everyone, I finally got there, turns out I put the array in the wrong place (it was outside the for loop so only made 1 set of random numbers) Fixed it now. Next challange; having a comparison program to scan 90+ sets of 6 unique numbers, and comparing if any of them match a different set (per row/set >.<)
You can stuff random integers into a Set<Integer> until it has six elements:
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
Alternatively, you can generate the numbers 1-50, shuffle them, and pick any six elements:
List<Integer> numbers = new ArrayList<>(50); // known capacity
for (int i = 1; i <= 50; ++i) { numbers.add(i); }
Collections.shuffle(numbers);
List<Integer> sixRandomNumbers = numbers.subList(0, 6);
The first solution does extra work whenever there is a collision; this extra work goes up the greater the ratio is of desired to total numbers. The second does extra work by having to deal with all 50 numbers; the extra work goes down the greater the ratio is of desired to total numbers. It's an interesting question where the cross-over point is.
EDIT (Responding to the edit to the original question) After you use one of the above methods to generate six distinct, random numbers, you need to put them into the variables you are going to use. One way (say, using the first method) is as follows:
int[] numbers = new int[6];
Set<Integer> randomNumbers = new HashSet<>();
Random rand = new Random();
while (randomNumbers.size() < 6) {
randomNumbers.add(rand.nextInt(50) + 1);
}
System.out.println("Six random numbers: " + randomNumbers.toString());
// if you need them as an `int` array:
int i = 0;
for (Integer n : randomNumbers) {
numbers[i++] = n;
}
The numbers array replaces your variables number1, ..., number6.
Use a data type which allows you to check if the int has already been created. For example, adding them to an ArrayList<Integer>.
ArrayList<Integer> numbers = new ArrayList<Integer>();
while(numbers.size() < 6) {
int num = rand.nextInt(50) + 1;
if(!numbers.contains(num)) {
numbers.add(num);
}
}
Of course, as #sanbhat says in the comments, you can use a Set<Integer> and avoid the if() conditional entirely in the loop. However I thought this would be more intuitive for a beginner who doesn't know that the Set API will not add a duplicate element.
Save a sorted list or more efficiently a set of the previously chosen values and check your current selection against the previous ones, if it was previously chosen try again.
If you know the valid range of your random numbers and if the size of that range is not prohibitive, one simple algorithm would be as follows:
Create an array with a size equal to your number range
Consecutively fill your array with the numbers in your number range
Iterate through the list an arbitrarily large number of times; generate two pseudorandom numbers that are within your array indices, and swap the two elements at those indices
After the iteration is complete, you will have an array of uniquely represented numbers that are all within your number range that appear in a random order. This nearly exactly simulates what happens when one shuffles a deck of cards.
You can then write a simple method to consecutively pop numbers out of your array each time it is called.
An advantage of this algorithm is that it can be implemented as an array of primitives, eg. int[], without any need for the Java Collections API.

Categories