Random Number Generator (rand) isn't Random? - c++

I'm generating mazes, I can only pick the first or last column. And I can only choose an even row (if you start the row index at 1). I have the correct logic, except that the maze start position isn't random. If I generate 50 mazes, that are all 20x20, all starting positions will be the same. Any help will be appreciated. Thanks.
void Maze::generatePath()
{
int startingColumn = -1;
int startingRow = -1;
srand (time(NULL));
int side = rand() % 2;
startingColumn = (width - 1) * side; // will get first or last column
int row = rand() % height; // 0 -> height - 1
if(row % 2 == 0) // even, add one, or subtract if last row
{
if(row + 1 >= width)
startingRow = row - 1;
else
startingRow = row + 1;
}
else
{
startingRow = row; // odd, keep it
}
grid[startingRow][startingColumn] = ' '; // starting character is blank
}
I call this method every time I generate a new maze. This code is to get the starting position. I haven't written the rest.

Only call srand once when your program starts. By calling it over and over in the same second, you keep resetting the random number generator to the same state.

If you need better randomness you might use as random seed something better than time(NULL).
It may be for example /dev/random(or more practically /dev/urandom) device on unix-like systems.
For really hardcore cases some real radnomness based on physical phenomena might be desired.
For instance this one: http://photonics.anu.edu.au/qoptics/Research/qrng.php

Related

How to make so Random Number (under 50 milliseconds) wont repeat twice

I'm making script and it generates random numbers in milliseconds (Range 20-100), let's say it generated delays : 30, 40 , 42 (All < (less than) 50)
Now I want to make it so 4th delay cant be again less than 50, I tried this:
I tried using for loop, but my when i use this code script doesn't work at all anymore / it won't toggle or anything.
Just imagine you made script and it generates random numbers from 20-100 and you dont want 4 in row delays that are less than 50, what would you do? Thanks.
for (int i = 0; i < 4;)
{
// Total Delay aka delay1+delay2
if (totaldelay < 50)
{
i++;
}
// Should make totaldelay > 50
if (i == 3)
{
delay1 = RandomInt(75, 105);
}
// Reset to 0 so it checks from 0 again
if (total > 50)
{
i = 0;
}
}
If I understand the question correctly, you don't want four consecutive numbers to be all less than 50. You can achieve this by simply keeping a count and adjusting your behaviour so that you generate a different number if the previous three were all less than 50.
If you're looking for a standalone C++ function to do that (give you one random number per call, with your specific added limitations), you can use something like:
int getMyRand() {
// Keep track of how many consecutive under-50s already done.
// Careful in multi-threaded code, may need thread-local instead.
static int consecUnder50 = 0;
int number;
// If last three were all < 50, force next one to be >= 50.
if (consecUnder50 == 3) {
number = rand() % 51 + 50; // 50-100 (inclusive).
} else {
number = rand() % 81 + 20; // 20-100 (inclusive).
}
// If less, record it, otherwise restart count.
if (number < 50) {
++consecUnder50;
} else {
consecUnder50 = 0;
}
// Give caller the number.
return number;
}
Don't forget to seed the random number generator before using this, and be aware that C++ has better random number generators, although rand() is usually fine unless you're a statistician or cryptographer :-)

How to trace error with counter in do while loop in C++?

I am trying to get i to read array with numbers and get the smaller number, store it in variable and then compare it with another variable that is again from two other numbers (like 2,-3).
There is something wrong in the way I implement the do while loop. I need the counter 'i' to be updated twice so it goes through I have 2 new variables from 4 compared numbers. When I hard code it n-1,n-2 it works but with the loop it gets stuck at one value.
int i=0;
int closestDistance=0;
int distance=0;
int nextDistance=0;
do
{
distance = std::min(values[n],values[n-i]); //returns the largest
distance=abs(distance);
i++;
nextDistance=std::min(values[n],values[n-i]);
nextDistance=abs(closestDistance); //make it positive then comp
if(distance<nextDistance)
closestDistance=distance;//+temp;
else
closestDistance=nextDistance;
i++;
}
while(i<n);
return closestDistance;
Maybe this:
int i = 0;
int m = 0;
do{
int lMin = std::min(values[i],values[i + 1]);
i += 2;
int rMin = std::min(values[i], values[i + 1]);
m = std::min(lMin,rMin);
i += 2;
}while(i < n);
return m;
I didn't understand what you meant, but this compares values in values 4 at a time to find the minimal. Is that all you needed?
Note that if n is the size of values, this would go out of bounds. n would have to be the size minus 4, leading to odd exceptional cases.
The issue with your may be in the call to abs. Are all the values positive? Are you trying to find the smallest absolute value?
Also, note that using i += 2 twice ensures that you do not repeat any values. This means that you will go over 4 unique values. Your code goes through 3 in each iteration of the loop.
I hope this clarified.
What are you trying to do in following lines.
nextDistance=std::min(values[n],values[n-i]);
nextDistance=abs(closestDistance); //make it positive , then computed

How to create a random number that doesn't repeat?

I have a variable that will either become 1 or 0, and all I know is rand()% 2.
The problem is when I loop it it keeps becoming either 1 for about four times straight then 0, or 0 for straight 6 times then 1.
I want it to be like 0 for once or twice, then 1, then 0 again. Something like that.
Is it possible to do this?
You either want a random number or a predictable result. You can't choose the amount of randomness, the whole point of a random number generator is to generate something unpredictable.
But what you can do is simply use the random number in a different way. If you want, say, at most, 4 consecutive runs of 0 or 1 you could determine the count of consecutive numbers using rand and generate the numbers yourself:
int number = 0;
for (int runs = 0; runs < 100; ++runs) {
int count = rand() % 4;
for (int i = 0; i < (count ? count : 1); ++i) { // Ensure at least 1 run
printf("%d", number);
}
number = 1 - number;
}
See codepad example:
http://codepad.org/OKe5Agib
If you really want to have only runs of 1 or 2, while maintaining some randomness, you can keep track of it like this;
int nextRandomIshThing( ) {
static int n1 = 0;
static int n2 = -1;
if( n1 != n2 ) {
n1 = n2;
// use a high-order bit, which supposedly has better randomness
// 14 because the standard guarantees that rand() produces at least
// 15 bits of randomness (not sure why that exactly)
n2 = (rand( ) >> 14) & 1;
} else {
n2 = !n2;
}
return n2;
}
http://codepad.org/HTTtPezu
But beware that depending on how you're using this, it means that users can "game" your system; "I've seen 2 1's, therefore the next must be 0!". A truly random source will always produce long sequences. There is a 1 in 8 chance for a truly random source to produce 4 1's or 0's in a row, and a 1 in 16 chance of 5. When you consider that you don't care where exactly the run starts, this becomes even more likely. If you want to be fair, embrace this instead of fighting it!
Oh and don't forget to srand.

Petrol Pumps circular tour

Problem:
Suppose there is a circle. There are n petrol pumps on that circle.
You are given two sets of data.
The amount of petrol that petrol pump will give.
Distance from that petrol pump to the next petrol pump.
Calculate the first point from where a truck will be able to complete
the circle
I just solved the problem. I want to know if I solved the problem correctly.
Algorithm:
I started from starting point and I tried adding rest of the petrol left travelling the distance. if value is < 0 and if we reach start again then no solution exists. otherwise keep looping till you reach the end. End is always start + 1; Also I know the algorithm O(n). Can some one also explain using a good logic how its O(n).
int PPT(int P[], int D[], int N)
{
int start = 0, end = 1, cur_ptr = P[0] - D[0], i = start;
while(start != end)
{
if(cur_ptr < 0)
{
start = (i + 1) % N;
end = (start + 1) % N;
cur_ptr = 0;
if(start == 0) return -1; // if start again becomes 0 then no solution exists
}
i = (i + 1) % N;
cur_ptr += P[i] - D[i];
}
}
start != end always holds. Therefore, your algorithm produces an infinite loop if there is a solution. Furthermore, I don't understand, why end should be start + 1.
Here is another approach:
Consider the following function:
This function calculates the remaining petrol just before arriving at pump i. The function can be visualized as follows:
The function starts at petrol = 0. You see that this configuration is not valid, because at pump 4 the remaining petrol is negative. Furthermore, there is a solution, because the remaining petrol at the last pump (again the start pump) is positive.
What happens, if we choose a different start? The basic shape of the function remains the same. It is just moved to the left. Furthermore, because the function starts at petrol = 0, the function is decreased by C(start). The remaining fuel at the end does not play a role in this case, because it would increase the current petrol.
The task is to find a start that allows all C(i) to be positive. This is obviously the case for the minimal C(i), in this case for start = 4.
Calculating the function C(i) can be done iteratively, and therefore, in linear time. You iterate once from 0 to N. The minimum can be found during this iteration in constant time (by comparing with the current minimum). Therefore, the overall time complexity is O(n).
I don't think the solution you provide is correct. Whenever cur_ptr is greater than 0, you are not updating the variable end. Therefore, suppose if at every station P[i] > D[i], the loop will keep running till infinity.
Besides a few more changes, I believe you need to add end = (end + 1) % N; somewhere. I have modified the code and it gives the correct solution.
int PPT(int[] P, int[] D, int N)
{
int start = 0, end = 1, cur_ptr = P[0] - D[0];
bool none = false;
while (start != end)
{
if (cur_ptr < 0)
{
start = (start + 1) % N;
if (start == 0) // all stations have been traveled but solution is not yet available
{
none = true;
break;
}
end = (start + 1) % N;
cur_ptr = P[start] - D[start];
}
else
{
end = (end + 1) % N;
cur_ptr += P[end] - D[end];
}
}
return none?-1:start;
}

How do I hide numbers from a table of sudoku?

I'm trying to write a program that will give the user a sudoku puzzle to solve. But I'm stuck on hiding numbers by difficulty level. How do I do that?
Considering you have a 9x9 matrix of integers
int sudoku[9][9];
and this matrix is filled with a correct Sudoku, just replace some entries by 0 for example. Remember that Sudoku are often symmetric around their centre.
// Hide (i,j) from solution
sudoku[i][j] = 0;
sudoku[8-i][8-j] = 0;
Each time you hide two numbers from the solution, check back with your solver that it can still be solved. Finally, associate difficulty with a certain amount of loops of such a process
for (k=0; k < difficulty; ) {
// randomly select (i,j) so that:
// - 0 <= i <= 4
// - 0 <= j <= 4
// - (i,j) != (4, 4)
// - solution[i][j] != 0 (i.e., (i, j) has not already been randomly selected
save1 = solution[i][j];
solution[i][j] = 0;
save2 = solution[8-i][8-j];
solution[8-i][8-j] = 0;
if (!can_be_solved(solution)) {
// (i, j) was not a good choice!
solution[i][j] = save1;
solution[8-i][8-j] = save2;
}
else {
// it's still OK, let's go one step further
k += 1;
}
}
//
}
You could write a sudoku solver and then just randomly generate sudoku boards and test if they are valid with your sudoku solver. In your method that generates the boards, you could have an input that specifies the number of numbers that will be shown on the beginning board. Take a look at the standard number of numbers for different difficulties and base it off of that.