I'm receiving some inconsistent behavior from the Random.NextDouble().
Regularly, the console would freeze and the cpu usage would increase dramatically until I closed it down. I ran the debugger and found that the cause of the freezing was Random.NextDouble(). I added some lines for debugging purposes, but the code is as follows:
double generateCatenationRate()
{
double catenation = 999.999; //random value to see if it pops up down there
double uniformValue;
double int_covalence = covalence.original;
double dist = int_covalence - 4;
int counter = 0;
while (true)
{
counter++;
uniformValue = utils.getRandomDouble(); //goes bad here!
if (uniformValue <= 0.15)
{
catenation = Math.Abs(utils.normalize(dist, 0, 4)) + uniformValue;
if (catenation < 0 || catenation > 1)
{
if (counter > 10000)
{
Console.WriteLine("Went nuclear!");
break; //break so console doesn't stall out
}
continue;
}
else
{
break;
}
}
}
Console.WriteLine("Took "+counter+" iterations.");
return 1 - catenation;
}
And:
public static double getRandomDouble()
{
Init();
return random.NextDouble();
}
Lastly:
private static void Init()
{
if (random == null) random = new Random();
}
It typically does not stall out, but running it several times successively produces output such as:
Took 4 iterations.
Took 3 iterations
Took 3 iterations.
Took 23 iterations.
Took 12 iterations.
Took 4 iterations.
Went nuclear!
Took 10007 iterations.
Can anyone explain why Random.NextDouble() occasionally seems to create an infinite loop? Looking around, I suspect it has something to do with how the values are seeded, but any insight would be appreciated; would love to fix this issue.
Thank you!
EDIT: covalence.original is always an integer between 1 and 8 (inclusive). normalize() performs min-max normalization, producing a number from 0-1 based on an input and a range. Neither of these seem to contribute to the problem, however.
If I understand correctly then the value of dist and utils.normalize(dist, 0, 4) never changes.
So if int_covalence = 8 then dist = 4 and utils.normalize(dist, 0, 4) = 1, correct?
Since the chance of generating 0.0 is pretty small, that will make catenation virtually always greater than 1 and the check if (catenation < 0 || catenation > 1) always true.
why not just generate the samples directly rather than using rejection sampling?
public static double generateCatenationRate(Random rng, double coval_norm) {
double low = Math.abs(coval_norm) + 0.15;
double delta = 1. - low;
if (delta < 0) {
throw new IllegalArgumentException("impossible given covalence");
}
return low + delta * rng.nextDouble();
}
where coval_norm is whatever you get back from utils.normalize. if we write it this way we get visibility of the "impossible" condition and can do something about it, rather than just looping.
I have the following problem:
I have three elements a, b and c. And also integers from 0 to 100. How can I get all the possible combinations to look like:
a 0 b 0 c 0
a 1 b 0 c 0
a 0 b 1 c 0
a 0 b 0 c 1
a 1 b 1 c 0
...
a 100 b 100 c 100
and so on? I am using C# but I am rather struggling to find the correct algorithm independently of programming language. Unfortunately I do not really understand carthesian products etc.
You say you want to
find the correct algorithm independently of programming language
So I shall try to answer this using the minimum of programming language features. The example I shall give assumes the programming language has expandable lists, arrays, arrays of arrays and the ability to shallow clone an array. These are common programming features, so hopefully this will be OK.
To solve this problem, you need to produce all the combinations of 3 sets of N integers where each set consists the integers from 0..N-1. (The set of combinations of a set of sets - which is what this is - is called the Cartesian Product of those sets.)
The solution below uses recursion, but we don't need to worry about stack overflow because the stack depth does not exceed the number of sets to combine - in this case, 3. (Normally with recursion you would try to use a stack class to manage it, but that makes the code more complicated.)
How it works:
combine() recursively iterates through all elements of each set, and at each level of recursion it begins processing the elements of the next set.
So the outer level of recursion begins iterating over all the elements of set[0], and for each element it fills in the next item of the current combination with that element.
Then: if that was the last set, the combination is complete and it is output. Otherwise: a recursive call is made to start filling in the elements from the next set.
Once we have all the combinations, we can just iterate through them and intersperse them
with a, b and c as per your requirement.
Putting this together:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var sets = createSets(3, 10);
var combinations = Combinations(sets);
foreach (var combination in combinations)
{
Console.WriteLine($"a {combination[0]} b {combination[1]} c {combination[2]}");
}
}
static int[][] createSets(int numSets, int intsPerSet)
{
int[][] sets = new int[numSets][];
// All the sets are the same, so we can just use copies of it rather than create multiples.
int[] oneSet = new int[intsPerSet];
for (int i = 0; i < intsPerSet; ++i)
oneSet[i] = i;
for (int i = 0; i < numSets; ++i)
sets[i] = oneSet;
return sets;
}
public static List<int[]> Combinations(int[][] sets)
{
var result = new List<int[]>();
combine(sets, 0, new int[sets.Length], result);
return result;
}
static void combine(int[][] sets, int set, int[] combination, List<int[]> output)
{
for (int i = 0; i < sets[set].Length; ++i)
{
combination[set] = sets[set][i];
if (set < (sets.Length - 1))
combine(sets, set + 1, combination, output);
else
output.Add((int[])combination.Clone());
}
}
}
}
Notes
This is an inefficient implementation because it returns all the combinations in one huge list. I kept it this way for simplicity (and to reduce the number of program language features required for its implementation). A better solution in C# would be to pass in an Action<int[]> to be called with each combination - then the results wouldn't need to be returned via a huge list.
This doesn't produce the results in the same order as your sample output. I have assumed that this doesn't matter!
A great Linq implementation of the Cartesian Product is presented by Eric Lippert here. I highly recommending reading it!
If the order of the output doesn't matter, this should be enough:
for(int i = 0; i <= 100; i++){
for(int j = 0; j <= 100; j++){
for(int k = 0; k <= 100; k++){
Console.WriteLine($"a {i} b {j} c {k} ");
}
}
}
OUTPUT
a 0 b 0 c 0
a 0 b 0 c 1
a 0 b 0 c 2
a 0 b 0 c 3
...
a 100 b 100 c 100
Modifying a plugin for a Rust game server, and I'm not too great at C#. I currently have the system set up to print the votes to chat every time a new vote comes in, but want it based on percentage or every 5 votes. How would I do that? This is my current code.
public int tallyVotes() {
int yesVotes = 0;
foreach (var votes in votesReceived) {
if (votes.Value)
yesVotes = yesVotes + 1;
}
return yesVotes;
couldn't you return yesVotes/5 as an integer, essentially giving you 1 vote for every 5.
int voteWeighting = 5;
return (int)yesVotes/voteWeighting;
if you're looking for when to print it then the generic fizz buzz solution would fix it.
int printWeighting = 5;
if (yesVotes%printWeighting ==0)
{
//print stuff here
}
this works by using the modulus function "a%b" it will return the remainder when you divide a by b and as such return a number less than "b" but greater or equal to zero. as such if you only ever increment by 1 the number, then when a mod b is 0 you have incremented b times.
Fizzbuzz example
I'm running this class and method
public class DiceRoll
{
static Random _r =new Random();
public int Random6()
{
int n = _r.Next(1, 7);
return n;
}
}
I'm trying to use it inside an if statement in another class like so:
if (input == "d6")
{
int dice = diceRoll.Random6();
Console.WriteLine(dice);
}
my question is this. If I call diceRoll.Random6(); with a multiplier like this diceRoll.Random6() * 2; Is it creating two random numbers and adding them or is it just taking one and multiplying it by two?
I think it's probably the latter but I just wanted to check before I got into convoluted programming.
If it is the latter is there a way to make my program call multiple instances of Random6 without going diceRoll.Random6() + diceRoll.Random6(); That works ok for doing it twice but if I want to do it four or six times it'll become inelegant.
Thanks in advance.
Call the method from within a loop
int result = 0;
for(int i = 0; i < 10; i++)
{
result += Random6();
}
It just generates 1 random number then multiplies it by 2
you can just do it in a loop, or if you want to be fancy
var sum = Enumerable.Range(1, 6).Sum(x => diceRoll.Random6())
which you might want to break down into...
var rolls = Enumerable.Range(1, 6).Select(x => diceRoll.Random6()).ToList();
var sumOfRolls = rolls.Sum();
that way you have the sum and a list of each individual roll.
I need to select N amount of events a day randomly, but they can't be too close to each other (M). So the N events have to be a at least M apart within a particular window (W). In this case the window I am thinking of is 12 hours.
N = the number of events
T = the time at which the event should occur (UTC)
M = the minimum factor they should be apart (Hours).
W = the window of the events (Now to Now + 12 hours).
U = the user (probably not important to this problem)
I could probably figure this out, but I thought it would be a fun StackOverflow question and interested how people would solve it.
Thanks in advance :)
Update: Moved answer to an answer
Try this:
It splits the available time (window - count * minimum) randomly, then sorts the times and adds the minimum amount to produce the final event array T[].
static Random rnd=new Random();
static void Main(string[] args)
{
double W=12;
double M=1.0;
int N=7;
double S=W-(N-1)*M;
double[] T=new double[N];
for(int i=0; i<N; i++)
{
T[i]=rnd.NextDouble()*S;
}
Array.Sort(T);
for(int i=0; i<N; i++)
{
T[i]+=M*i;
}
Console.WriteLine("{0,8} {1,8}", "#", "Time");
for(int i=0; i<N; i++)
{
Console.WriteLine("{0,8} {1,8:F3}", i+1, T[i]);
}
// With N=3, Window 12h, Min. Span = 5h
// # Time
// 1 0.468
// 2 5.496
// 3 10.529
// With N=7, Window 12h, Min. Span = 1h
// # Time
// 1 0.724
// 2 2.771
// 3 4.020
// 4 5.790
// 5 7.331
// 6 9.214
// 7 10.673
}
As a check also, when minimum times completely covers the time window then the events are equally spaced. So for 3 events on a 12hr window with minimum time 6hrs this algorithm produces events at 0.0 ,6.0 and 12.0 as expected.
You can use the idea I had for my question here: Generating non-consecutive combinations, essentially requiring that you only solve the M=0 case.
If you want to skip the description, the algorithm is given at the end of the post, which has no unpredictable while loops etc, and is guaranteed to be O(N log N) time (would have been O(N), if not for a sorting step).
Long Description
To reduce the general M case to the M=0 case, we map each possible combination (with the "aleast M constraint") to a combination without the "at least M" apart constraint.
If your events were at T1, T2, .., TN such that T1 <= T2 -M, T2 <= T3 - M ... you map them to the events Q1, Q2, .. QN such that
Q1 = T1
Q2 = T2 - M
Q3 = T3 - 2M
...
QN = TN - (N-1)M.
These Q satisfy the property that Q1 <= Q2 <= ... <= QN, and the mapping is 1 to 1. (From T you can construct the Q, and from Q you can construct the T).
So all you need to do is generate the Q (which is essentially the M=0 case), and map them back to the T.
Note that the window for generating Q becomes [Now, Now+12 - (N-1)M]
To solve the M=0 problem, just generate N random numbers in your window and sort them.
Final Algorithm
Thus your whole algorithm will be
Step 1) Set Window = [Start, End - (N-1)M]
Step 2) Generate N random numbers in the Window.
Step 3) Sort the numbers generated in Step 2. Call them Q1, Q2, .. , QN
Step 4) Create Ti with the formula Ti = Qi + (i-1)M, for i = 1 to N.
Step 5) Output T1,T2,..,TN
If we assume that events occur instantaneously (and, as such, can occur at time = end of window, you could do something like this:
//Using these, as defined in the question
double M;
int N;
DateTime start; //Taken from W
DateTime end; //Taken from W
//Set these up.
Random rand = new Random();
List<DateTime> times;
//This assumes that M is
TimeSpan waitTime = new TimeSpan.FromHours(M);
int totalSeconds = ((TimeSpan)end-start).TotalSeconds;
while( times.Count < N )
{
int seconds = rand.Next(totalSeconds);
DateTime next = start.AddSeconds(seconds);
bool valid = true;
if( times.Count > 0 )
{
foreach( DateTime dt in times )
{
valid = (dt > next && ((TimeSpan)dt - next) > waitTime) ? true : false;
if( !valid )
{
break;
}
}
}
if( valid )
{
times.Add(next);
}
}
Now, in a 12 hour window with at least an hour after each event before the next, you'd best have a small N - my psuedocode above does not check to see if it's possible to fit N events into X time with M hours between each event.
timeItems = new List();
int range;
double randomDouble;
for i = 1 to N
{
range = W/M;
//assumes generate produces a random number between 0 and 1 (exclusive)
randomDouble = RandomGenerator.generate() * (range);
T = Math.floor(randomDouble)*M;
timeItems.add(T);
}
return timeItems
First consider the job of generating one event such that there are (n-1) more events to generate (need to be separated by at least M each) and total of w time left.
Time t can be in between 0 to w-(n-1)m. The average value of t should be w/(n-1). Now, use any of your favorite distribution (I recommend poisson) to generate a random number with mean w/(n-1). If the number is higher than w-n-1)m, then generate again. That will give your t.
Recursively call (offset=offset+t, w=w-t, n=n-1, m=m) to generate more numbers.
def generate(offset, w, n, m):
mean = w/(n-1);
t=ininity;
while (t> (w-(n-1)m)):
t= poisson( w/(n-1) )
return [t+offset] + generate(offset+t, w-t, n-1, m)
I have not coded for corner conditions and other cases which I leave it to you.
Here is my solution. You get some weird behavior if your time apart and numOfEvents are conflicting. Play around with it and see what happens.
using System;
using System.Collections.Generic;
namespace RandomScheduler
{
class Program
{
public static Random R = new Random();
static void Main()
{
var now = DateTime.Now;
var random = new Random((int)now.Ticks);
const int windowOfHours = 12;
const int minimumTimeApartInHours = 2;
const int numOfEvents = 5;
// let's start the window 8 AM
var start = new DateTime(now.Year, now.Month, now.Day, 8, 0, 0, 0);
// let's end 12 hours later
var end = start.AddHours(windowOfHours);
var prev = null as DateTime?;
const int hoursInEachSection = windowOfHours / numOfEvents;
var events = new List<DateTime>();
for (var i = 0; i < numOfEvents; i++)
{
// if there is a previous value
// let's at least start 2 hours later
if (prev.HasValue)
start = prev.Value.AddHours(minimumTimeApartInHours);
DateTime? #event;
do
{
// pick a random double, so we get minutes involved
var hoursToAdd = random.NextDouble()*hoursInEachSection;
// let's add the random hours to the start
// and we get our next event
#event = start.AddHours(hoursToAdd);
// let's make sure we don't go past the window
} while (#event > end);
prev = #event;
events.Add(#event.Value);
}
Console.WriteLine(string.Join("\n", events));
Console.ReadLine();
}
}
}