trying to add an item at random time intervals.
I was thinking I need to start when i is equal to arriveTime, once that is met I need to create a new random arrival and add i (otherwise it will not happen again as i is already past arrival. So I add another if, once that is met create new arrival time and add i again. pseudocode seems to make sense, code not so much, any help is appreciated.
ArrayList<Integer> q = new ArrayList<Integer>();
Random r = new Random();
int arrivals = 0;
for (int i = 1; i <= 720; i++) {
int arrive = r.nextInt(4)+1;
if (i == arrive) {
q.add(i);
arrivals ++;
arrive = r.nextInt(4)+1+i;
}
else if (i == arrive) {
q.add(i);
arrivals ++;
arrive = r.nextInt(4)+1+i;
}
}
sorry, arriveTime should be just arrive. ArriveTime does not exist.
edit: To expand from comments. 'i' represents time and I dont want to add a random integer to the list. Rather add the same object at random intervals of 'i'. I was adding the value of 'i' to the list to see at what times the algorithm was adding an item because it didnt seem to be working. Results vary, but it seems to be always single digits that get added to list. Also made updates to code.
Your algorithm is lacking a pause - ie a call to Thread.sleep(), otherwise it will spin.
I'd be trying to keep it simple, matching your code to the problem: ie wait a random time between adding to the queue, simply:
ArrayList<Integer> q = new ArrayList<Integer>();
Random r = new Random();
for (int i = 1; i <= 720; i++) { // loop as many times as you want
Thread.sleep(r.nextLong() % 1000); // wait a random time up to 1 second
q.add(r.nextInt()); // add a random number to the queue
}
You can adjust the numbers to suit your requirements.
you should be comparing time to 1-4 in your if statements, then adding that value to i (as i is representative of time) Something like this
ArrayList<Integer> q = new ArrayList<Integer>();
Random r = new Random();
int arrivals = 0;
for (int i = 1; i < 100 ; i++) { //loop as many times as you want.
int time = r.nextInt(4)+1; //choose a random time of arrival, 1-4
//now compare time to your random time intervals (1-4, not i
//if it matches add that value to i
if (time == 1) {
//add your object to the list
i += 1;
}
else if (time == 2) {
//add your object to the list
i += 2;
}
else if (time == 3) {
//add your object to the list
i += 3;
}
else if (time == 4) {
//add your object to the list
i += 4;
}
}
The code as posted doesn't make much sense.
It depends on an undeclared variable.
The statements that update arrive have no effect ... because it it local to the loop.
Related
I have a problem for an online course I am doing. The question is:
Given an Integer x, write a program which generates random numbers between x and 0 until each number in this range has been generated at least once. Once all numbers in this range have been generated, the program should display the numbers which were generated.
I have written a program which I thought would solve this but am having problems with the checking if a number is in the range. Here is my code so far:
public static void main(String[] args) {
Random generator = new Random();
ArrayList<Integer> range = new ArrayList<Integer>();
ArrayList<Integer> generated = new ArrayList<Integer>();
int x = 10;
int count = 0;
for(int i = 0; i<x+1; i++){
range.add(i);
}
while(range.isEmpty() != true){
int temp = generator.nextInt(x-1);
count++;
generated.add(temp);
if(range.contains(temp)){
range.remove(temp);
}
}
}
}
My idea was to first create two arraylists. The first would hold all numbers between 0 and the given x. The second would contain the random numbers generated. I then fill the range arraylist with the range between 0 and x. My While loop then checks this range list to see if it is empty. If not, it generates a random number, adds it to my second arraylist. I then check if this number is in the range arraylist - if it is it removes it and carries on. The problem I am having is it is running into IndexOutOfBoundsException after a few goes. I think this is because I am removing the generated numbers from the arraylist. Can anyone help me with fixing this
EDIT: I cant use any collections or other APIs. This part of the course is mainly about using Arrays and loops etc, not advanced Java stuff.
remove is an overloaded method, there is remove(int) which removes the item at the index specified and there is remove(T) which removes the first object int the list that is equal to the argument you passed in
since you passed an int to the method not an Integer, the first method is chosen
the simpliest modification to your code is replacing range.remove(temp); with range.remove(range.indexOf(temp)); or range.remove((Integer)temp)
also you have to call generator.nextInt(x+1); or else the program will be stuck in an infinite loop
You can just replace range.remove(temp); with range.removeIf(t -> t == temp);
Random generator = new Random();
ArrayList<Integer> range = new ArrayList<Integer>();
ArrayList<Integer> generated = new ArrayList<Integer>();
int x = 10;
int count = 0;
for(int i = 0; i<x+1; i++){
range.add(i);
}
while(range.isEmpty() != true){
int temp = generator.nextInt(x-1);
count++;
generated.add(temp);
if(range.contains(temp)){
range.removeIf(t -> t == temp);
}
}
OR You can use Iterator to remove from the List
for (Iterator<Integer> it = range.iterator(); it.hasNext(); ) {
Integer obj= it.next();
if (obj == temp) {
// Remove the current element from the iterator and the list.
it.remove();
break;
}
}
One more issue in your logic
int temp = generator.nextInt(x-1); The random number you are generating doesn't contain all the numbers. It should be int temp = generator.nextInt(x+2);
Hope the below will meet your requirement.
Random random = new Random();
int x = 3;
List<Integer> range = new ArrayList<>();
for(int i = 0; i <x+1; i++) {
range.add(i);
}
List<Integer> list = new ArrayList<>();
while (!list.containsAll(range)) {
list.add(random.nextInt(x + 1));
}
System.out.println(list);
I have a problem to write more lucidity program for random numbers without repeating. My code works but its not really nice.
I tried many thinks especially i just played with loops
for(int i=1; i<=pole.length;i++){
while(p<=13){
i=rd.nextInt(13)+1;
if(pole[i]==i){
}
else{
System.out.println`(i+"-"+p);
pole[i]=i;
p++;
if(i>Max){
Max=i;
}
}
i=Max;
}
I expect 13 numbers without repeating this one works but how to write it easier
i try to solve you problem
1st way:
Integer[] arr = new Integer[13];
int i = 0;
for (;;) {
if (i == 13) {
break;
}
int random = (int) (Math.random() * 100);
if (!Arrays.asList(arr).contains(random)) {
arr[i] = random;
i++;
}
}
2nd way:
List<Integer> list = new ArrayList<>();
while (list.size()<13) {
Integer random = (int )(Math.random() * 100);
if(!list.contains(random)){
list.add(random);
}
}
If for some reason you do not want to use Collections.shuffle(), you can also achieve the same using Set.
Set<Integer> set = new LinkedHashSet<>();
while (set.size() < 13)
set.add((int) (Math.random() * 101));
Please keep in mind, you will also have to check if the random number range is much greater than the set size (In the above example, you need to make sure 101 is always greater than the number of unique numbers needed i.e 13, else you would end up in a very long/infinite while loop)
I'm making a Sudoku program, and I wanted to store every combination of x bits in an 81-bit integer into a list. I want to be able to then shuffle this list, iterate through it, and each on-bit will represent a cell that is to be removed from an existing Sudoku grid, x depending on difficulty. My program then tests this unique puzzle to see if it's solvable, if not, continue to the next combination. Do you guys understand? Is there a better way?
Currently I have a for-loop with a BigInteger, adding 1 every iteration, and testing to see if the resulting number has a number of bits on equal to 55. But this takes LOOOOOONG time. I don't think there's enough time in the universe to do it this way.
LOOP: for(BigInteger big = new BigInteger("36028797018963967");
big.compareTo(new BigInteger("2417851639229258349412351")) < 0;
big = big.add(big.ONE))
{
int count = 0;
for(int i = 0; i < 81; i++)
{
if(big.testBit(i)) count++;
if(count > 55) continue LOOP;
}
//just printing first, no arraylist yet
if(count == 55) System.out.println(big.toString(2));
}
As you already noticed, storing all combinations in a list and then shuffling them is not a viable option.
Instead, you can obtain a shuffled stream of all combinations, by using the Streamplify library.
import org.beryx.streamplify.combination.Combinations;
...
SudokuGrid grid = new SudokuGrid();
int[] solvedPuzzle = IntStream.range(0, 81).map(i -> grid.get(i)).toArray();
int k = 55;
new Combinations(81, k)
.shuffle()
.parallelStream()
.map(removals -> {
int[] puzzle = new int[81];
System.arraycopy(solvedPuzzle, 0, puzzle, 0, 81);
for(int i : removals) {
puzzle[i] = 0;
}
return puzzle;
})
.filter(puzzle -> resolveGrid(new SudokuSolver(new Candidates(puzzle))))
//.limit(10)
.forEach(puzzle -> System.out.println(Arrays.toString(puzzle)));
You probably don't want to generate all puzzles of a given difficulty, but only a few of them.
You can achieve this by putting a limit (see the commented line in the above code).
Certainly there are methods that will finish before you die of old age. For example:
Make an array (or BitSet, as David Choweller suggested in the comments) to represent the bits, and turn on as many as you need until you have enough. Then convert that back into a BigInteger.
I appreciate any feedback. The following seems to be a better option than my initial idea, since I believe having a list of all possible combinations would definitely give an out of memory error. It's not perfect, but this option takes out a random cell, tests to see if its solvable, if not put the last taken number back, and continue to remove the next random cell until enough cells have been taken out, or start over.
int[] candidates = new int[81];
SudokuGrid grid = new SudokuGrid();
LOOP: while(true)
{
ArrayList<Integer> removals = new ArrayList<Integer>();
for(int i = 0; i < 81; i++)
{
removals.add(i);
candidates[i] = grid.get(i);
}
Collections.shuffle(removals);
int k = 55;
for(int i = 0; i < k; i++)
{
int num = candidates[removals.get(i)];
candidates[removals.get(i)] = 0;
cand = new Candidates(candidates);
SudokuSolver solver = new SudokuSolver(cand);
if(!resolveGrid(solver))
{
candidates[removals.get(i)] = num;
k++;
if(k > removals.size())
continue LOOP;
}
}
break;
}
This takes about 5 seconds to solve. It's a bit slower than I wanted it to be, but a lot of it depends on the way I coded the solving strategies.
I have this code for setting random values to true in a boolean[][], without making any duplicates:
int a = 0;
int b = 0;
int counter = 0;
for (int i=0; i<=50; i++) {
do {
a = randomizer.nextInt(hoogte);
b = randomizer.nextInt(breedte);
/**debug variable*/
counter++;
} while (bommaker[a][b]);
bommaker[a][b] = true;
}
After testing for a while, I noticed something was wrong, so I added a counter to check it. Every time I run the program, there comes a different number out of "counter". One time it was 57 while the other time even 63. But I have set the loop to exactly 51. This means the code isn't working as it should. Can somebody explain why it generates more than 51 numbers, and give a possible solution?
You have to remember that you have a loop within a loop. The OUTTER loop is limited to 51 executions, but the inner loop will cause a random number of iterations (an extra iteration for each time it sees that the array has already been set to true).
Other than the counter value being greater than you expected, what about the code is not working?
move out the counter++ line from do while loop
int a = 0;
int b = 0;
int counter = 0;
for (int i=0; i<=50; i++) {
do {
a = randomizer.nextInt(hoogte);
b = randomizer.nextInt(breedte);
/**debug variable*/
} while (bommaker[a][b]);
counter++;
bommaker[a][b] = true;
}
I have the following code to set 10 random values to true in a boolean[][]:
bommaker = new boolean[10][10];
int a = 0;
int b = 0;
for (int i=0; i<=9; i++) {
a = randomizer.nextInt(9);
b = randomizer.nextInt(9);
bommaker[a][b] = true;
}
However, with this code, it is possible to have the same value generated, and therefore have less then 10 values set to random. I need to build in a checker, if the value isn't already taken. And if it is already taken, then it needs to redo the randomizing. But I have no idea how to do that. Can someone help me?
simplest solution, not the best:
for (int i=0; i<=9; i++) {
do {
a = randomizer.nextInt(10);
b = randomizer.nextInt(10);
} while (bommaker[a][b]);
bommaker[a][b] = true;
}
You're problem is similar to drawing cards at random from a deck if I'm not mistaken...
But first... The following:
randomizer.nextInt(9)
will not do what you want because it shall return an integer between [0..8] included (instead of [0..9]).
Here's Jeff's take on the subject of shuffling:
http://www.codinghorror.com/blog/2007/12/shuffling.html
To pick x spot at random, you could shuffle your 100 spot and keep the first 10 spots.
Now of course seen that you'll have only 10% of all the spots taken, simply retrying if a spot is already taken is going to work too in reasonable time.
But if you were to pick, say, 50 spots out of 100, then shuffling a list from [0..99] and keeping the 50 first value would be best.
For example here's how you could code it in Java (now if speed is an issue you'd use an array of primitives and a shuffle on the primitives array):
List<Integer> l = new ArrayList<Integer>();
for (int i = 0; i < 100; i++) {
l.add(i);
}
Collections.shuffle(l);
for (int i = 0; i < n; i++) {
a[l.get(i)/10][l.get(i)%10] = true;
}