TreeSet myNumbers = new TreeSet();
Random randGen = new Random();
for (int i = 1; i <= 16; i++) {
// number generation here
int randNum = randGen.nextInt(16 - 1) + 1;
for (;;) {
if (myNumbers.add(randNum))
break;
else
randNum = randGen.nextInt();
}
Toast.makeText(getApplicationContext(), "" + randNum, 100).show();
}
I want to generate random numbers between 1 and 16 and the same number should not be repeated.
The code above gives me output like:
2, 5, 7, 9, 1, 4, 10.4109446, -448831, 98824724, 11, 13, ...
I do not know why it gives me random numbers not in the 1-16 range, please help me out.
You're only generating one number in the range 1-15. You're then generating subsequent numbers with just nextInt:
if (myNumbers.add(randNum))
break;
else
randNum = randGen.nextInt();
That should be:
if (myNumbers.add(randNum))
break;
else
randNum = randGen.nextInt(16) + 1;
... and fix the initial call to nextInt to remove the "-1". (You don't need the 16 - 1, as explained in Josh's answer.)
To generate a random number in a range, it is like:
int min = ...
int max = ...
int randNumber = min + new Random().nextInt(max - min + 1);
So in your example where you want to generate a random number from [1, 16], it would look like:
int randNumber = 1 + new Random().nextInt(16 - 1 + 1);
Or if you choose to simplify:
int randNumber = 1 + new Random().nextInt(16);
Also, you should really be using a while loop instead of an infinite for loop:
final TreeSet<Integer> myNumbers = new TreeSet<>();
final Random rand = new Random();
for(int i = 0; i < 16; i++){
int n = 1 + rand.nextInt(16);
while(!myNumbers.add(n))
n = 1 + rand.nextInt(16);
}
It's not a big issue, if you are working in the range 1-16, but your code results in rejection of some randomly drawn numbers, if they have already been picked before.
In your solution, the expected value of nextInt() calls is proportional to n log(n), where n is the number of total elements you want to shuffle (16 in your case) – and the actual values can be much higher for a single run. You might consider using a more efficient implementation.
A solution which always uses only n calls:
ArrayList<Integer> originalNumbers = new ArrayList<Integer>();
Random randGen = new Random();
int max = 16;
for (int i = 1; i <= max; i++) {
// initializing ordered list so it becomes 1, 2, ..., max
originalNumbers.add(i);
}
for (int i = max; i >= 1; i--) {
// picking a random number from the ordered list, and swapping it
// with the last unpicked element which is placed closer to the
// end of list, where the already picked numbers are stored
int randNum = randGen.nextInt(i);
Collections.swap(originalNumbers, i - 1, randNum);
Toast.makeText(getApplicationContext(), "" + originalNumbers[i - 1], 100).show();
}
Related
I'm writing a code to find the mean, median and mode of an array of randomly generated ints (user inputs a size for the array and a range between which random numbers are to be generated it generate numbers between 3-22 randomly. I have not had too much trouble writing code for a mean or median but I cannot seem to be able to write code to calculate the mode (most commonly occurring number). Can anyone help or show/put code for how to calculate the mode of a randomly generated array of ints without having to create a method for yourself in the code? Thanks. Here is what I have so far (code that finds the mean and median):
public class ArraysIntsMeanMedianAndMode {
public static void main(String[] args) {
int ArraySize;
int min;
int max;
double x;
// To get the Size and range of numbers for the randomly genereated ints in the array.
Scanner sc = new Scanner(System.in);
System.out.println("What size should the array be?");
ArraySize = sc.nextInt();
System.out.println("Please enter a minimum value for the range of ints.");
min = sc.nextInt();
System.out.println("Please enter a maximum value for the range of ints.");
max = sc.nextInt();
//Making the array and filling it based on the user inputs
int[] MMMarray = new int[ArraySize];
int total = 0;
for (int i = 0; i < ArraySize; i++) {
x = (int) (Math.random() * ((max - min) + 1)) + min;
System.out.println(x);
int RandoNums = (int) x;
total = total + RandoNums;
MMMarray[i] = RandoNums;
}
//Finding mean/average
double Mean = (total + 0.0) / ArraySize;
System.out.println("The mean is: " + Mean);
//Finding Median/Middle number
Arrays.sort(MMMarray);
System.out.println(Arrays.toString(MMMarray));
if (ArraySize % 2 == 0) {
System.out.println("The median is: " + ((MMMarray[(ArraySize / 2)] + 0.0) + MMMarray[(ArraySize / 2) - 1]) / 2 + ".");
} else System.out.println("The median is: " + MMMarray[ArraySize / 2] + ".");
//How to find mode????????
Finding mode of unsorted array of int:
int freq = 0;
int value = 0;
int length = MMMArray.length;
for (int outer = 0; outer < length; outer++)
{
int tempFreq = 0;
for (int inner = 0; inner < length; inner++)
{
if (MMMArray[outer] == MMMArray[inner])
{
tempFreq++;
}
}
if (tempFreq > freq)
{
freq = tempFreq;
value = MMMArray[outer];
}
}
System.out.println("Mode is " + value + ", which appears " + freq + " times.");
Because you have already sorted the array to calculate the median, the problem of finding the mode(s) becomes equivalent to finding the longest consecutive streak of the same number. So, for example, if you have [1, 1, 2, 2, 2, 3, 5, 5, 21], there are three consecutive 2's, which is longer than any other run, so 2 is the mode.
To find the longest run, you can pass over the data once more, not reading any element twice. I'm adapting the code of Litvin and Litvin ever so slightly to use your array name, to count a run of 1 as a run, and to report what number the mode is rather than where it is in the array. You can drop this code in right where you ask your question, after the median has been calculated.
// at this point MMMArray is a sorted, nonempty array of int, because it was already sorted to find the median
int maxRunStart = 0, maxRunLength = 1;
int runStart = 0, runLength = 1;
for (int i = 1; i <= MMMArray.length; i++) //what they do here by using <=
//rather than < is worth reflecting upon
//it handles the case of the biggest run being at the end within the loop body
{
if (i < MMMArray.length && MMMArray[i] == MMMArray[i - 1])//notice how the boolean short-circuit prevents reading beyond the end of the array
{
runLength++;
}
else
{
if (runLength > maxRunLength)
{
maxRunStart = runStart;
maxRunLength = runLength;
}
runStart = i;
runLength = 1;
}
}
System.out.println("The mode is: " + MMMArray[maxRunStart] + ".");
}
Now here is something new to ponder. Suppose MMMArray contains [1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3]. This code (or that of MarsAtomic) will report 1 is the only mode. But the data is bimodal, and 3 is the mode as much as 1 is. One way to adapt the code would be to store the mode(s) in an array list (or an array, because we know up front there cannot be more modes than numbers). I think it is simpler (not more efficient, just easier not to mess up and without introducing another non-simple type) to make one more pass over the data. If you want that, then after the first for loop, instead of the println of the one mode, insert the following:
runLength = 1;
runStart = 0;
for (int i = 1; i <= MMMArray.length; i++)
{
if (i < MMMArray.length && MMMArray[i] == MMMArray[i - 1])
{
runLength++;
}
else
{
if (runLength == maxRunLength)
{
System.out.println("The mode is: " + MMMArray[runStart] + ".");
}
runStart = i;
runLength = 1;
}
}
int[] integers = new int[12];
Random r = new Random();
for (int i = 0; i < integers.length; i++) {
integers[i] = r.nextInt((10 - (-10) + 1) + (-10));
}
I'm executing it using online compiler and it throws an error at random.
can anyone help me to solve that problem? I don't know how to write that half of it be negative and half positive. And that random number can't be 0
First of all, to generate a number between -10 and 10, the correct code is :
integers[i] = r.nextInt(21)-10;
r.nextInt(21) will generate numbers between 0 and 20, so subtracting 10 will give you the desired range.
Now, you must validate the random numbers you generated, to make sure you don't generate too many positives or negative, and no zeroes.
int posCount=0;
int negCount=0;
for (int i = 0; i < integers.length; i++) {
integers[i] = r.nextInt(21)-10;
if (integers[i]>0)
posCount++;
else if (integers[i]<0)
negCount--;
if (posCount>6||negCount>6||integers[i]==0)
i--; // redo the current iteration of the loop, since the last generated
// number should be replaced
}
Another alternative, which will run faster, is to generate first 6 positive integers (r.nextInt(10)+1) and then 6 negative integers (-1-r.nextInt(10)), but I'm not sure whether the order of the generated numbers is important (i.e. is it acceptable that all the positives will come before all of the negatives).
1+ r.nextInt(10) gives integers 1-10. For negative integers, just put minus sign to the result of this calculation. Call it six times for positives and six times for negatives. What kind of error you get?
check this :
Random r = new Random();
int[] integers = new int[10];
boolean isEven=false;
int i = 0;
while(true){
int check = r.nextInt(10)*(isEven?-1:1);
if (check != 0){
isEven = !isEven;
integers[i] = check;
System.out.println(integers[i]);
i++;
}
if(i == 10){
break;
}
}
Keeping it simple:
Fill the current index with a random number from (1 to 10);
Fill the next index with a random number from (-1 to -10);
int[] integers = new int[12];
Random r = new Random();
for (int i = 0; i < integers.length; i+=2) {
integers[i] = r.nextInt(10) + 1;
if((i+1)<integers.length){
integers[i+1] = r.nextInt(10) -10;
}
}
I am trying to write a program that selects 5 integers at random between 1 and 6. I then need the program to display the missing integer. I can't figure out how to have it not display "0" as an integer. This is what I have so far...
import java.util.Random;
public class Task6
{
public static void main(String[] args)
{
int[] numbers = new int[5];
Random random = new Random();
for(int n = 1; n < 5; n++)
{
int select = random.nextInt(n + 1); //shuffle generator so it will not duplicate numbers
numbers[n] = numbers[select];
numbers[select] = n;
}//end for statement
for(int number : numbers)
{
System.out.println("Numbers selected : " + number);
}//end for
}
}
I have to have a O(n^2) operation in this as well.
If I understand correctly, you want your random numbers to only be between 1 and 6 (inclusive)? If that's the case then you need to restrict the range of what the RNG can actually spit out, using code similar to this:
/**
* Returns a pseudo-random number between min and max, inclusive.
* The difference between min and max can be at most
* <code>Integer.MAX_VALUE - 1</code>.
*
* #param min Minimum value
* #param max Maximum value. Must be greater than min.
* #return Integer between min and max, inclusive.
* #see java.util.Random#nextInt(int)
*/
public static int randInt(int min, int max) {
// NOTE: Usually this should be a field rather than a method
// variable so that it is not re-seeded every call.
Random rand = new Random();
// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
Also, your for loop:
for(int n = 1; n < 5; n++) { ... }
will not generate 5 numbers, it will generate 4. Think about the constraints of the loop; it will run through once with n = 1, 2, 3, 4, and then stop (5 is not less than 5).
If you want 5 iterations, you can do this:
for (int n = 0; n < 5; n++) { ... }.
or this:
for (int n = 1; n <= 5; n++) { ... }
Your number of iterations and your random number range don't need to be related.
Check this excellent answer for more detail if you need it.
Create a method that applies your constraints to the random number. Here is an example.
// this assumes that only 0 is unacceptable.
private static int myRandomBlammy()
{
int returnValue;
do
{
returnValue = blam; // replace blam with some way of generating a random integer.
} while (returnValue == 0);
return returnValue;
}
You should have an if statement on your loop that goes through the numbers.
for(int number : numbers)
{
if(number != 0){
System.out.println("Numbers selected : " + number);
}
}//end for
I am trying to write a program that selects 5 integers at random
between 1 and 6. I then need the program to display the missing
integer. I can't figure out how to have it not display "0" as an
integer.
From your question, there may be a case where your 5 random integers will not all be unique, and there may be more than one unique number that was not generated.
I would handle this with an array that counts how many of each number is generated:
import java.util.Random;
public class RandomCounter
{
/**
* An example that uses array indices to count how many random
* numbers are generated in a range.
*/
public static void main(String[] args)
{
//use an array of size n + 1 (ignore the zero index)
int[] numbers = new int[7];
Random r = new Random();
//generate random numbers
for (int i = 1; i < 6; i++){
int next = r.nextInt(6) + 1;
numbers[next]++; //count each number at the index
}
//print any numbers that didn't occur at least once.
for(int i = 1; i < numbers.length; i++){
if(numbers[i] != 0){
System.out.println(i);
}
}
}
}
Replace the last for-loop with this code snippet to see how many of each number occurred:
//print how many of each number occurred.
for(int i = 1; i < numbers.length; i++){
System.out.println (i + ": " + numbers[i]); }
}
Array index counting is a useful way to dynamically count occurrences of numbers.
on the first iteration- I want to create a random number from 0..10
This is how I've implement it-
int generator= (int)(Math.random() * (10));
On the first iteration I want to create another random number, but without one of the values.
For example I would like the random number without the number 4.
only 1,2,3,5,6,7,8,9,0
How can I remove one of the values from the numbers 0..10 when I generate a random number?
1st Way: -
You can also maintain a List of all the numbers. Then use Collections.shuffle to shuffle the list and get the first element. And remove it.
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(4);
list.add(2);
list.add(3);
System.out.println("Original List: " + list);
Collections.shuffle(list);
System.out.println("Shuffled List: " + list);
int number1 = list.remove(0); // Remove the first value
System.out.println("Number removed: " + number1);
Collections.shuffle(list);
System.out.println("Shuffled List: " + list);
number1 = list.remove(0);
System.out.println("Number removed: " + number1);
OUTPUT: -
Original List: [1, 4, 2, 3]
Shuffled List: [4, 3, 1, 2]
Number removed: 4
Shuffled List: [1, 3, 2]
Number removed: 1
2nd Way: -
A better way would be to generate a random number from 0 to the size of the list, and get the value of that index and remove it.
int size = list.size();
Random random = new Random();
for (int i = 0; i < size; i++) {
int index = random.nextInt(list.size());
int number1 = list.remove(index);
System.out.println(number1);
}
NOTE: -
If you want to exclude a fixed set of numbers from being generated, then you can have those numbers in a list. And then remove all elements of that list from your list of numbers. And then use any of the approach above.
int generator= (int)(Math.random() * (10));
if (generator >= 4) generator++;
This will include the number 10 as a possible outcome, if you do not want this, multiply by 9 instead of 10.
You could store the values in a list, and generate a random index to take from that list.
private Random random = new Random();
private ArrayList<Integer> values = new ArrayList<Integer>();
public static int nextInt() {
if (values.size() > 0) {
return values.remove(random.nextInt(values.size()));
} else {
throw new RuntimeException("no values possible");
}
}
Random.nextInt(10)==number generate again
public int generateExcept(int number) {
Random random = new Random();
int generated = 0;
while ((generated = random.nextInt(11)) == number) {
}
return generated;
}
As quoted by OP
On the first iteration I want to create another random number, but without one of the values
If I understand correctly This is single operation not repetitive operation.
Without Regeneration
public static int generateExcept(int number, int max) {
Random random = new Random();
int generated = 0;
if ((generated = random.nextInt(max - 1)) == number) {
generated++;
}
return generated;
}
Random is always generated max-1 because we want to increment by one
There are two basic efficient approaches:
1 - Generate an array of valid values (0 to 10 except 4), and use the randomizer to pick an index on that array. An example follows:
Random random = new Random();
int[] unwanted = {4};
int[] values = new int[10-unwanted.length];
for(int i=0; i<10-unwanted.length; i++){
for(int curr : unwanted){
if(i == curr) continue;
}
values[i] = i;
}
int result = values[random.nextInt(10-unwanted.length)];
2 - Follow Simon André's approach.
What you could do (perhaps there is a cleaner way of handling this) is to check the 2nd generated number to see if it matches the first, and if it does, just have it run the random num. generator again.
A simple if...else loop should take care of it.
int excluded[] = { 1,4,3};
Random r = new Random();
int generator;
do {
generator= r.nextInt(10);
} while (! Arrays.asList(excluded).contains(generator) )
I've some strange situation here and i thought that you may help me. I have an int array populated with numbers from 1 to 10. I want to generate random number from this array and save it to another int array. I used class Random to pick any number and since random throws 0 also i modify it like that ( so it throws numbers from 1 to 10 )
randNum = rand.nextInt(numbers.length-min+1)+min;
Following code makes sure that if it generates same random number, it skips it. Program is actually working and i'm getting in another array randomly positioned numbers from 1 to 10. That's what i wanted. But sometimes i'm missing one number from 1 - 10 AND iam Getting ZERO instead. Why??
int[] numbers = {1,2,3,4,5,6,7,8,9,10};
int[] usednum = new int[10];
Random rand = new Random();
int randNum;
int min = 1;
for (int x = 0; x<numbers.length; x++) {
for (int i = 0; i<usednum.length; i++) {
randNum = rand.nextInt(numbers.length-min+1) + min;
for (int f = 0; f<usednum.length; f++) {
if (usednum[f] == randNum) {
break;
} else if (usednum[f] == 0) {
usednum[x] = randNum;
}
}
}
}
for (int c = 0; c<usednum.length; c++) {
System.out.println(usednum[c]);
}
You're inner-most for loop only checks if the current random number is in the usednum[] array. And the for loop immediately outer of that only checks 10 times total. It gives up too quickly because it only tries 10 random numbers. If all 10 are already used, nothing will get stored in that slot of usednum[] (thus it will be 0), try adding a while loop around that and get rid of the extraneous outer-most for loop:
for(int i = 0; i<usednum.length; i++) {
while(usednum[i]==0) {
randNum = rand.nextInt(numbers.length-min+1)+min;
for(int f = 0; f<usednum.length; f++) {
if(usednum[f] == randNum) {
break;
} //if
else if (usednum[f] == 0) {
usednum[i] = randNum;
}
}
}
}
Also note that the assignment is for usednum[i] = randNum;.
This is essentially replacing the middle for loop (the one that goes from i=0 to 9) with the while loop.
If your goal is simply to shuffle an array of numbers, try this instead:
Integer[] numbers = {1,2,3,4,5,6,7,8,9,10};
Collections.shuffle(Arrays.asList(numbers));
It will have the same effect. Unless you are completing a homework assignment that forces you to solve the issue in a more manual fashion, just make use of the standard Java libraries.
The shuffle method writes changes through to the underlying Integer array, thanks to the special type of List returned by Arrays.asList(...). Note you have to use an array of Integer not int (see Why does Collections.shuffle() fail for my array?).
You are generating used numbers through an entire pass, so it doesn't generate a zero is just fails to generate a value it should.
you have one for loop too much.
remove the loop with the i iterator and the program should do what you want.
Oh and remove the -min+1 from the random generator, -1+1=0
Your array usednum is consisted of zeros at the beginning. In some cases, your program doesn't change that initial value, but breaks before at the line:
if(usednum[f] == randNum)
and does that during all iterations with same value x. X increments and there goes your chance to change the zero value.
Edit - followed it and re-wrote it:
List<Integer> numbers = new LinkedList<Integer>(Arrays.asList(new Integer[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }));
int[] usednum = new int[10];
Random rand = new Random();
int n = numbers.size();
for (int i = 0; i < n; i++) {
int randNum = rand.nextInt(numbers.size());
usednum[i]=numbers.get(randNum);
numbers.remove(randNum);
}
for (int c:usednum) {
System.out.println(c);
}
Actually, you are never using the content of the array numbers. Try changing the array to something like int[] numbers = { 10, 22, 23, 42, 53, 18, 7, 8, 93, 10 };. You will get similar output.
Jon Lin's answer describe why your code is not working but does not address this issue. I think you will want to change your code to something like:
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int[] usednum = new int[10];
Random rand = new Random();
int selectedCount = 0;
while (selectedCount < numbers.length) {
int randNum = numbers[rand.nextInt(numbers.length)];
boolean contains = false;
for (int x = 0; x < selectedCount; x++) {
if (usednum[x] == randNum) {
contains = true;
break;
}
}
if (!contains) {
usednum[selectedCount] = randNum;
selectedCount++;
}
}
for (int c = 0; c < usednum.length; c++) {
System.out.println(usednum[c]);
}