How do I get all possible combinations of an enum ( Flags ) - c#

[Flags]
public enum MyEnum
{
None = 0,
Setting1 = (1 << 1),
Setting2 = (1 << 2),
Setting3 = (1 << 3),
Setting4 = (1 << 4),
}
I need to be able to somehow loop over every posible setting and pass the settings combination to a function. Sadly I have been unable to figure out how to do this

Not tested, use at your own risk, but should solve the problem generically enough. System.Enum is not a valid restriction as technically C# only allow inheritance in/with class the backend bypasses this for Enum and ValueType. So sorry for the ugly casting. It is also not horribly efficient but unless you are running this against a dynamically generated type it should only ever have to be done once per execution (or once period if saved).
public static List<T> GetAllEnums<T>()
where T : struct
// With C# 7.3 where T : Enum works
{
// Unneeded if you add T : Enum
if (typeof(T).BaseType != typeof(Enum)) throw new ArgumentException("T must be an Enum type");
// The return type of Enum.GetValues is Array but it is effectively int[] per docs
// This bit converts to int[]
var values = Enum.GetValues(typeof(T)).Cast<int>().ToArray();
if (!typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Any())
{
// We don't have flags so just return the result of GetValues
return values;
}
var valuesInverted = values.Select(v => ~v).ToArray();
int max = 0;
for (int i = 0; i < values.Length; i++)
{
max |= values[i];
}
var result = new List<T>();
for (int i = 0; i <= max; i++)
{
int unaccountedBits = i;
for (int j = 0; j < valuesInverted.Length; j++)
{
// This step removes each flag that is set in one of the Enums thus ensuring that an Enum with missing bits won't be passed an int that has those bits set
unaccountedBits &= valuesInverted[j];
if (unaccountedBits == 0)
{
result.Add((T)(object)i);
break;
}
}
}
//Check for zero
try
{
if (string.IsNullOrEmpty(Enum.GetName(typeof(T), (T)(object)0)))
{
result.Remove((T)(object)0);
}
}
catch
{
result.Remove((T)(object)0);
}
return result;
}
This works by getting all the values and ORing them together, rather than summing, in case there are composite numbers included. Then it takes every integer up to the maximum and masking them with the reverse of each Flag, this causes valid bits to become 0, allowing us to identify those bits that are impossible.
The check at the end is for missing zero from an Enum. You can remove it if you are fine with always including a zero enum in the results.
Gave the expected result of 15 when given an enum containing 2,4,6,32,34,16384.

Since it's a flagged enum, why not simply:
Get the highest vale of the enum.
Calculate the amound of combinations, i.e. the upper bound.
Iterate over every combination, i.e. loop from 0 to upper bound.
An example would look like this
var highestEnum = Enum.GetValues(typeof(MyEnum)).Cast<int>().Max();
var upperBound = highestEnum * 2;
for (int i = 0; i < upperBound; i++)
{
Console.WriteLine(((MyEnum)i).ToString());
}

Here is a solution particular to your code sample, using a simple for loop (don't use, see update below)
int max = (int)(MyEnum.Setting1 | MyEnum.Setting2 | MyEnum.Setting3 | MyEnum.Setting4);
for (int i = 0; i <= max; i++)
{
var value = (MyEnum)i;
SomeOtherFunction(value);
}
Update: Here is a generic method that will return all possible combinations. And thank #David Yaw for the idea to use a queue to build up every combination.
IEnumerable<T> AllCombinations<T>() where T : struct
{
// Constuct a function for OR-ing together two enums
Type type = typeof(T);
var param1 = Expression.Parameter(type);
var param2 = Expression.Parameter(type);
var orFunction = Expression.Lambda<Func<T, T, T>>(
Expression.Convert(
Expression.Or(
Expression.Convert(param1, type.GetEnumUnderlyingType()),
Expression.Convert(param2, type.GetEnumUnderlyingType())),
type), param1, param2).Compile();
var initalValues = (T[])Enum.GetValues(type);
var discoveredCombinations = new HashSet<T>(initalValues);
var queue = new Queue<T>(initalValues);
// Try OR-ing every inital value to each value in the queue
while (queue.Count > 0)
{
T a = queue.Dequeue();
foreach (T b in initalValues)
{
T combo = orFunction(a, b);
if (discoveredCombinations.Add(combo))
queue.Enqueue(combo);
}
}
return discoveredCombinations;
}

public IEnumerable<TEnum> AllCombinations<TEnum>() where TEnum : struct
{
Type enumType = typeof (TEnum);
if (!enumType.IsEnum)
throw new ArgumentException(string.Format("The type {0} does not represent an enumeration.", enumType), "TEnum");
if (enumType.GetCustomAttributes(typeof (FlagsAttribute), true).Length > 0) //Has Flags attribute
{
var allCombinations = new HashSet<TEnum>();
var underlyingType = Enum.GetUnderlyingType(enumType);
if (underlyingType == typeof (sbyte) || underlyingType == typeof (short) || underlyingType == typeof (int) || underlyingType == typeof (long))
{
long[] enumValues = Array.ConvertAll((TEnum[]) Enum.GetValues(enumType), value => Convert.ToInt64(value));
for (int i = 0; i < enumValues.Length; i++)
FillCombinationsRecursive(enumValues[i], i + 1, enumValues, allCombinations);
}
else if (underlyingType == typeof (byte) || underlyingType == typeof (ushort) || underlyingType == typeof (uint) || underlyingType == typeof (ulong))
{
ulong[] enumValues = Array.ConvertAll((TEnum[]) Enum.GetValues(enumType), value => Convert.ToUInt64(value));
for (int i = 0; i < enumValues.Length; i++)
FillCombinationsRecursive(enumValues[i], i + 1, enumValues, allCombinations);
}
return allCombinations;
}
//No Flags attribute
return (TEnum[]) Enum.GetValues(enumType);
}
private void FillCombinationsRecursive<TEnum>(long combination, int start, long[] initialValues, HashSet<TEnum> combinations) where TEnum : struct
{
combinations.Add((TEnum)Enum.ToObject(typeof(TEnum), combination));
if (combination == 0)
return;
for (int i = start; i < initialValues.Length; i++)
{
var nextCombination = combination | initialValues[i];
FillCombinationsRecursive(nextCombination, i + 1, initialValues, combinations);
}
}
private void FillCombinationsRecursive<TEnum>(ulong combination, int start, ulong[] initialValues, HashSet<TEnum> combinations) where TEnum : struct
{
combinations.Add((TEnum)Enum.ToObject(typeof(TEnum), combination));
if (combination == 0)
return;
for (int i = start; i < initialValues.Length; i++)
{
var nextCombination = combination | initialValues[i];
FillCombinationsRecursive(nextCombination, i + 1, initialValues, combinations);
}
}

First, grab a list of all the individual values. Since you've got 5 values, that's (1 << 5) = 32 combinations, so iterate from 1 to 31. (Don't start at zero, that would mean to include none of the enum values.) When iterating, examine the bits in the number, every one bit in the iteration variable means to include that enum value. Put the results into a HashSet, so that there aren't duplicates, since including the 'None' value doesn't change the resulting enum.
List<MyEnum> allValues = new List<MyEnum>(Enum.Getvalues(typeof(MyEnum)));
HashSet<MyEnum> allCombos = new Hashset<MyEnum>();
for(int i = 1; i < (1<<allValues.Count); i++)
{
MyEnum working = (MyEnum)0;
int index = 0;
int checker = i;
while(checker != 0)
{
if(checker & 0x01 == 0x01) working |= allValues[index];
checker = checker >> 1;
index++;
}
allCombos.Add(working);
}

I usually don't want to update each variable representing the max of an enumeration, when I add a new member to an enumeration.
For example I dislike the statement Greg proposed:
int max = (int)(MyEnum.Setting1 | MyEnum.Setting2 | ... | MyEnum.SettingN);
Consider when you have several of these variabeles scattered throughout your solution and you decide to modify your enumeration. That surely isn't a desirable scenario.
I will admit in advance that my code is slower, but it is automatically correct after an enumeration has been modified, and I strive to code in such a robust manner. I'm willing to pay some computational penalty for that, C# is all about that anywayz. I propose:
public static IEnumerable<T> GetAllValues<T>() where T : struct
{
if (!typeof(T).IsEnum) throw new ArgumentException("Generic argument is not an enumeration type");
int maxEnumValue = (1 << Enum.GetValues(typeof(T)).Length) - 1;
return Enumerable.Range(0, maxEnumValue).Cast<T>();
}
This assumes the enumeration contains members for all powers of 2 up to a certain power(including 0), exactly like a flag-enumeration is usually used.

I'm probably a little late to the party I would like to leave my solution which also includes the values plus the possible text of the combination in form of ("V1 | V2", "V1 | V2 | V3", etc).
I took some aspects of the solutions proposed above, so thanks to all that had posted the previous answers :D.
Note: only work with Enum set as base 2 combinations.
public static Dictionary<int,string> GetCombinations( this Enum enu)
{
var fields = enu.GetType()
.GetFields()
.Where(f => f.Name != "value__")
.DistinctBy(f=> Convert.ToInt32(f.GetRawConstantValue()));
var result = fields.ToDictionary(f=>Convert.ToInt32(f.GetRawConstantValue()), f => f.Name);
int max = Enum.GetValues(enu.GetType()).Cast<int>().Max();
int upperBound = max * 2;
for (int i = 0 ; i <= upperBound ; i += 2)
{
string s = Convert.ToString(i, 2).PadLeft(Math.Abs(i-max),'0');
Boolean[] bits = s.Select(chs => chs == '1' ? true : false)
.Reverse()
.ToArray();
if (!result.ContainsKey(i))
{
var newComb = string.Empty;
for (int j = 1; j < bits.Count(); j++)
{
var idx = 1 << j;
if (bits[j] && result.ContainsKey(idx))
{
newComb = newComb + result[idx] + " | ";
}
}
newComb = newComb.Trim(new char[] { ' ', '|' });
if (!result.ContainsValue(newComb) && !string.IsNullOrEmpty(newComb))
{
result.Add(i, newComb);
}
}
}
return result;
}

Concluded with this version:
Without checks:
public IEnumerable<T> AllCombinations<T>() where T : struct
{
var type = typeof(T);
for (var combination = 0; combination < Enum.GetValues(type).Cast<int>().Max()*2; combination++)
{
yield return (T)Enum.ToObject(type, combination);
}
}
With some checks:
public IEnumerable<T> AllCombinations<T>() where T : struct
{
var type = typeof(T);
if (!type.IsEnum)
{
throw new ArgumentException($"Type parameter '{nameof(T)}' must be an Enum type.");
}
for (var combination = 0; combination < Enum.GetValues(type).Cast<int>().Max()*2; combination++)
{
var result = (T)Enum.ToObject(type, combination);
// Optional check for legal combination.
// (and is not necessary if all flag a ascending exponent of 2 like 2, 4, 8...
if (result.ToString() == combination.ToString() && combination != 0)
{
continue;
}
yield return result;
}
}

Related

Sorting an array of enumeration

Hello I have an array of enumerations, and I'm trying sort that array by their enumeration value and get the array index's of the top
private enum Values
{
LOW,
MEDIUM,
HIGH
}
private Values[] Settings = new Values[10];
Settings[0] = LOW;
Settings[1] = HIGH;
Settings[2] = MEDIUM;
Settings[3] = LOW;
Settings[4] = LOW;
Settings[5] = LOW;
Settings[6] = LOW;
Settings[7] = LOW;
Settings[8] = MEDIUM;
Settings[9] = MEDIUM;
Basically now, with what I have above, I need to sort the settings array by enumeration value and get the array indexes of the top (let's say 3) items;
So I'd get back values 1, 2, 8
The platform I'm using does not support LINQ so those handy functions are not available.
I've been trying to wrap my head around this but it would help to have another pair of eyes.
thanks.
Implement a wrapper reference type,
class ValueWrapper : IComparable<ValueWrapper>
{
public Values Value { get; set; }
public int Index { get; set; }
public int CompareTo(ValueWrapper other)
{
return this.Value.CompareTo(other.Value) * -1; // Negating since you want reversed order
}
}
Usage -
ValueWrapper[] WrappedSettings = new ValueWrapper[10];
for(int i = 0; i < WrappedSettings.Length; i++)
{
WrappedSettings[i] = new ValueWrapper { Value = Settings[i], Index = i };
}
Array.Sort(WrappedSettings);
WrappedSettings will be sorted as you specified, preserving the indexes they were in the original array.
how about this:
Values first = Values.Low,second = Values.Low,third = Values.Low;
int firstI = -1,secondI = -1, thirdI = -1;
for(int i = 0;i < Settings.Length;i++)
{
if(Settings[i] > first || firstI == -1)
{
third = second;
thirdI = secondI;
second= first;
secondI= firstI;
first = Settings[i];
firstI = i;
}
else if(Settings[i] > second || secondI == -1)
{
third = second;
thirdI = secondI;
second = Settings[i];
secondI = i;
}
else if(Settings[i] > third || thirdI == -1)
{
third = Settings[i];
thirdI = i;
}
}
So, since you say you work in an environment where Linq is not available, I assume that other things like generics, nullables and so on will not be available either. A very low-tech solution.
Basic idea:
For every possible enum value, from highest to lowest, go through the list. If we find that value, output it and remember how many we have output. If we reach 3, stop the algorithm.
So, we first look for HIGH in the list, then for MEDIUM and so on.
class Program
{
private enum Values
{
LOW,
MEDIUM,
HIGH
}
static void Main(string[] args)
{
// Sample data
Values[] settings = new Values[10];
settings[0] = Values.LOW;
settings[1] = Values.HIGH;
settings[2] = Values.MEDIUM;
settings[3] = Values.LOW;
settings[4] = Values.LOW;
settings[5] = Values.LOW;
settings[6] = Values.LOW;
settings[7] = Values.LOW;
settings[8] = Values.MEDIUM;
settings[9] = Values.MEDIUM;
// Get Values of the enum type
// This list is sorted ascending by value but may contain duplicates
Array enumValues = Enum.GetValues(typeof(Values));
// Number of results found so far
int numberFound = 0;
// The enum value we used during the last outer loop, so
// we skip duplicate enum values
int lastValue = -1;
// For each enum value starting with the highest to the lowest
for (int i= enumValues.Length -1; i >= 0; i--)
{
// Get this enum value
int enumValue = (int)enumValues.GetValue(i);
// Check whether we had the same value in the previous loop
// If yes, skip it.
if(enumValue == lastValue)
{
continue;
}
lastValue = enumValue;
// For each entry in the list where we are searching
for(int j=0; j< settings.Length; j++)
{
// Check to see whether it is the currently searched value
if (enumValue == (int)settings[j])
{
// if yes, then output it.
Console.WriteLine(j);
numberFound++;
// Stop after 3 found entries
if (numberFound == 3)
{
goto finished;
}
}
}
}
finished:
Console.ReadLine();
}
}
Output is as requested 1,2,8
I'm not sure if this is exactly what you want because it doesn't sort the original array, but one way to get the indexes of the top three values is to simply store the indexes of the top values in another array. Then we can loop through the original array, and for each item, see if it's larger than any of the items at the indexes we've stored so far. If it is, then swap it with that item.
For example:
// Start the topIndexes array with all invalid indexes
var topIndexes = new[] {-1, -1, -1};
for (var settingIndex = 0; settingIndex < Settings.Length; settingIndex++)
{
var setting = Settings[settingIndex];
var topIndexLessThanSetting = -1;
// Find the smallest topIndex setting that's less than this setting
for (int topIndex = 0; topIndex < topIndexes.Length; topIndex++)
{
if (topIndexes[topIndex] == -1)
{
topIndexLessThanSetting = topIndex;
break;
}
if (setting <= Settings[topIndexes[topIndex]]) continue;
if (topIndexLessThanSetting == -1 ||
Settings[topIndexes[topIndex]] < Settings[topIndexes[topIndexLessThanSetting]])
{
topIndexLessThanSetting = topIndex;
}
}
topIndexes[topIndexLessThanSetting] = settingIndex;
}
// topIndexes = { 1, 2, 8 }

Get null as a default for integer types

An algorithm from Leetcode Discussion uses Binary Search Tree to hold a range of values from an input array to check if this array contains values that are different at most by t, and their indexes are at most k far from each other.
JAVA:
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if (nums == null || nums.length == 0 || k <= 0) {
return false;
}
final TreeSet<Integer> values = new TreeSet<>();
for (int ind = 0; ind < nums.length; ind++) {
final Integer floor = values.floor(nums[ind] + t);
final Integer ceil = values.ceiling(nums[ind] - t);
if ((floor != null && floor >= nums[ind])
|| (ceil != null && ceil <= nums[ind])) {
return true;
}
values.add(nums[ind]);
if (ind >= k) {
values.remove(nums[ind - k]);
}
}
return false;
}
I am struggling to make it work in C#. This code doesn't work as long as LastOrDefault and FirstOrDefault methods return 0 as a default. How to work around to get null as a default?
C#:
public bool ContainsNearbyAlmostDuplicate(int[] nums, int k, int t)
{
if (nums == null || nums.Length < 2 || k < 1) return false;
SortedSet<long> set = new SortedSet<long>();
for (int i = 0; i < nums.Length; i++)
{
long l = (long)nums[i];
long floor = set.LastOrDefault(n => n <= l);
long ceil = set.FirstOrDefault(n => n >= l);
if ((l - floor <= t) || (ceil - l <= t))
return true;
set.Add(l);
if (i >= k) set.Remove((long)nums[i - k]);
}
return false;
}
One way would be to declare your set with nullable longs
var set = new SortedSet<long?>();
Or you could just not use the FirstOrDefault and do something like:
var greaterOrEqualToOne = set.Where(n => n >= 1);
long? ceil = greaterOrEqualToOne.Any() ? greaterOrEqualToOne.First() : null;
Yet another way, cast them to long? first:
long? ceil = set.Select(n => (long?)n).FirstOrDefault(n => n >= 1);
Use nullable long to get null on LastOrDefault
SortedSet<long?> set = new SortedSet<long?>();
If you want to retrieve int/long/... values including null, then you need to user Nullable Types
And in your source code will be:
SortedSet<long?> set = new SortedSet<long?>();
Other answers are technically correct (use nullable types on your set)
SortedSet<long?> set = new SortedSet<long?>();
However, in order to ever receive null value from FirstOrDefault/LastOrDefault you need to pass the int?[] nums to your method, because you fill your set by casting
long l = (long)nums[i];
which won't get you null value from int array even when casted to nullable long?.
In other words - your method needs to get nullable array in order to work with null values.
And if you won't ever be working with nulls on provided array why not just iterate from i = 1?
If you want to declare int,long... values as NULL, you need to declare like this:
int? empId;
if(empId is null)
{
// do this
}
else
{
//do this
}
In the same way you have to use:
SortedSet<long?> sortedSet = new SortedSet<long?>();
You can cast int/long it to nullable type (?) as other users have stated and then use DefaultIfEmpty to create a default collection that contains null if the collection turns out to be empty.
SortedSet<long?> set = new SortedSet<long?>();
long? floor = set.Where(n => n <= l).DefaultIfEmpty().LastOrDefault();
long? ceil = set.Where(n => n >= l).DefaultIfEmpty().FirstOrDefault();

enum ToString and performance

I was profiling some C# code and wound up investigating the implementation of ToString for enum values.
The ToString method ultimately calls System.Type.GetEnumName. Here's the relevant source code, taken from http://referencesource.microsoft.com/#mscorlib/system/type.cs
public virtual string GetEnumName(object value)
{
if (value == null)
throw new ArgumentNullException("value");
if (!IsEnum)
throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
Contract.EndContractBlock();
Type valueType = value.GetType();
if (!(valueType.IsEnum || Type.IsIntegerType(valueType)))
throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
Array values = GetEnumRawConstantValues();
int index = BinarySearch(values, value);
if (index >= 0)
{
string[] names = GetEnumNames();
return names[index];
}
return null;
}
// Returns the enum values as an object array.
private Array GetEnumRawConstantValues()
{
string[] names;
Array values;
GetEnumData(out names, out values);
return values;
}
// This will return enumValues and enumNames sorted by the values.
private void GetEnumData(out string[] enumNames, out Array enumValues)
{
Contract.Ensures(Contract.ValueAtReturn<String[]>(out enumNames) != null);
Contract.Ensures(Contract.ValueAtReturn<Array>(out enumValues) != null);
FieldInfo[] flds = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
object[] values = new object[flds.Length];
string[] names = new string[flds.Length];
for (int i = 0; i < flds.Length; i++)
{
names[i] = flds[i].Name;
values[i] = flds[i].GetRawConstantValue();
}
// Insertion Sort these values in ascending order.
// We use this O(n^2) algorithm, but it turns out that most of the time the elements are already in sorted order and
// the common case performance will be faster than quick sorting this.
IComparer comparer = Comparer.Default;
for (int i = 1; i < values.Length; i++)
{
int j = i;
string tempStr = names[i];
object val = values[i];
bool exchanged = false;
// Since the elements are sorted we only need to do one comparision, we keep the check for j inside the loop.
while (comparer.Compare(values[j - 1], val) > 0)
{
names[j] = names[j - 1];
values[j] = values[j - 1];
j--;
exchanged = true;
if (j == 0)
break;
}
if (exchanged)
{
names[j] = tempStr;
values[j] = val;
}
}
enumNames = names;
enumValues = values;
}
// Convert everything to ulong then perform a binary search.
private static int BinarySearch(Array array, object value)
{
ulong[] ulArray = new ulong[array.Length];
for (int i = 0; i < array.Length; ++i)
ulArray[i] = Enum.ToUInt64(array.GetValue(i));
ulong ulValue = Enum.ToUInt64(value);
return Array.BinarySearch(ulArray, ulValue);
}
If I'm understanding this correctly, whenever an enum's name is requested:
The entire set of enum values and names are inserted into arrays using insertion sort.
The values are copied to an array of ulongs.
This array is searched with binary search.
Am right to think that this is grossly inefficient? (especially for enums with hundreds or thousands of values)
It seems like some sort of dictionary/hashtable structure would be ideal. But even a simple O(n) linear scan of the values would have accomplished the same goal without sorting or binary searching or allocating superfluous arrays.
I was able to precompute a dictionary for one particular case where ToString was being called many times in a loop; and that yielded significant performance gains. But is there any built-in, alternative, more holistic technique that would also facilitate things like JSON serialization?

String Combinations With Character Replacement

I am trying to work through a scenario I haven't seen before and am struggling to come up with an algorithm to implement this properly. Part of my problem is a hazy recollection of the proper terminology. I believe what I am needing is a variation of the standard "combination" problem, but I could well be off there.
The Scenario
Given an example string "100" (let's call it x), produce all combinations of x that swap out one of those 0 (zero) characters for a o (lower-case o). So, for the simple example of "100", I would expect this output:
"100"
"10o"
"1o0"
"1oo"
This would need to support varying length strings with varying numbers of 0 characters, but assume there would never be more than 5 instances of 0.
I have this very simple algorithm that works for my sample of "100" but falls apart for anything longer/more complicated:
public IEnumerable<string> Combinations(string input)
{
char[] buffer = new char[input.Length];
for(int i = 0; i != buffer.Length; ++i)
{
buffer[i] = input[i];
}
//return the original input
yield return new string(buffer);
//look for 0's and replace them
for(int i = 0; i != buffer.Length; ++i)
{
if (input[i] == '0')
{
buffer[i] = 'o';
yield return new string(buffer);
buffer[i] = '0';
}
}
//handle the replace-all scenario
yield return input.Replace("0", "o");
}
I have a nagging feeling that recursion could be my friend here, but I am struggling to figure out how to incorporate the conditional logic I need here.
Your guess was correct; recursion is your friend for this challenge. Here is a simple solution:
public static IEnumerable<string> Combinations(string input)
{
int firstZero = input.IndexOf('0'); // Get index of first '0'
if (firstZero == -1) // Base case: no further combinations
return new string[] { input };
string prefix = input.Substring(0, firstZero); // Substring preceding '0'
string suffix = input.Substring(firstZero + 1); // Substring succeeding '0'
// e.g. Suppose input was "fr0d00"
// Prefix is "fr"; suffix is "d00"
// Recursion: Generate all combinations of suffix
// e.g. "d00", "d0o", "do0", "doo"
var recursiveCombinations = Combinations(suffix);
// Return sequence in which each string is a concatenation of the
// prefix, either '0' or 'o', and one of the recursively-found suffixes
return
from chr in "0o" // char sequence equivalent to: new [] { '0', 'o' }
from recSuffix in recursiveCombinations
select prefix + chr + recSuffix;
}
This works for me:
public IEnumerable<string> Combinations(string input)
{
var head = input[0] == '0' //Do I have a `0`?
? new [] { "0", "o" } //If so output both `"0"` & `"o"`
: new [] { input[0].ToString() }; //Otherwise output the current character
var tails = input.Length > 1 //Is there any more string?
? Combinations(input.Substring(1)) //Yes, recursively compute
: new[] { "" }; //Otherwise, output empty string
//Now, join it up and return
return
from h in head
from t in tails
select h + t;
}
You don't need recursion here, you can enumerate your patterns and treat them as binary numbers. For example, if you have three zeros in your string, you get:
0 000 ....0..0....0...
1 001 ....0..0....o...
2 010 ....0..o....0...
3 011 ....0..o....o...
4 100 ....o..0....0...
5 101 ....o..0....o...
6 110 ....o..o....0...
7 111 ....o..o....o...
You can implement that with bitwise operators or by treating the chars that you want to replace like an odometer.
Below is an implementation in C. I'm not familiar with C# and from the other answers I see that C# already has suitable standard classes to implement what you want. (Although I'm surprised that so many peolpe propose recursion here.)
So this is more an explanation or illustration of my comment to the question than an implementation advice for your problem.
int binrep(char str[])
{
int zero[40]; // indices of zeros
int nzero = 0; // number of zeros in string
int ncombo = 1; // number of result strings
int i, j;
for (i = 0; str[i]; i++) {
if (str[i] == '0') {
zero[nzero++] = i;
ncombo <<= 1;
}
}
for (i = 0; i < ncombo; i++) {
for (j = 0; j < nzero; j++) {
str[zero[j]] = ((i >> j) & 1) ? 'o' : '0';
}
printf("%s\n", str); // should yield here
}
return ncombo;
}
Here's a solution using recursion, and your buffer array:
private static void Main(string[] args)
{
var a = Combinations("100");
var b = Combinations("10000");
}
public static IEnumerable<string> Combinations(string input)
{
var combinations = new List<string>();
combinations.Add(input);
for (int i = 0; i < input.Length; i++)
{
char[] buffer= input.ToArray();
if (buffer[i] == '0')
{
buffer[i] = 'o';
combinations.Add(new string(buffer));
combinations = combinations.Concat(Combinations(new string(buffer))).ToList();
}
}
return combinations.Distinct();
}
The method adds the raw input as the first result. After that, we replace in a loop the 0s we see as a o and call our method back with that new input, which will cover the case of multiple 0s.
Finally, we end up with a couple duplicates, so we use Distinct.
I know that the earlier answers are better. But I don't want my code to go to waste. :)
My approach for this combinatorics problem would be to take advantage of how binary numbers work. My algorithm would be as follows:
List<string> ZeroCombiner(string str)
{
// Get number of zeros.
var n = str.Count(c => c == '0');
var limit = (int)Math.Pow(2, n);
// Create strings of '0' and 'o' based on binary numbers from 0 to 2^n.
var binaryStrings = new List<string>();
for (int i = 0; i < limit; ++i )
{
binaryStrings.Add(Binary(i, n + 1));
}
// Replace each zero with respect to each binary string.
var result = new List<string>();
foreach (var binaryString in binaryStrings)
{
var zeroCounter = 0;
var combinedString = string.Empty;
for (int i = 0; i < str.Length; ++i )
{
if (str[i] == '0')
{
combinedString += binaryString[zeroCounter];
++zeroCounter;
}
else
combinedString += str[i];
}
result.Add(combinedString);
}
return result;
}
string Binary(int i, int n)
{
string result = string.Empty;
while (n != 0)
{
result = result + (i % 2 == 0 ? '0' : 'o');
i = i / 2;
--n;
}
return result;
}

Determine if an Enum with FlagsAttribute has unique bit values

Consider the following enumeration:
[Flags]
public enum EnumWithUniqueBitFlags
{
None = 0,
One = 1,
Two = 2,
Four = 4,
Eight = 8,
}
[Flags]
public enum EnumWithoutUniqueFlags
{
None = 0,
One = 1,
Two = 2,
Four = 4,
Five = 5,
}
The first one has values such that any combination will produce a unique bit combination while the second one will not. I need to programmatically determine this. So far I had only been checking if every value was a power of two but this since this code will be used to consume Enums developed by others, it is not practical.
var values = Enum.GetValues(typeof(TEnum)).OfType<TEnum>().ToList();
for (int i = 0; i < values.Count; i++)
{
if (((int) ((object) values [i])) != ((int) Math.Pow(2, i)))
{
throw (new Exception("Whatever."));
}
}
As opposed to the code above how could programatically determine that the following Enum meets the bit combination uniqueness objective (without assumptions such as values being powers of 2, etc.)?
[Flags]
public enum EnumWithoutUniqueFlags
{
Two = 2,
Four = 9,
Five = 64,
}
Please ignore which integral type the enum derives from as well as the fact that values could be negative.
You could compare the bitwise OR of enum values with the arithmetic sum of enum values:
var values = Enum.GetValues(typeof(EnumWithoutUniqueFlags))
.OfType<EnumWithoutUniqueFlags>().Select(val => (int)val).ToArray();
bool areBitsUnique = values.Aggregate(0, (acc, val) => acc | val) == values.Sum();
EDIT
As the #usr mentioned, the code above works for positive values only.
Despite the fact that the OP requested to ignore:
Please ignore which integral type the enum derives from as well as the fact that values could be negative.
I'm glad to introduce more optimal single loop approach:
private static bool AreEnumBitsUnique<T>()
{
int mask = 0;
foreach (int val in Enum.GetValues(typeof(T)))
{
if ((mask & val) != 0)
return false;
mask |= val;
}
return true;
}
To make it work for other underlying type (uint, long, ulong), just change the type of the mask and val variables.
EDIT2
Since the Enum.GetValues method returns values in the ascending order of their unsigned magnitude, if you need to check for duplicates of zero value, you could use the following approach:
private static bool AreEnumBitsUnique<T>()
{
int mask = 0;
int index = 0;
foreach (int val in Enum.GetValues(typeof(T)))
{
if ((mask & val) != 0) // If `val` and `mask` have common bit(s)
return false;
if (val == 0 && index != 0) // If more than one zero value in the enum
return false;
mask |= val;
index += 1;
}
return true;
}
To be unique, the enum must have no bits in common with other enum values. The bitwise AND operation can be used for this.
for (int i = 0; i < values.Count; ++i)
{
for (int j = 0; j < values.Count; ++j)
{
if (i != j && ((values[i] & values[j]) != 0))
throw new Exception(...);
}
}
I would cast the enums to uints, do a bitwise not of a 0x0, use an xor and if the next value is less than the previous one you have a collision
public static bool CheckEnumClashing<TEnum>()
{
uint prev = 0;
uint curr = 0;
prev = curr = ~curr;
foreach(var target in Enum.GetValues(typeof(TEnum)).Select(a=>(uint)a))
{
curr ^=target;
if( curr <= prev )
return false;
prev = curr;
}
return true;
}

Categories