C#: How to assign random int values to variables? - c#

I have made a dice class that includes a method which uses random.next to determine a random int value from 1-6.
Fairdice.cs:
class FairDice
{
//defining variable and property
private Random rnd;
public int Current { get; private set; }
public FairDice()
{
rnd = new Random(Guid.NewGuid().GetHashCode());
Current = 0;
}
public int FRoll()
{
Current = rnd.Next(1, 7);
return Current;
}
RollDice.cs that features a loop for printing.
static class RollDice
{
public static void Roll(this int count, Action action)
{
for (int i = 0; i < count; i++)
{
action();
}
}
}
Program.cs includes this code, which prints out 5 random values between 1-6:
FairDice fd = new FairDice();
5.Roll(() => Console.WriteLine("Dice: " + fd.FRoll()));
Problem: I wish to assign the random values in each variable and store and save them in either a list or array for future use.
clarification:
lets say it prints out the numbers: 1, 2, 3, 4, 5 - i then wish to assign each value a variable: a = 1, b = 2, ... f = 5.
and/or simply store the values in an array {1, 2, 3, 4, 5}
Is there any way to do this?

If you want to store the values returned by calling FRoll then you could do something like this:
FairDice fd = new FairDice();
var numbers = new List<int>();
5.Roll(() => numbers.Add(fd.FRoll())); // Append the values to the list as we generate them
var firstNumberRolled = numbers[0]; // Access the values later
Console.WriteLine($"The first number rolled was {firstNumberRolled}");

Once the throw results are into an array you can extract assign variables as necessary.
class FairDice
{
private static int _seed;
private static ThreadLocal<Random> threadLocal = new ThreadLocal<Random>
(() => new Random(Interlocked.Increment(ref _seed)));
static FairDice()
{
_seed = Environment.TickCount;
}
private static Random Rng { get { return threadLocal.Value; } }
public int Roll()
{
return Rng.Next(1, 6);
}
}
static class RollDice
{
public static int[] Roll(this int count, FairDice dice)
{
int[] values = new int[count];
for (int i = 0; i < count; i++)
{
values[i] = dice.Roll();
}
return values;
}
}
class Program
{
static void Main(string[] args)
{
FairDice fd = new FairDice();
int[] values = 5.Roll(fd);
Console.WriteLine(String.Join(",", values.Select(x => x.ToString()).ToArray()));
}
}

add this to FairDice (lines with '*'):
class FairDice
* private int[] returnedValues;
public int FRoll()
{
Current = rnd.Next(1, 7);
* returnedValues[Current]++;
return Current;
}
*public void GetreturnedValues()
* {
* for (int i = 1; i < 7; i++)
* {
* Console.WriteLine("{0}: {1}", i, returnedValues[i]);
* }
* }
After this adding d.GetreturnedValues(); to you Program.cs will show how many time the different values where thrown.

Related

How to assign a new value from Method's Array to the Variable?

My main goal is to create a Method, where it is possible to enter a number, out of which a Method will choose some other numbers (according to the purpose) and combine them in Array.
I need this Array and its value to be flexible, so I decided to create a new variable, that is within the scope for both Container() and Main() methods. Then I assigned a value from Container() to optainer, but it didn't work (foreach doesn't display all numbers from Container(), only the first one). Where is my problem?
static int[] optainer;
static void Container()
{
uint numb = uint.Parse(Console.ReadLine());
for (int i = 1000000; i >= 1; i--)
{
if (numb % i == 0)
{
optainer = new int[] { i };
}
}
}
static void Main(string[] args)
{
Console.WriteLine("Enter num. from 1 to 1 000 000");
Container();
foreach (int iw in optainer)
{
Console.WriteLine(iw);
}
// Expected: few numbers according to the condition; Real result: 1
```
You have always only one element in optainer,
this line is the error
optainer = new int[] { i }; you create always a new array with only one item and the last is always 1.
you can change in this way
static List<int> optainer = new List<int>();
static void Main(string[] args)
{
Console.WriteLine("Enter num. from 1 to 1 000 000");
Container();
foreach (int iw in optainer)
{
Console.WriteLine(iw);
}
}
static void Container()
{
uint numb = uint.Parse(Console.ReadLine());
for (int i = 1000000; i >= 1; i--)
{
if (numb % i == 0)
{
optainer.Add(i);
}
}
}
I'm sure there's a sexier way to do this, but try this:
static void Container()
{
uint numb = uint.Parse(Console.ReadLine());
for (int i = 1000000; i >= 1; i--)
{
if (numb % i == 0)
{
int size = optainer.Length + 1;
Array.Resize(ref optainer, size);
optainer[size - 1] = i;
}
}
}
Everytime you write
optainer = new int[] { i };
you create a new list(you overwrite the old one) you would have to append
to the array. Therefore you would need to know the size of the array.
To save memory you should use something more dynamic like lists.
Here is an explanation how to add a value:
Adding values to a C# array

C# Am I doing "Bays & Durham Randomization by Shuffling" correctly?

I tried to improvise a random number generator by using the "Bays & Durham Randomization by Shuffling" algorithm. I followed a tutorial online and made this code:
public int[] GenerateRandomSequence_Improved(int n, int min, int max)
{
int[] seq = new int[n];
for(int i = 0; i < n; i++)
{
int rand = GenerateNextRandomNumber(min, max);
rand = min + rand % (max + 1 - min);
seq[i] = rand;
}
return seq;
}
I wanna know if I did it correctly or not..
EDIT: This is the code for the GenerateNextRandomNumber method
public int GenerateNextRandomNumber(int min, int max)
{
return cSharpRNG.Next(min,max);
}
According to Knuth TAOCP Vol. 2 p. 34 Algorithm B, the proper algorithm is the following,
public class BaysDurham
{
private readonly int[] t;
private int y; // auxiliary variable
// Knuth TAOCP Vol. 2 p. 34 Algorithm B
public BaysDurham(int k)
{
t = new int[k];
for (int i = 0; i < k; i++)
{
t[i] = rand.Next();
}
y = rand.Next();
}
public int Next()
{
var i = (int)((t.Length * (long) y) / int.MaxValue); // mitigates the bias
y = t[i];
t[i] = rand.Next();
return y;
}
private readonly Random rand = new Random();
}
I let you adapt the range of the output, but just know that the formula you use with the modulo introduce significant bias and makes the distribution non-uniform please look at this.
Here is what I believe proper implementation of the Bays-Durham shuffling. Warning wrt bias in indexing due to modulo operation is right though.
.NET Core 2.2, x64 Win10
using System;
using System.Diagnostics;
namespace BaysDurhamShuffling
{
public class BaysDurhamRNG
{
public int[] _table;
public int _xnext;
public Random _rng = null;
public BaysDurhamRNG(int n, int seed = 312357) {
Debug.Assert(n > 1);
_rng = new Random(seed);
_table = new int [n];
for(int k = 0; k != n; ++k) {
_table[k] = _rng.Next();
}
_xnext = _rng.Next();
}
public int next() {
var x = _xnext; // store return value
var j = _xnext % _table.Length; // form the index j into the table
_xnext = _table[j]; // get jth element of table and to copy it to the output stream on next call
_table[j] = _rng.Next(); // replace jth element of table with next random value from input stream
return x; // return what was stored in next value
}
}
class Program
{
static void Main(string[] args)
{
var rng = new BaysDurhamRNG (16, 12345);
for(int k = 0; k != 30; ++k) {
var x = rng.next();
Console.WriteLine($"RV = {x}");
}
}
}
}

Creating an array that holds both integers and datetime C#

I am trying to create an array that looks like this when printed out:
[0] 100 10:00
[1] 60 10:04
I have created the array, I need to now add the values to the array:
int[,] ArrayOfSensors = new int[41,41];
/// <summary>
/// Generates Random Blood Pressure Systolic Value
/// </summary>
/// <returns></returns>
public int RandomBPSValue()
{
Random random = new Random();
int RandomNumber = random.Next(90, 120);
for (int runs = 1; runs < 41; runs = runs + 5)
{
ArrayOfSensors[runs, DateTime.Now] = RandomNumber;
}
return RandomNumber;
}
You can use a Tuple<int, DateTime> for your code. Read the MSDN doc here.
Your code will look somewhat similar to
var myComplexArray = new Tuple<int, DateTime>[5]; //array of 5 for example
Random random = new Random();
for (int runs = 0; runs < 5; runs++)
{
int num = random.Next(90, 120); //use your real data here
myComplexArray[runs] = new Tuple<int, DateTime>(num, DateTime.Now.AddMinutes(runs));
}
//to show your desired output
for (var i = 0; i < myComplexArray.Length; i++)
{
Console.WriteLine(string.Format("[{0}] {1} {2}", i, myComplexArray[i].Item1,
myComplexArray[i].Item2.ToShortDateString()));
}
Try something like:
public class Observation
{
public int Systolic { get; set; }
public DateTime ObsTime { get; set;}
}
public List<Observation> RandomBPSValue()
{
List<Observation> myList = new List<Observation>();
Random random = new Random();
int RandomNumber = random.Next(90, 120);
for (int runs = 1; runs < 41; runs = runs + 5)
{
Observation observation = new Observation() { ObsTime = DateTime.Now, Systolic = runs};
myList.Add(observation);
}
return myList;
}

how to add value to array in the next postion

i am building a small app that act like a digital camera, and on my takephoto function i want to insert a random number to my array(i succeed doing that), my problem is that when i take multiple pictures the value always go into the first postion. my code:
public override void TakePhoto()
{
Random rnd = new Random();
int photo = rnd.Next(1, 10);
for (int i = 0; i < 1; i++)
{
MemoryCard.buffer[i] = photo;
}
}
class Program
{
static void Main(string[] args)
{
DigitalCamera digitalCamera =
new DigitalCamera("kodak", 43, newMemoryCard, 3);
digitalCamera.TakePhoto();
digitalCamera.TakePhoto();
digitalCamera.TakePhoto();
}
}
how do i jump to the next position after each photo?
You esplicitly say to put next value in the first position.
Look on your code:
for (int i = 0; i < 1; i++)
{
MemoryCard.buffer[i] = photo;
}
i is always 0
To resolve this, just save an i value into some global variable, or next index accept like a parameter in the TakePhoto(...) function.
Example:
int curindex = 0; //GLOBAL VARIABLE
public override void TakePhoto()
{
Random rnd = new Random();
int photo = rnd.Next(1, 10);
if(curindex < MemoryCard.buffer.Length) //IF CURINDEX LESS THE TOTAL ARRAY LENGTH
{
MemoryCard.buffer[curindex] = photo; //ASSIGN PHOTO IN CURRENTINDEX
curindex ++; //INCEREMENT CURRENTINDEX
}
}
You have a bug in your for-loop, i assume you want to use the Length of the buffer variable instead
You are calling TakePhoto too fast, therefore you create the Random always with the same seed, hence always the same "random" number is generated.
Instead pass the Random instance as parameter to the method or use a field variable.
public override void TakePhoto(Random rnd)
{
int photo = rnd.Next(1, 10);
for (int i = 0; i < MemoryCard.buffer.Length; i++)
{
MemoryCard.buffer[i] = photo;
}
}
Now always use the same instance:
Random r = new Random();
DigitalCamera digitalCamera = new DigitalCamera("kodak", 43, newMemoryCard, 3);
digitalCamera.TakePhoto(r);
digitalCamera.TakePhoto(r);
digitalCamera.TakePhoto(r);
I think following modification to your code will resolve your issue:
class DigitalCamera
{
static int currentPhotoNumber = 0;
private Random rnd = new Random();
public override void TakePhoto()
{
int photo = rnd.Next(1, 10);
MemoryCard.buffer[currentPhotoNumber++] = photo;
}
}
class Program
{
static void Main(string[] args)
{
DigitalCamera digitalCamera = new DigitalCamera("kodak", 43, newMemoryCard, 3);
digitalCamera.TakePhoto();
digitalCamera.TakePhoto();
digitalCamera.TakePhoto();
}
}
There is a logic error in your code here:
for (int i = 0; i < 1; i++)
{
MemoryCard.buffer[i] = photo;
}
If you look at your for-loop variables, the loop is running from i=0, to i<1. Which basically means that the loop is only running once (for i=0).
You need to increase i each time, perhaps
MemoryCard.buffer[MemoryCard.numberofphotos] = photo;
MemoryCard.numberofphotos++;

Generating random numbers from giving numbers in c#

User enters numbers to 10 textbox and i sent them to an array. Now i want to generate random numbers from this array. What can i do?
Something like this:
public class Randomizer<T>
{
private readonly Random _random = new Random();
private readonly IList<T> _numbers;
public Randomizer(IList<T> numbers)
{
_numbers = numbers;
}
public T Next()
{
int idx = _random.Next(0, _numbers.Count);
return _numbers[idx];
}
}
Usage:
var r = new Randomizer<int>(new int[] { 10, 20, 30, 40, 50 });
for (int i = 0; i < 100; i++)
Console.Write(r.Next() + " ");
Or do you want to shuffle the array?
[Edit]
To shuffle the array, you can use the Fisher–Yates shuffle shown in this post:
// https://stackoverflow.com/questions/108819/110570#110570
public class Shuffler
{
private Random rnd = new Random();
public void Shuffle<T>(IList<T> array)
{
int n = array.Count;
while (n > 1)
{
int k = rnd.Next(n);
n--;
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
}
If you want the interface to be same as the Randomizer class above, you can modify it to use the Shuffler class:
public class Randomizer<T>
{
private readonly Shuffler _shuffler = new Shuffler();
private readonly IList<T> _numbers;
public Randomizer(IList<T> numbers)
{
_numbers = new List<T>(numbers);
_shuffler.Shuffle(_numbers);
}
volatile int idx = 0;
public T Next()
{
if (idx >= _numbers.Count)
{
_shuffler.Shuffle(_numbers);
idx = 0;
}
return _numbers[idx++];
}
}
Note that the code is not thread safe, so some locking should be implemented if Next method might be called simultaneously from multiple threads.
Seed the standard System.Random class with a value from the array? If you need your random numbers to depend on ALL array items, then just XOR them all.
public static Random BuildSeededRandom(int[] data)
{
if ( data == null || data.Length < 1 )
return new Random();
int xor = 0;
foreach ( var i in data )
xor ^= i;
return new Random(xor);
}

Categories

Resources