shuffle Domino stones in list c# - c#

I have Domino class
public Class Domino(){
public int SideA{get;set;}
public int SideB{get;set;}
public Domino(int sideA,int sideB){
SideA = sideA;
SideB = SideB;
}
}
and manager class where I create List of it and Shuffle It
public class Manager{
private List<Domino> _dominoes = new List<Domino>();
private void CreateDomino(){
for(int i=0;i<7;i++){
for(int j=i;j<7;j++){
_dominoes.Add(new Domino(i,j));
}
}
}
private void Shuffle(){
RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
int n = _dominoes.Count;
while (n > 1)
{
byte[] box = new byte[1];
do provider.GetBytes(box);
while (!(box[0] < n * (Byte.MaxValue / n)));
int k = (box[0] % n);
n--;
T value = _dominoes[k];
_dominoes[k] = _dominoes[n];
_dominoes[n] = value;
}
}
}
}
the shuffle method works fine it randomizes the dominoes list but the problem is that, when I send the first 7 stones to the player class, there are almost every time 4 same stone (same I mean for example 1/2, 1/1,1/4, 1/5 , one of stone number is same as others one) i tried 1000 times and it made 300 times it's quite big number, so how could I shuffle it to decrease it?

The List class is based upon an Array. As such it accepts the array accessor []. Instead of shuffling your list (which is somewhat resource intensive) and then iterating through your list, you could create an array of integers from 0 to _dominoes.Count -1 and randomize that, then just iterate through that array accessing _dominoes[MyIndexValue]. Then you're just randomizing an array of value types (integers) and your list of dominoes never changes.

When you do the shuffle like this:
int n = _dominoes.Count;
while (n > 1)
{ ...
int k = (box[0] % n);
n--;
T value = _dominoes[k];
_dominoes[k] = _dominoes[n];
_dominoes[n] = value;
}
Your pieces towards the beginning of the list can only be swapped with other pieces from the beginning of the list.
E.g. if n = 2 then k = box[0] % 2 which can only be either 0 or 1.
Don't do that - instead, use the entire range for the potential swap candidate:
int k = (box[0] % _dominoes.Count);

Related

Way to extract positive and negative numbers from one array to another two (positive and negative)

I'm studying c# and I was wondering if there is any way to extract positive and negative numbers (integers) from one array to others two, one that contains the positive numbers and the other negative ones
I've tried something like
public static void Main(string[] args)
{
int[] num = new int[50];
Random objeto = new Random();
int i = 0;
for (i = 1; i <= 50; i++)
{
Console.WriteLine("Random numbers:");
num[1] = objeto.Next(-50, 50);
Console.WriteLine(num[1] + "");
}
Console.ReadKey(); here
}
I have to create two other arrays
int[] positive_numbers = int new [N]
int[] negative_numbers = int new [N]
And I guess I should create a method, but I do not know how I have to do it.
You could use LINQ:
var positiveNumbers = numbers.Where(n => n > 0).ToArray();
var negativeNumbers = numbers.Where(n => n < 0).ToArray();
Or an alternative approach is to count how many even and odd numbers you have, create two arrays and then populate them. This assumes that you want the arrays to be exactly the correct length.
// Variables to store counts of positive and negative numbers
int positiveCount = 0;
int negativeCount = 0;
// Because we'll be building new arrays, we need to track our
// position within them, so we create two variables to do that
int positiveIndex = 0;
int negativeIndex = 0;
// loop through once to count the positive and negative numbers
foreach (var number in numbers)
{
if (number > 0)
{
++positiveCount; // same as positiveCount = positiveCount + 1
}
else if (number < 0)
{
++negativeCount;
}
}
// now we know how many +ve and -ve numbers we have,
// we can create arrays to store them
var positiveNumbers = new int[positiveCount];
var negativeNumbers = new int[negativeCount];
// loop through and populate our new arrays
foreach (var number in numbers)
{
if (number > 0)
{
positiveNumbers[positiveIndex++] = number;
// number++ will return the value of number before it was incremented,
// so it will first access positiveNumbers[0] and then positiveNumbers[1], etc.
// each time we enter this code block.
}
else if (number < 0)
{
negativeNumbers[negativeIndex++] = number;
}
}
An alternative approach to the initial count would be to define both arrays to be the same length as the numbers array, and then use positiveIndex and negativeIndex to determine the maximum populated index in the positiveNumbers and negativeNumbers arrays. The downside is that it uses a little more memory (but memory is cheap for such a small set), and the upside is that you only have to loop through once so it's more performant.
If your situation allows, it might be easier to use generic lists instead:
var positiveNumbers = new List<int>();
var negativeNumbers = new List<int>();
foreach (var number in numbers)
{
if (number > 0)
{
positiveNumbers.Add(number);
}
else if (number < 0)
{
negativeNumbers.Add(number);
}
}
Generic lists are basically fancy wrappers around internal arrays. The list starts out with an array of a relatively small size. As you add items to the list, more arrays are generated to store all of your items. You can see the current overall size of the internal arrays by checking the list's .Capacity property. Do not confuse Capacity with Count. Count shows the number of items actually in your list, whereas Capacity shows the number of items your list can hold before expanding.
Note that in these answers, zeroes will be excluded since you only asked for positive and negative numbers, and zero is neither. As highlighted by Max Play's comment, you should change > to >= if you consider zero to be positive.
Assuming you'll handle 0 as positive, add a method to check for positive.
private static bool isNegtive(int number)
{
return number < 0;
}
I'd use list over array for unknown quantities. It'd go something like this:
public static void SeparateRandomNumbers()
{
IList<int> positive_numbers = new List<int>();
IList<int> negative_numbers = new List<int>();
Random objeto = new Random();
for (int i = 0; i < 50; i++)
{
var number = objeto.Next(-50, 50);
if (isNegtive(number))
{
negative_numbers.Add(number);
}
else
{
positive_numbers.Add(number);
}
}
}

How to generate unique random integers that do not duplicate

I have created a short program that creates 3 random integers between 1-9 and stores them in an array, however, I would not like any of them to repeat, that is, I would like each to be unique. Is there an easier way to generate 3 unique integers other than having to iterate through the array and comparing each integer to each other? That just seems so tedious if I were to increase my array to beyond 3 integers.
This is my code to generate 3 random numbers. I saw other code in Java, but I thought maybe C# has a easier and more efficient way to do it.
var number = new Numbers[3];
Random r = new Random();
for ( int i = 0; i < number.Length; i++)
{
number[i] = new Numbers(r.Next(1,9));
}
Console.WriteLine("The Three Random Numbers Are:");
foreach(Numbers num in number)
{
Console.WriteLine("{0}", num.Number);
}
I would do something like this:
var range = Enumerable.Range(1, 8);
var rnd = new Random();
var listInts = range.OrderBy(i => rnd.Next()).Take(3).ToList();
You could make an array or a list of the numbers that might be generated, e.g. 0, 1, 2, 3. Then you generate a number from 0 to this list's length, e.g. 2 and pick list[2] so for the next time you only have 0, 1, 3 in your list.
It takes longer to generate it, especially for long lists but it doesn't repeat numbers.
using System;
using System.Collections.Generic;
public class Test
{
static Random random = new Random();
public static List<int> GenerateRandom(int count)
{
// generate count random values.
HashSet<int> candidates = new HashSet<int>();
// top will overflow to Int32.MinValue at the end of the loop
for (Int32 top = Int32.MaxValue - count + 1; top > 0; top++)
{
// May strike a duplicate.
if (!candidates.Add(random.Next(top))) {
candidates.Add(top);
}
}
// load them in to a list.
List<int> result = new List<int>();
result.AddRange(candidates);
// shuffle the results:
int i = result.Count;
while (i > 1)
{
i--;
int k = random.Next(i + 1);
int value = result[k];
result[k] = result[i];
result[i] = value;
}
return result;
}
public static void Main()
{
List<int> vals = GenerateRandom(10);
Console.WriteLine("Result: " + vals.Count);
vals.ForEach(Console.WriteLine);
}
}
Grate explanation and answers from here
Source http://ideone.com/Zjpzdh

Compare current and last value in list

There is a moving average suppose: 2, 4, 6 , 8 , 10...n;
Then add the current value (10) to list
List<int>numHold = new List<int>();
numhold.Add(currentvalue);
Inside the list:
the current value is added
10
and so on
20
30
40 etc
by using
var lastdigit = numHold[numhold.Count -1];
I can get the last digit but the output is
current: 10 last: 10
current: 20 last: 20
the output should be
current: 20 last: 10
Thanks
Typically, C# indexers start from 0, so the first element has index 0. On the other hand, Count/Length will use 1 for one element. So your
numHold[numhold.Count - 1]
actually takes the last element in the list. If you need the one before that, you need to use - 2 - though be careful you do not reach outside of the bounds of the list (something like Math.Max(0, numhold.Count - 2) might be appropriate).
You can also store the values in separate variables:
List<int> nums = new List<int> { 1 };
int current = 1;
int last = current;
for (int i = 0; i < 10; i++)
{
last = current;
current = i * 2;
nums.Add(current);
}
Console.WriteLine("Current: {0}", current);
Console.WriteLine("Last: {0}", last);
Question is so unclear, but if ur using moving average to draw a line graph 📈 you would use a circular buffer which can be implemented by urself utilizing an object that contains an array of specified size, and the next available position. You could also download a nuget package that already has it done.
A relatively simple way to calculate a moving average is to use a circular buffer to hold the last N values (where N is the number of values for which to compute a moving average).
For example:
public sealed class MovingAverage
{
private readonly int _max;
private readonly double[] _numbers;
private double _total;
private int _front;
private int _count;
public MovingAverage(int max)
{
_max = max;
_numbers = new double[max];
}
public double Average
{
get { return _total / _count; }
}
public void Add(double value)
{
_total += value;
if (_count == _max)
_total -= _numbers[_front];
else
++_count;
_numbers[_front] = value;
_front = (_front+1)%_max;
}
};
which you might use like this:
var test = new MovingAverage(11);
for (int i = 0; i < 25; ++i)
{
test.Add(i);
Console.WriteLine(test.Average);
}
Note that this code is optimised for speed. After a large number of iterations, you might start to get rounding errors. You can avoid this by adding to class MovingAverage a slower method to calculate the average instead of using the Average property:
public double AccurateAverage()
{
double total = 0;
for (int i = 0, j = _front; i < _count; ++i)
{
total += _numbers[j];
if (--j < 0)
j = _max - 1;
}
return total/_count;
}
Your last item will always be at position 0.
List<int>numHold = new List<int>();
numHold.add(currentvalue); //Adding 10
numHold[0]; // will contain 10
numHold.add(currentvalue); //Adding 20
numHold[0]; // will contain 10
numHold[numhold.Count - 1]; // will contain 20
the better way to get first and last are
numHold.first(); //Actually last in your case
numHold.last(); //first in your case

How to efficiently generate all combinations (at all depths) whose sum is within a specified range

Suppose you have a set of values (1,1,1,12,12,16) how would you generate all possible combinations (without repetition) whose sum is within a predefined range [min,max]. For example, here are all the combinations (of all depths) that have a range between 13 and 17:
1 12
1 1 12
1 1 1 12
16
1 16
This assumes that each item of the same value is indistinguishable, so you don't have three results of 1 12 in the final output. Brute force is possible, but in situations where the number of items is large, the number of combinations at all depths is astronomical. In the example above, there are (3 + 1) * (2 + 1) * (1 + 1) = 24 combinations at all depths. Thus, the total combinations is the product of the number of items of any given value + 1. Of course we can logically throw out huge number of combinations whose partial sum is greater than the max value (e.g. the set 16 12 is already bigger than the max value of 17, so skip any combinations that have a 16 and 12 in them).
I originally thought I could convert the input array into two arrays and increment them kind of like an odometer. But I am getting completely stuck on this recursive algorithm that breaks early. Any suggestions?
{
int uniqueValues = 3;
int[] maxCounts = new int[uniqueValues];
int[] values = new int[uniqueValues];
// easy code to bin the data, just hardcoding for example
maxCounts[0] = 3;
values[0] = 1;
maxCounts[1] = 2;
values[1] = 12;
maxCounts[2] = 1;
values[2] = 16;
GenerateCombinationsHelper(new List<int[]>(), 13, 17, 0, 0, maxCounts, new int[3], values);
}
private void GenerateCombinationsHelper(List<int[]> results, int min, int max, int currentValue, int index, int[] maxValues, int[] currentCombo, int[] values)
{
if (index >= maxValues.Length)
{
return;
}
while (currentCombo[index] < maxValues[index])
{
currentValue += values[index];
if (currentValue> max)
{
return;
}
currentCombo[index]++;
if (currentValue< min)
{
GenerateCombinationsHelper(results, min, max, currentValue, index + 1, maxValues, currentCombo, values);
}
else
{
results.Add((int[])currentCombo.Clone());
}
}
}
Edit
The integer values are just for demonstration. It can be any object that has a some sort of numerical value (int, double, float, etc...)
Typically there will only be a handful of unique values (~10 or so) but there can be several thousands total items.
Switch the main call to:
GenerateCombinationsHelper2(new List<int[]>(), 13, 17, 0, maxCounts, new int[3], values);
and then add this code:
private void GenerateCombinationsHelper2(List<int[]> results, int min, int max, int index, int[] maxValues, int[] currentCombo, int[] values)
{
int max_count = Math.Min((int)Math.Ceiling((double)max / values[index]), maxValues[index]);
for(int count = 0; count <= max_count; count++)
{
currentCombo[index] = count;
if(index < currentCombo.Length - 1)
{
GenerateCombinationsHelper2(results, min, max, index + 1, maxValues, currentCombo, values);
}
else
{
int sum = Sum(currentCombo, values);
if(sum >= min && sum <= max)
{
int[] copy = new int[currentCombo.Length];
Array.Copy(currentCombo, copy, copy.Length);
results.Add(copy);
}
}
}
}
private static int Sum(int[] combo, int[] values)
{
int sum = 0;
for(int i = 0; i < combo.Length; i++)
{
sum += combo[i] * values[i];
}
return sum;
}
It returns the 5 valid answers.
The general tendency with this kind of problem is that there are relatively few values that will show up, but each value shows up many, many times. Therefore you first want to create a data structure that efficiently describes the combinations that will add up to the desired values, and only then figure out all of the combinations that do so. (If you know the term "dynamic programming", that's exactly the approach I'm describing.)
The obvious data structure in C# terms would be a Hashtable whose keys are the totals that the combination adds up to, and whose values are arrays listing the positions of the last elements that can be used in a combination that could add up to that particular total.
How do you build that data structure?
First you start with a Hashtable which contains the total 0 as a key, and an empty array as a value. Then for each element of your array you create a list of the new totals you can reach from the previous totals, and append your element's position to each one of their values (inserting a new one if needed). When you've gone through all of your elements, you have your data structure.
Now you can search that data structure just for the totals that are in the range you want. And for each such total, you can write a recursive program that will go through your data structure to produce the combinations. This step can indeed have a combinatorial explosion, but the nice thing is that EVERY combination produced is actually a combination in your final answer. So if this phase takes a long time, it is because you have a lot of final answers!
Try this algo
int arr[] = {1,1,1,12,12,16}
for(int i = 0;i<2^arr.Length;i++)
{
int[] arrBin = BinaryFormat(i); // binary format i
for(int j = 0;j<arrBin.Length;j++)
if (arrBin[j] == 1)
Console.Write("{0} ", arr[j]);
Console.WriteLine();
}
This is quite similar to the subset sum problem which just happens to be NP-complete.
Wikipedia says the following about NP-complete problems:
Although any given solution to such a problem can be verified quickly,
there is no known efficient way to locate a solution in the first
place; indeed, the most notable characteristic of NP-complete problems
is that no fast solution to them is known. That is, the time required
to solve the problem using any currently known algorithm increases
very quickly as the size of the problem grows. This means that the
time required to solve even moderately sized versions of many of these
problems can easily reach into the billions or trillions of years,
using any amount of computing power available today. As a consequence,
determining whether or not it is possible to solve these problems
quickly, called the P versus NP problem, is one of the principal
unsolved problems in computer science today.
If indeed there is a way to solve this besides brute-forcing through the powerset and finding all subsets which sum up to a value within the given range, then I would be very interested in hearing it.
An idea for another implementation:
Create from the list of numbers a list of stacks, each stack represents a number that appear in the list, and this number is pushed into the stack as many times as he appeared in the numbers list. more so, this list is sorted.
The idea is that you iterate through the stack list, in each stack you pop one number at a time if it doesn't exceed the max value and recall the function, and perform an additional call of skipping the current stack.
This algorithm reduces many redundant computations like trying to add different elements which have the same value when adding this value exceeds the maximal value.
I was able to solve pretty large problems with this algorithm (50 numbers and more), depending on the min and max values, obviously when the interval is very big the number of combinations may be huge.
Here's the code:
static void GenerateLimitedCombinations(List<int> intList, int minValue, int maxValue)
{
intList.Sort();
List<Stack<int>> StackList = new List<Stack<int>>();
Stack<int> NewStack = new Stack<int>();
NewStack.Push(intList[0]);
StackList.Add(NewStack);
for (int i = 1; i < intList.count; i++)
{
if (intList[i - 1] == intList[i])
StackList[StackList.count - 1].Push(intList[i]);
else
{
NewStack = new Stack<int>();
NewStack.Push(intList[i]);
StackList.Add(NewStack);
}
}
GenerateLimitedCombinations(StackList, minValue, maxValue, 0, new List<int>(), 0);
}
static void GenerateLimitedCombinations(List<Stack<int>> stackList, int minValue, int maxValue, int currentStack, List<int> currentCombination, int currentSum)
{
if (currentStack == stackList.count)
{
if (currentSum >= minValue)
{
foreach (int tempInt in CurrentCombination)
{
Console.Write(tempInt + " ");
}
Console.WriteLine(;
}
}
else
{
int TempSum = currentSum;
List<int> NewCombination = new List<int>(currentCombination);
Stack<int> UndoStack = new Stack<int>();
while (stackList[currentStack].Count != 0 && stackList[currentStack].Peek() + TempSum <= maxValue)
{
int AddedValue = stackList[currentStack].Pop();
UndoStack.Push(AddedValue);
NewCombination.Add(AddedValue);
TempSum += AddedValue;
GenerateLimitedCombinations(stackList, minValue, maxValue, currentStack + 1, new List<int>(NewCombination), TempSum);
}
while (UndoStack.Count != 0)
{
stackList[currentStack].Push(UndoStack.Pop());
}
GenerateLimitedCombinations(stackList, minValue, maxValue, currentStack + 1, currentCombination, currentSum);
}
}
Here's a test program:
static void Main(string[] args)
{
Random Rnd = new Random();
List<int> IntList = new List<int>();
int NumberOfInts = 10, MinValue = 19, MaxValue 21;
for (int i = 0; i < NumberOfInts; i++) { IntList.Add(Rnd.Next(1, 10));
for (int i = 0; i < NumberOfInts; i++) { Console.Write(IntList[i] + " "); } Console.WriteLine(); Console.WriteLine();
GenerateLimitedCombinations(IntList, MinValue, MaxValue);
Console.ReadKey();
}

Byte Array Manipulation - Interview Question

I was having this discussion with my friend who had this question asked to him in the Interview. The Question goes like this. Write a Function which takes in a byte array(2 dimensional) as input along with an Integer n, The initial assumption is all the elements of M*N byte array is zero and the problem is to fill 'n' Byte array elements with value 1, For instance if M=5 and N=5 and the n value is 10 the Byte array should've 10/25 elements to be 1 and rest of the 15 values to be 0. The values filled should be random and one cell in byte array should be filled only once. I was fascinated to try solving this on my own. I've attached the code I've come up with so far.
public Boolean ByteArrayFiller(int a,int b, int n)
{
int count = n;
int iLocalCount = 0;
byte[,] bArray= new byte[a,b];
for (int i = 0; i <a; i++)
for (int j = 1; j <b; j++)
bArray[i, j] = 0;
Random randa= new Random();
int iRandA = randa.Next(a);
int iRandB = randa.Next(b);
while (iLocalCount < n)
{
if (bArray[iRandA, iRandB] == 0)
{
bArray[iRandA, iRandB] = 1;
iLocalCount++;
}
iRandA = randa.Next(a);
iRandB = randa.Next(b);
continue;
}
//do
//{
// //iRandA = randa.Next(a);
// //iRandB = randa.Next(b);
// bArray[iRandA,iRandB]=1;
// iLocalCount++;
//} while (iLocalCount<=count && bArray[iRandA,iRandB]==0);
return true;
}
The code i wrote is in C# but it's straight forward to understand. It's able to do the purpose of the question( I did some trials runs and results came out correctly) perfectly but I have used Random object in C#(Equivalent to Math.Rand in Java) to fill up the byte array and I keep thinking if Rand returns the same values for a and b. There is a good chance for this to go indefinitely. Is that the purpose of the question? or Does the solution that i came up for this question is good enough!
I am curious to see how experts here solve this problem? I am just looking for new ideas to expand my horizon. Any pointers would be greatly appreciated. Thanks for taking the time to read this post!
A while loop trying random locations until it finds a good one is generally a very bad approach. If n = M*N, then the last one will have a probability of 1/(M*N) of finding a match. If M*N are sufficiently large, this can be extremely inefficient.
If M*N is not too large, I would create a temporary array of M*N size, fill it with the numbers 0 through (M*N)-1, and then permutate it - i.e. you walk through it and swap the current value with that of a random other value.
Then you go to the first n elements in your array and set the appropriate cell. (row = value / columns, col = value % columns).
I would treat the array, logically, as a one-dimensional array. Fill the first n positions with the prescribed value, and then shuffle the array.
Given a byte array, and the number of rows and columns in the array, and assuming that the array is already filled with 0:
int NumElements = NumRows * NumCols;
for (int i = 0; i < NumElementsToFill; ++i)
{
int row = i / NumRows;
int col = i % NumCols;
array[row, col] = 1;
}
// Now shuffle the array
Random rnd = new Random();
for (int i = 0; i < NumElements; ++i)
{
int irow = i / NumRows;
int icol = i % NumCols;
int swapWith = rnd.Next(i+1);
int swapRow = swapWith / NumRows;
int swapCol = swapWith % NumCols;
byte temp = array[irow, icol];
array[irow, icol] = array[swapRow, swapCol];
array[swapRow, swapCol] = temp;
}
The key here is converting the one-dimensional index into row/col values. I used / and %. You could also use Math.DivRem. Or create Action methods that do the get and set for you.
Choose a number, which is larger than both N and M and is prime (or co-prime to both N and M). Let's call this number p.
Loop until you've set x numbers:
Generate a random number less than N*M. Call this number `l`.
Then the next place to put the number will be `p*l%(N*M)`, if that position hasn't been set.
A downside to this approach is that if the array is filling up, you'll have more collisions.
Bascially, you need to choose n unique random numbers from range [0, p) (where p = M * N), and map them to positions of 2-dimensional array.
Naive approaches are 1) generate non-unique numbers with retry 2) fill an array with numbers from 0 to p-1, shuffle it and take first n numbers (takes O(p) time, O(p) memory).
Another approach is to choose them with the following algorithm (O(n2) time, O(n) memory, code in Java):
public Set<Integer> chooseUniqueRandomNumbers(int n, int p) {
Set<Integer> choosen = new TreeSet<Integer>();
Random rnd = new Random();
for (int i = 0; i < n; i++) {
// Generate random number from range [0, p - i)
int c = rnd.nextInt(p - i);
// Adjust it as it was choosen from range [0, p) excluding already choosen numbers
Iterator<Integer> it = choosen.iterator();
while (it.hasNext() && it.next() <= c) c++;
choosen.add(c);
}
return choosen;
}
Mapping of generated numbers to positions of 2-dimensional array is trivial.

Categories