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

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 :-)

Related

Using modulus to solve coin change question

I'm looking for a different way to solve coin change problem using modulus. Most solutions refer to use of dynamic memory to solve this.
Example:
You are given coins of different denominations and a total amount of
money amount. Write a function to compute the fewest number of coins
that you need to make up that amount. If that amount of money cannot be
made up by any combination of the coins, return -1.
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
The goal is to create a solution using modulus instead.
Here is what I've tried so far. I'm wondering if my variable should be initialized to something other than 0 or I'm updating in the wrong part of the code block.
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int pieces = 0;
int remainder = 0;
for(int i = coins.size()-1; i = 0; i--) {
if (amount % coins[i] == 0)
{
pieces += amount/coins[i];
} else {
pieces += amount/coins[i];
remainder = amount%coins[i];
amount = remainder;
}
}
return pieces;
}
}
I'm expecting the output as above. Stuck and not sure what else to try to get this to work.
I understand what you're trying to do, but your code isn't actually going to accomplish what you think it will. Here's a breakdown of your code:
int coinChange(vector<int>& coins, int amount) {
// Minimum number of coins to sum to 'amount'
int pieces = 0;
int remainder = 0;
// Assuming 'coins' is a non-decreasing vector of ints,
// iterate over all coins, starting from the larger ones,
// ending with the smaller ones. This makes sense, as it
// will use more coins of higher value, implying less
// coins being used
for(int i = coins.size()-1; i = 0; i--) {
// If what's left of the original amount is
// a multiple of the current coin, 'coins[i]',
if (amount % coins[i] == 0)
{
// Increase the number of pieces by the number
// of current coins that would satisfy it
pieces += amount/coins[i];
// ERROR: Why are you not updating the remaining amount?
} else {
// What's left of the original amount is NOT
// a multiple of the current coin, so account
// for as much as you can, and leave the remainder
pieces += amount/coins[i];
remainder = amount%coins[i];
amount = remainder;
}
}
// ERROR: What if amount != 0? Should return -1
return pieces;
}
If you fixed the ERRORs I mentioned above, the function would work ASSUMING that all ints in coins behave as the following:
If a coin, s, is smaller than another coin, l, then l must be a multiple of s.
Every coin has to be >= 1.
Proof of 1:
If a coin, s, is smaller than another coin, l, but l is not a multiple of s, using l as one of the coins in your solution might be a bad idea. Let's consider an example, where coins = [4, 7], and amount = 8. You will iterate over coins in non-increasing order, starting with 7. 7 fits into 8, so you will say that pieces = 1, and amount = 1 remains. Now, 4 doesn't fit into amount, so you don't add it. Now the for-loop is over, amount != 0, so you fail the function. However, a working solution would have been two coins of 4, so returning pieces = 2.
Proof of 2:
If a coin, c is < 1, it can be 0 or less. If c is 0, you will divide by 0 and throw an error. Even more confusingly, if you changed your code you could add an infinite amount of coins valued 0.
If c is negative, you will divide by a negative, resulting in a negative amount, breaking your logic.

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.

Understanding Sum of subsets

I've just started learning Backtracking algorithms at college. Somehow I've managed to make a program for the Subset-Sum problem. Works fine but then i discovered that my program doesn't give out all the possible combinations.
For example : There might be a hundred combinations to a target sum but my program gives only 30.
Here is the code. It would be a great help if anyone could point out what my mistake is.
int tot=0;//tot is the total sum of all the numbers in the set.
int prob[500], d, s[100], top = -1, n; // n = number of elements in the set. prob[i] is the array with the set.
void subset()
{
int i=0,sum=0; //sum - being updated at every iteration and check if it matches 'd'
while(i<n)
{
if((sum+prob[i] <= d)&&(prob[i] <= d))
{
s[++top] = i;
sum+=prob[i];
}
if(sum == d) // d is the target sum
{
show(); // this function just displays the integer array 's'
top = -1; // top points to the recent number added to the int array 's'
i = s[top+1];
sum = 0;
}
i++;
while(i == n && top!=-1)
{
sum-=prob[s[top]];
i = s[top--]+1;
}
}
}
int main()
{
cout<<"Enter number of elements : ";cin>>n;
cout<<"Enter required sum : ";cin>>d;
cout<<"Enter SET :\n";
for(int i=0;i<n;i++)
{
cin>>prob[i];
tot+=prob[i];
}
if(d <= tot)
{
subset();
}
return 0;
}
When I run the program :
Enter number of elements : 7
Enter the required sum : 12
Enter SET :
4 3 2 6 8 12 21
SOLUTION 1 : 4, 2, 6
SOLUTION 2 : 12
Although 4, 8 is also a solution, my program doesnt show it.
Its even worse with the number of inputs as 100 or more. There will be atleast 10000 combinations, but my program shows 100.
The Logic which I am trying to follow :
Take in the elements of the main SET into a subset as long as the
sum of the subset remains less than or equal to the target sum.
If the addition of a particular number to the subset sum makes it
larger than the target, it doesnt take it.
Once it reaches the end
of the set, and answer has not been found, it removes the most
recently taken number from the set and starts looking at the numbers
in the position after the position of the recent number removed.
(since what i store in the array 's' is the positions of the
selected numbers from the main SET).
The solutions you are going to find depend on the order of the entries in the set due to your "as long as" clause in step 1.
If you take entries as long as they don't get you over the target, once you've taken e.g. '4' and '2', '8' will take you over the target, so as long as '2' is in your set before '8', you'll never get a subset with '4' and '8'.
You should either add a possibility to skip adding an entry (or add it to one subset but not to another) or change the order of your set and re-examine it.
It may be that a stack-free solution is possible, but the usual (and generally easiest!) way to implement backtracking algorithms is through recursion, e.g.:
int i = 0, n; // i needs to be visible to show()
int s[100];
// Considering only the subset of prob[] values whose indexes are >= start,
// print all subsets that sum to total.
void new_subsets(int start, int total) {
if (total == 0) show(); // total == 0 means we already have a solution
// Look for the next number that could fit
while (start < n && prob[start] > total) {
++start;
}
if (start < n) {
// We found a number, prob[start], that can be added without overflow.
// Try including it by solving the subproblem that results.
s[i++] = start;
new_subsets(start + 1, total - prob[start]);
i--;
// Now try excluding it by solving the subproblem that results.
new_subsets(start + 1, total);
}
}
You would then call this from main() with new_subsets(0, d);. Recursion can be tricky to understand at first, but it's important to get your head around it -- try easier problems (e.g. generating Fibonacci numbers recursively) if the above doesn't make any sense.
Working instead with the solution you have given, one problem I can see is that as soon as you find a solution, you wipe it out and start looking for a new solution from the number to the right of the first number that was included in this solution (top = -1; i = s[top+1]; implies i = s[0], and there is a subsequent i++;). This will miss solutions that begin with the same first number. You should just do if (sum == d) { show(); } instead, to make sure you get them all.
I initially found your inner while loop pretty confusing, but I think it's actually doing the right thing: once i hits the end of the array, it will delete the last number added to the partial solution, and if this number was the last number in the array, it will loop again to delete the second-to-last number from the partial solution. It can never loop more than twice because numbers included in a partial solution are all at distinct positions.
I haven't analysed the algorithm in detail, but what struck me is that your algorithm doesn't account for the possibility that, after having one solution that starts with number X, there could be multiple solutions starting with that number.
A first improvement would be to avoid resetting your stack s and the running sum after you printed the solution.

Random Number Generator (rand) isn't Random?

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

changing probability of getting a random number

I would like to generate a random number between 0 and 3 and I have the following in my code:
int random = rand() % 4;
This works fine but I would like it to generate 1, 2, and 3 most of the time and 0 only occasionally.
What is the best way to go about this? What are the names of common algorithms to address this problem?
Here's one way. Suppose you want 0, 1, 2, 3 to have a distribution of 5%, 20%, 30%, 45%.
You could do it like this:
double val = (double)rand() / RAND_MAX;
int random;
if (val < 0.05) // 5%
random = 0;
else if (val < 0.25) // 5% + 20%
random = 1;
else if (val < 0.55) // 5% + 20% + 30%
random = 2;
else
random = 3;
Of course it doesn't have to be done with floating-point. I just did it this way since it's more intuitive.
You can use the discrete_distribution class from the random library.
#include <iostream>
#include <random>
#include <ctime>
int main()
{
std::discrete_distribution<> dist({ 1.0, 4.0, 4.0, 4.0 });
std::mt19937 eng(std::time(0));
for (int i=0; i<100; ++i)
std::cout << dist(eng);
}
Demo: http://ideone.com/z8bq4
If you can't use C++11, these classes also exist in boost.
You didn't give exact proportions, but suppose you want 1, 2, and 3 to each occur 32% of the time, and 0 to occur the other 4%. Then you could write:
int random = rand() % 25;
if(random > 0)
random = random % 3 + 1;
(Obviously you'd need to adjust that for different proportions. And the above is just one approach; many similar approaches could work.)
how many numbers have you tested this on? if it is actually true you can instead generate a range from say 0->3999 using a = rand()%4000 and use int = a/1000 this should remove the weight of the apparently under produced zero.
I would just map more values to 1,2,3 from a larger set. For example: 9 and map 1,2,3 => 1, 3,4,5=>2, 6,7,8=>3 and 0 for zero. There are other ways, but I am working within your question
Just code exactly what you want:
int myrand(void)
{
const int percentZero = 10;
if ((rand()%100) < percentZero) return 0;
return 1 + (rand() % 3);
}
You can change the percentage of time zero is returned to whatever you want.
You need to find a probability distribution that works for your case. Since you're only talking about the numbers 0-3 this is quite easy, you could either call rand() again if the first result is a 0, or you could use weights:
int random = rand() % 16;
if(random > 10)
{
random = 3;
}
else if(random > 5)
{
random = 2;
}
else if(random > 0)
{
random = 1;
}
This isn't a particularly elegant, but hopefully it shows you how you can create a custom distribution to fit your needs.