I have array of Bitarray (each element consists of 128 bits) and I want to find duplicate of elements of it.
I tried this code:
Bitarray [] bitsarr=//something;
string g=//convert the array of bitarray to binary string
int numOfBytes = g.Length / 8;
byte[] bytes = new byte[numOfBytes];
for (int i = 0; i < numOfBytes; ++i)
{
bytes[i] = Convert.ToByte(g.Substring(8 * i, 8), 2);
}
int[] bytesAsInts = bytes.Select(x => (int)x).ToArray();
var dict = new Dictionary<int, int>();
foreach (var num in bytesAsInts)
{
if (!dict.ContainsKey(num))
{
dict.Add(num, 0);
}
dict[num]++;
}
foreach (var kvp in dict)
{
Console.WriteLine("{0} repeats {1} times", kvp.Key, kvp.Value);
}
but I don't want to convert it to int because the results will be false.
I want to know the duplication of each element of array of bitarray.
Can anyone help?
You can try to use BitArray.Xor(BitArray) to find duplicates, on MSDN:
The bitwise exclusive OR operation returns true if exactly one operand is true, and returns false if both operands have the same Boolean value
After XOR operation you can check is all bits in BitArray are False:
public static class Extensions
{
public static bool IsAllFalse(this BitArray bitArray)
{
for (int i = 0; i < bitArray.Length; i++)
{
if (bitArray[i] == true)
return false;
}
return true;
}
}
P.S. Mind that BitArray.Xor(BitArray) modifying current object, save values in BitArray object before calling it.
Related
I have some code that wasn't written by myself and I'm trying to use it to build a Poker ICM calculator program. This program takes an array of stack sizes and prize payouts and calculates each players prize equity.
The code works for 3 prizes but when I add a 4th prize I get an index out of bounds error because I'm trying to get permutation[3] when the object only contains indexes 0 to 2. The problem is I can't understand how the size of permuation gets set so I can't figure out how to adjust the code to work for higher numbers of prizes. I'd appreciate some help.
Below is a minimum working example with working and non-working code in the main method and a comment to indicate where the error occurs.
ICMCalculator.cs
class ICMCalculator
{
public double[] CalcEV(int[] structure, int[] chips)
{
//the probability of a players position
double[,] probabilitys = new double[structure.Length, chips.Length];
//the expected value of the player
double[] EVs = new double[chips.Length];
int[] players = new int[chips.Length];
for (int i = 0; i < players.Length; ++i)
players[i] = i;
IEnumerable<int[]> permutations;
for (int i = 0; i < structure.Length; ++i)
{
permutations = (new Permutation()).Enumerate(players, i + 2);
foreach (int[] permutation in permutations)
{
// OUT OF BOUNDS ERROR OCCURS HERE
probabilitys[i, permutation[i]] += CalcPermutationProbability(permutation, chips);
}
}
for (int i = 0; i < structure.Length; ++i)
{
for (int j = 0; j < chips.Length; ++j)
EVs[j] += probabilitys[i, j] * structure[i];
}
return EVs;
}
private double CalcPermutationProbability(int[] permutations, int[] chips)
{
double probability = 1.0F;
int chips_sum = chips.Sum();
for (int i = 0; i < permutations.Length; ++i)
{
probability *= System.Convert.ToDouble(chips[permutations[i]]) / System.Convert.ToDouble(chips_sum);
chips_sum -= chips[permutations[i]];
}
return probability;
}
}
Permutation.cs
class Permutation
{
public IEnumerable<T[]> Enumerate<T>(IEnumerable<T> nums, int length)
{
var perms = _GetPermutations<T>(new List<T>(), nums.ToList(), length);
return perms;
}
private IEnumerable<T[]> _GetPermutations<T>(IEnumerable<T> perm, IEnumerable<T> nums, int length)
{
if (length - perm.Count() <= 0)
{
yield return perm.ToArray();
}
else
{
foreach (var n in nums)
{
var result = _GetPermutations<T>(perm.Concat(new T[] { n }),
nums.Where(x => x.Equals(n) == false), length - perm.Count());
foreach (var xs in result)
yield return xs.ToArray();
}
}
}
}
Utils.cs
class Utils
{
public static string DoubleArrayToString(double[] doubles)
{
StringBuilder sb = new StringBuilder();
foreach (double dub in doubles)
{
sb.AppendLine(Utils.Format2DP(dub));
}
return sb.ToString().Trim();
}
}
Program.cs
static class Program
{
static void Main()
{
// THIS WORKS
ICMCalculator ev = new ICMCalculator();
int[] stacks = new int[] { 4500, 2700, 1800, 1000, 500 };
int[] prizes = new int[] { 84,36,18 };
int prizePool = prizes.Sum();
double[] equity = ev.CalcEV(prizes, stacks);
Console.WriteLine(Utils.DoubleArrayToString(equity));
// THIS THROWS INDEX ERROR
ev = new ICMCalculator();
stacks = new int[] { 4500, 2700, 1800, 1000, 500 };
prizes = new int[] { 84,36,18,9 };
prizePool = prizes.Sum();
equity = ev.CalcEV(prizes, stacks);
Console.WriteLine(Utils.DoubleArrayToString(equity));
}
}
To be clear, I believe that each 'permutation' should be the length of structure.Length. I don't want to avoid the out of bounds error by reducing the max value of i. I think I need to increase the size of each permuation to match structure.Length but I'm unable to figure out how to do this.
If resolved correctly, the code that currently fails should output the values: 50.82, 37.85, 29.16, 19.01, 10.15
I think the problem is in this line:
var result = _GetPermutations<T>(perm.Concat(new T[] { n }),
nums.Where(x => x.Equals(n) == false), length - perm.Count());
Instead, I think it should be
var result = _GetPermutations<T>(perm.Concat(new T[] { n }),
nums.Where(x => x.Equals(n) == false), length);
The problem here is that we are double-counting the length of the permutation found so far when we determine whether to stop further recursion.
The condition length - perm.Count() <= 0 (which can be simplified to perm.Count() >= length) is used to stop further calls to _GetPermutations if the permutation perm generated so far is long enough to be returned. This relies on the parameter length being the required length of the resulting permutations. However, by passing length - perm.Count() in the recursive call to _GetPermutations(), then we are reducing the value of length that inner calls to _GetPermutations() receive, causing them to stop the recursion early with permutations that are too short.
This question already has answers here:
Find two sum function in c#
(15 answers)
Closed 1 year ago.
I'm trying to modify this algorithm which is of complexity O(n2) to something quicker.
the algorithm is supposed to do the following
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].
Any help is appreciated.
using System.Collections.Generic;
public class Solution
{
public int[] TwoSum(int[] nums, int target)
{
int[] output = new int[2];
for (int i = 0; i < nums.Length; i++)
{
for (int n = 0; n < nums.Length; n++)
{
if ((nums[i] + nums[n]) == target)
{
output[0] = n;
output[1] = i;
}
}
}
return output;
}
}
In order to code an O(n) solution, you should loop the elements(numbers) of the array only one time. So, you need to store them in a dictionary. Keys will be numbers, Values will be their indexes. Then will check that is there any key whose value is equal to target - number in the dictionary. Dictionary<TKey, TValue> is a good choice for this problem.
public class Solution {
public int[] TwoSum(int[] nums, int target)
{
//Declare key-value dictionary to store numbers
var set = new Dictionary<int, int>();
//Loop each number in the array until find the complementary number.
for (var i = 0; i < nums.Length; i++)
{
//Assign the element of the array to a integer variable to have an elegant code.
var number = nums[i];
//If the dictionary contains the complementary number then return it.
if (set.ContainsKey(target - number))
{
return new[] {set[target - number], i};
}
//If the current number is not a complementary number then add it to the dictionary.
if (!set.ContainsKey(number))
{
set.Add(number, i);
}
}
//throw the right exception if there is no valid solution.
throw new ArgumentException();
}
}
Assuming that you have good hash function, you can have O(n) complexity. For each p within num you should check if q = k - p exists within num. You can do each each check with O(1) if you use hash based collection (here Dictionary<int, int[]>). The only little problem is p = q = k/2; here we should check if two equal items k/2 are in num.
using System.Linq;
...
public static int[] TwoSum(int[] nums, int k) {
if (nums == null)
throw new ArgumentNullException(nameof(nums));
var dict = nums
.Select((value, index) => new { value = (long)value, index })
.GroupBy(pair => pair.value, pair => pair.index)
.ToDictionary(group => group.Key, group => group.ToArray());
for (int i = 0; i < nums.Length; ++i) {
long p = nums[i];
long q = k - p;
if (dict.TryGetValue(q, out var array))
if (p != q)
return new int[] { i, array[0] };
else if (array.Length >= 2)
return new int[] { array[0], array[1] };
}
return new int[] { -1, -1 };
}
Here I've used long for dictionary key, p and q in order to cope with integer overflow
While everyone debates the fastest algorithm, the following code is quicker than O(n^2) it runs on average O(n log n) and in N space.
using System.Collections.Generic;
public class Solution
{
public int[] TwoSum(int[] nums, int target)
{
int[] output = new int[2];
for (int i = 0; i < nums.Length; i++)
{
for (int n = 1; n < nums.Length; n++)
{
if ((nums[i] + nums[n]) == target)
{
output[0] = n;
output[1] = i;
return output; //early exit giving O(n log n) vs (n^2)
}
}
}
return output; // degenerate case no solution exists
}
}
How can you permutate the set of strings based on the set length, I have lets say 50 values in an array and only want to combine 24 values that is comma delimited Examples: (string1,string2,string3) but without ever repeating the combinations and the order. I have this code below.
class Program
{
static void Main(string[] args)
{
//var values1 = new[] { 1, 2, 3, 4, 5 };
//foreach (var permutation in values1.GetPermutations())
//{
// Console.WriteLine(string.Join(", ", permutation));
//}
var values2 = new[] { "asd", "das", "sad", "q1we", "asd" };
foreach (var permutation in values2.GetPermutations())
{
Console.WriteLine(string.Join(",", permutation));
}
Console.ReadLine();
}
}
public static class SomeExtensions
{
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(this IEnumerable<T> enumerable)
{
var array = enumerable as T[] ?? enumerable.ToArray();
var factorials = Enumerable.Range(0, array.Length + 1)
.Select(Factorial)
.ToArray();
for (var i = 0L; i < factorials[array.Length]; i++)
{
var sequence = GenerateSequence(i, array.Length - 1, factorials);
yield return GeneratePermutation(array, sequence);
}
}
private static IEnumerable<T> GeneratePermutation<T>(T[] array, IReadOnlyList<int> sequence)
{
var clone = (T[])array.Clone();
for (int i = 0; i < clone.Length - 1; i++)
{
Swap(ref clone[i], ref clone[i + sequence[i]]);
}
return clone;
}
private static int[] GenerateSequence(long number, int size, IReadOnlyList<long> factorials)
{
var sequence = new int[size];
for (var j = 0; j < sequence.Length; j++)
{
var facto = factorials[sequence.Length - j];
sequence[j] = (int)(number / facto);
number = (int)(number % facto);
}
return sequence;
}
static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
private static long Factorial(int n)
{
long result = n;
for (int i = 1; i < n; i++)
{
result = result * i;
}
return result;
}
}
How can I be able to combine an array of string (24 values) into 100 rows of unique combination? Can you please explain how and whats the best way on how to do it?
I think that I would do it like this
public static class StringPermutator
{
/// <summary>
/// Class to permutate input values
/// </summary>
/// <param name="inputValues">An array of inputs to be permutated</param>
/// <param name="numberOfResults">The number of outputs we want to have</param>
/// <param name="maxValuesPerRow">The number of values to be combined in each output row</param>
/// <returns>An IEnumerable of unique permutated string ouptuts</returns>
public static IEnumerable<string> Permutate<T>(T[] inputValues, int numberOfResults, int maxValuesPerRow)
{
HashSet<string> output = new HashSet<string>();
Random rnd = new Random();
//Loop until we have the number of results we want
while (output.Count < numberOfResults)
{
StringBuilder sb = new StringBuilder();
HashSet<int> usedIndexes = new HashSet<int>();
//Loop until we have the right number of values in a single row
while (usedIndexes.Count < maxValuesPerRow)
{
int index = rnd.Next(inputValues.Length);
//Ensure that each index we use is unique and only used once per row
if (usedIndexes.Add(index))
sb.Append(inputValues[index].ToString()).Append(",");
}
sb.Length--; //remove the last comma
output.Add(sb.ToString()); //value is only added if unique
}
return output.ToList();
}
}
You can call it like this
var result = StringPermutator.Permutate(stringValues, 100, 24);
foreach (var permutation in result)
{
Console.WriteLine(string.Join(",", permutation));
}
Basically the class uses HashSet which ensures that only unique values can be entered, therefore we can be sure that our output is not duplicated and we just loop until we have the right number of generated output values.
Within this loop then we randomly pick an index to use, and to ensure that this is also unique for each output value then we again use a HashSet to store the indexes used and loop until we have combined the right number of values into a single output row.
The return is an Enumerable list.
This should work on any type of input value, not just strings.
Edit:
Just to clarify, as per the comments.
If you don't have enough inputs to generate the number of permutations and rows combinations that you need then you could get stuck in a loop. So you should code a method to break out of this but in order to keep the example simple I didn't do that.
I propose the use of more deterministic permutation generator. Couple this with existing LINQ extension methods like Select(), Distinct() and Take() and you've got what you need:
var results = values2.Permutations(24)
.Select(p => String.Join(",", p))
.Distinct()
.Take(100);
foreach (var permutation in results)
Console.WriteLine(permutation);
where Permutations() is implemented as an extension method. The number 24 here indicates how many items should be in each permutation. It is the k in nPk.
The Select() call creates a string string with all the items for the particular permutation.
The Distinct() call makes sure that we only end up with unique strings.
The Take() call limits the number of strings that we collect.
Here is a naive implementation using recursion to generate the permutations:
public static IEnumerable<T[]> Permutations<T>(this IEnumerable<T> source, int k)
{
if (k < 0)
throw new ArgumentOutOfRangeException(nameof(k), "May not be negative");
var items = source.ToArray();
if (k > items.Length)
throw new ArgumentOutOfRangeException(nameof(k), "May not be bigger than the number of items in source");
var buffer = new ArraySegment<T>(items, 0, k);
return Permute(0);
IEnumerable<T[]> Permute(int depth)
{
if (depth == k)
{
yield return buffer.ToArray();
yield break;
}
for (int i = depth; i < items.Length; i++)
{
Swap(depth, i);
foreach (var permutation in Permute(depth + 1))
yield return permutation;
Swap(depth, i);
}
}
void Swap(int a, int b)
{
if (a != b)
{
T t = items[a];
items[a] = items[b];
items[b] = t;
}
}
}
I leave it to you to replace the implementation with the algorithm of your choice.
Is there an easy way to convert an array of boolean values into 8-bit hexadecimal equivlents? For example, if I have
bool[] BoolArray = new bool[] { true,false,true,true,false,false,false,true };
If true values=1 and false values=0 then I'd like a method or function that would convert the above array to 0xB1 (10110001).
Does there exist such a function or method to do this? I am using C#, by the way.
Yes, you can use the BitArray class. Something like this should do it:
BitArray arr = new BitArray(BoolArray);
byte[] data = new byte[1];
arr.CopyTo(data, 0);
If by "8-bit hexadecimal" you mean the string representation, you can use the BitConverter class for that:
string hex = BitConverter.ToString(data);
How about
static int BoolArrayToInt(bool[] arr)
{
if (arr.Length > 31)
throw new ApplicationException("too many elements to be converted to a single int");
int val = 0;
for (int i = 0; i < arr.Length; ++i)
if (arr[i]) val |= 1 << i;
return val;
}
static string ToHexStr(int i) { return i.ToString("X8"); }
note: an editor remarked that arr[0] is the LSB but he expected MSB. This is an API consideration, if you prefer your LSB to be at arr[length-1] just reverse the array before passing to that function.
The Binary part can be achieved through this method:
bool[] boolArray = {true, false, true} will give 101:
int BoolArrayToInt(bool[] bArray)
{
char[] caseChar = new char[bArray.Length];
for(int i = 0; i < bArray.Length; i++)
{
if (bArray[i] == true)
{
caseChar[i] = '1';
}
else
{
caseChar[i] = '0';
}
}
string caseString = new string(caseChar);
int caseNum = System.Convert.ToInt32(caseString);
return caseNum;
}
How can I convert BitArray to a single int?
private int getIntFromBitArray(BitArray bitArray)
{
if (bitArray.Length > 32)
throw new ArgumentException("Argument length shall be at most 32 bits.");
int[] array = new int[1];
bitArray.CopyTo(array, 0);
return array[0];
}
private int getIntFromBitArray(BitArray bitArray)
{
int value = 0;
for (int i = 0; i < bitArray.Count; i++)
{
if (bitArray[i])
value += Convert.ToInt16(Math.Pow(2, i));
}
return value;
}
This version:
works for up to 64 bits
doesn't rely on knowledge of BitArray implementation details
doesn't needlessly allocate memory
doesn't throw any exceptions (feel free to add a check if you expect more bits)
should be more than reasonably performant
Implementation:
public static ulong BitArrayToU64(BitArray ba)
{
var len = Math.Min(64, ba.Count);
ulong n = 0;
for (int i = 0; i < len; i++) {
if (ba.Get(i))
n |= 1UL << i;
}
return n;
}
Reffering to this post (#43935747). A value X is short tpe whic I set two bits (6 and 10) like below:
short X=1;
var result = X;
var bitsToSet = new [ ] { 5,9 };
foreach ( var bitToSet in bitsToSet )
{
result+=( short ) Math.Pow ( 2,bitToSet );
}
string binary = Convert.ToString ( result,2 );
Now I would like to read the specific all bits from Value X and put it in to an array or a bit type like bool Val1= bit1, bool Val2=bit2....
I am a newbie and I think it is pretty simple for you guyes..