Handling Permutations of If Statements in C# - c#

I have some Lists which store values. Now I want to create If-Statements to handle this but that's to much. For example:
if(list1.Count==0 && list2.Count==0)
{
//do something
}
if(list1.Count==0 && list3.Count==0)
{
//do something
}
if(list1.Count==0 && list2.Count==0 && list3.Count==0)
{
//do something
}
so there is a huge amount of if-statements if I have about 10 Lists. Is there a better way to handle that? I haven't found anything useful.
Thanks!

One of the way that i can give the suggestion seeing the code pasted here is that you have some duplicated stuff like this
if(list1.Count==0 && list2.Count==0)
and then
if(list1.Count==0 && list2.Count==0 && list3.Count==0)
One of the suggestion will be to per-calculate the condition like this
bool onetwo = list1.Count==0 && list2.Count==0;
bool thirdalone = list3.Count == 0;
Now the code can be more better like this
if(onetwo){
}
if(onetwo && thirdalone){
}
If you wish you can use the Bitmasking to generate all of them for example , here n is total lists we have.
bool[] statu = new bool[1 << n];
for(int i = 1 ; i < (1<< n) ; i++){
bool result = true;
for(int j = 0 ; j < 32 ; j++){
if(i & ( 1 << j) > 0){
//this position is part of set
if(list[j].count == 0)
result = false;
}
}
status[i] = result;
}
But it is just more semantic way , nothing can be performance enhancement etc..

If you need to check every permutation you can do something like this:
bool b1 = ( list1.count == 0 );
bool b2 = ( list2.count == 0 );
bool b3 = ( list3.count == 0 );
bool b4 = ( list4.count == 0 );
// etc etc
BitArray arr = new BitArray(new bool[4] { b1, b2, b3, b4 });
byte[] bits = new byte[4];
arr.CopyTo(bits, 0);
int x = BitConverter.ToInt32(bits, 0);
switch (x)
{
case 1: // only list 1 is empty
case 2: // only list 2 is empty
case 3: // only list 1 and list 2 are empty
case x: // and so on.
}
I wouldn't say is it's any more readable, but I'd rather maintain something like this is future than a giant if/else/else if block.

Related

C# Finding "connected" permutations

I'm working on a dictionary table and required to find out all possible combination of characters in a word. Thanks to https://codereview.stackexchange.com/questions/28248/implement-a-function-that-prints-all-possible-combinations-of-the-characters-in , I got below working so far:
public List<string> findAllOccurance(string str)
{
var results = from e in Range(0, BigInteger.Pow(2, str.Length))
let p =
from b in Enumerable.Range(1, str.Length)
select (e & BigInteger.Pow(2, b - 1)) == 0 ? (char?)null : str[b - 1]
select string.Join(string.Empty, p);
return results.ToList();
}
public IEnumerable<BigInteger> Range(BigInteger start, BigInteger count)
{
while (count-- > 0)
{
yield return start++;
}
}
Passing "abc" to above function would returns:
a
b
ab
c
ac
bc
abc
The problem is I actually would like to find out only the "connected" permutations in "original order", for example "abc" should return only
a
b
c
ab
bc
abc
Does anyone have any idea what should I change to achieve above?
By "connected" permutations - you are effectively looking for all substrings from length 1 up to the full length of the string. This can be very easily done with two for loops. The duplicates can be removed by using Linq's Distinct() method.
public List<string> findAllOccurance(string str)
{
List<string> result = new List<string>();
for (int i = 1; i <= str.Length; i++)
{
for (int j=0; j <= str.Length-i; j++)
result.Add(str.Substring(j,i));
}
return result.Distinct().ToList();
}
NOTE - if you really do want to return an empty string - you can either modify the outer loop to start from 0 or simply manually add it after creating the list instance. Modifying the loop will result in str.Length empty strings being added & more work for Distinct() when you know you will only ever always want 1 empty string returned.
List<string> result = new List<string>();
result.Add(String.Empty);
for (int i = 1; i <= str.Length; i++)
.....
I don't know if I understand "connected" right... Maybe you could simply check if a potential result is a part of the original string... Something like this:
public List<string> findAllOccurance(string str)
{
var results = from e in Range(0, BigInteger.Pow(2, str.Length))
let p =
from b in Enumerable.Range(1, str.Length)
select (e & BigInteger.Pow(2, b - 1)) == 0 ? (char?)null : str[b - 1]
let p2 = string.Join(string.Empty, p)
where str.Contains(p2)
select p2;
return results.ToList();
}
public IEnumerable<BigInteger> Range(BigInteger start, BigInteger count)
{
while (count-- > 0)
{
yield return start++;
}
}
For your code, you are performing bitwise operation in order to find all possible subsets. For the case abc your string length is 3. So possible subsets = 2 ^ 3 = 8. Writing them down and matching the rightmost bit with the leftmost index:
Possible cases:
0 0 0 // gives nothing
0 0 1 // gives 'a' (valid)
0 1 0 // gives 'b' (valid)
0 1 1 // gives 'ab' (valid)
1 0 0 // gives 'c' (valid)
1 0 1 // gives 'ac' (invalid as there is a 0 inbetween and not connected)
1 1 0 // gives 'bc' (valid)
1 1 1 // gives 'abc' (valid)
The above is what I understand for what you count as connected. You can easily perform a check to do this with two loops:
int max_size = BigInteger.Pow(2, str.Length);
int str_size = str.Length;
for(int i = 0; i < max_size; ++i)
{
string ans = "";
for(j = 0; j < str_size; ++j)
{
// We check if the jth bit is set, we print the jth element from the string.
if(i & (1 << j))
ans += str[j];
}
else {
if(ans.Length > 0){
// this means we have already added a character and then the next consecutive bit is '0'
ans = "";
break;
}
}
if(ans != ""){
Console.Writeline(ans); // we print the set. you can control this anyway you want.
}
}
}

C# IF statement

for (int k = 0; k < proc.Count; k++){
for (int i = k + 1; i < proc.Count; i++){
if (proc[k].arrivalTime >= proc[i].arrivalTime && proc[k].priority >= proc[i].priority && proc[k].brust > proc[i].brust){
temp = proc[i];
proc[i] = proc[k];
proc[k] = temp;
}
}
}
Input
Process Arrival Brust Priority
P0 0 10 5
P1 1 3 1
P2 1 2 1
P3 5 1 5
P4 5 8 2
I want to sort these processes following these rules
1) If the process arrived alone it'll work no matter what.
2) If 2 processes arrived in the same time, we gonna check the priority if the first one has higher priority(lower number) it'll work first, and if they have the same priority we gonna let the one who has lower Brust work first.
There's problem with last 2 processes where's the problem?
P3 5 1 5
P4 5 8 2
process 4 should work because it has higher priority
Rather than bubble sorting (which is the one of the least efficient ways to sort collections), why not just sort the collection using LINQ's OrderBy(), e.g.
var sorted = proc.OrderBy(x => x.arrivalTime)
.ThenBy(x => x.priority)
.ThenBy(x => x.brust)
.ToList(); // or .ToArray() or whatever collection you need
You provided very clear explanation of the rules.
Now check this line
if (proc[k].arrivalTime >= proc[i].arrivalTime && proc[k].priority >= proc[i].priority && proc[k].brust > proc[i].brust)
Is it doing what the rules say? Definitely no. The direct translation of the rules would be something like this
if (proc[k].arrivalTime > proc[i].arrivalTime ||
(proc[k].arrivalTime == proc[i].arrivalTime &&
(proc[k].priority > proc[i].priority ||
(proc[k].priority == proc[i].priority && proc[k].brust > proc[i].brust))))
Better and more readable would be
int compare = proc[k].arrivalTime.CompareTo(proc[i].arrivalTime);
if (compare == 0)
compare = proc[k].priority.CompareTo(proc[i].priority);
if (compare == 0)
compare = proc[k].brust.CompareTo(proc[i].brust);
if (compare > 0)
{
// ...
}
which is the standard way of doing multi key comparison.
Mahmoud, your if-statment is incorrect because it will evaluate to true if ALL conditions are met, your statement should cascade the conditions.
for (int k = 0; k < proc.Count; k++){
for (int i = k + 1; i < proc.Count; i++){
bool doSwap = false;
if (proc[k].arrivalTime > proc[i].arrivalTime)
{
doSwap = true;
}
else if (proc[k].arrivalTime == proc[i].arrivalTime)
{
if(proc[k].priority > proc[i].priority)
{
doSwap = true;
}
else if (proc[k].priority == proc[i].priority )
{
if(proc[k].brust > proc[i].brust)
{
doSwap = true;
}
}
}
if(doSwap)
{
temp = proc[i];
proc[i] = proc[k];
proc[k] = temp;
}
}
}

All possible combinations of boolean variables

I'm trying to find an algorithm that will allow me to do the following:
Imagine I have 10 boolean variables, and I want to try every combination, since my goal is to find ANY combination which will give as a result to one of my methods true (This method has lots of restrictions, which is why I want to test every possible combinations, and if there are no combinations that will solve the problem, then I want to notify the user this).
I hope it is understandable!
Try this:
for (int i = 0; i < (1 << 10); i++)
{
bool b1 = (i & (1 << 0)) != 0;
bool b2 = (i & (1 << 1)) != 0;
bool b3 = (i & (1 << 2)) != 0;
bool b4 = (i & (1 << 3)) != 0;
...
if (MyMethod(b1, b2, b3, b4, ...))
{
// Found a combination for which MyMethod returns true
}
}
You can, of course, also use LINQ:
var result = from b1 in new[] { false, true }
from b2 in new[] { false, true }
from b3 in new[] { false, true }
from b4 in new[] { false, true }
...
where MyMethod(b1, b2, b3, b4, ...)
select new { b1, b2, b3, b4, ... };
I finally came up with a more efficient method: Using binary numbers:
Let's say I want to test all possible boolean combinations out of 8 variables:
If I pick do the following I'll get to test every combination:
public string CombinationFinder()
{
for (int i = 0; i < 2 ^ 8; i++)
{
String ans = Convert.ToInt32(i, 2).ToString();
if (myMethod(ans))
{
return ans;
}
}
return null;
}
This will go from 0 to 255, which in binary means going from 00000000 to 11111111
where each digit take the value 0 or 1, which can be represented as boolean. In this example if there's no combination found the method will return null.
I know this is an old question, but waclock's answer doesn't compile (there's no exponent operator in C#). dtb's answer gets 99% of the way there, but doesn't handle unknown number of booleans, which is what this answer provides:
var props = typeof(TypeWithBooleans).GetProperties().Where(prop => prop.PropertyType == typeof(bool)).ToArray();
for (var i = 0; i < (1 << props.Length); ++i)
{
var combination = Enumerable.Range(0, props.Length).Select(j => (i & (1 << j)) != 0).ToArray();
if (MyMethod(combination)) {
// handle match
};
}
This assumes that all the booleans you care about are confined to a single class/struct, and that MyMethod uses a params array.
define a class like this:
class Bint
{
int num;
public bool this[int num]
{
get {return num << n & 0x1 == 1;}
}
public int Num
{
get {return num;}
set {num = value;}
}
}
and iterate through the numbers:
Bint n = new Bint();
for (int i = 0; i < Math.pow(2,10); i++)
{
n.Num = i;
f(n[0],n[1]...);
}

Union of two arrays

Given two arrays
int arr1[n]
int arr2[m]
where n > m
Need to write a union of two arrays into one.
For example, if the input arrays are:
int arr1[] = {1, 3, 4, 5, 7}
int arr2[] = {2, 3, 5, 6}
Then program should create new array Union as {1, 2, 3, 4, 5, 6, 7}
Implementation can be in C# or Java.
In order to solve it first of all need to to sort the arrays using Merge Sort
and then do the union
I looked in the net but did not find the elegant way . Every code that I looked
was full of IF's.
Please advice what is the most quick and elegant way to do it
You are correct that merging the two lists as is done in Merge Sort is the most efficient thing to do. This assumes that the two lists are already sorted, as in your example. Here is an example of how to implement merge:
function merge(left,right)
var list result
while length(left) > 0 or length(right) > 0
if length(left) > 0 and length(right) > 0
if first(left) ≤ first(right)
append first(left) to result
left = rest(left)
else
append first(right) to result
right = rest(right)
else if length(left) > 0
append first(left) to result
left = rest(left)
else if length(right) > 0
append first(right) to result
right = rest(right)
end while
return result
From here, simply do not include repeats in the final output.
If its an elegant MergeSort you are looking then nothing is more elegant than a recursive function :-)
Here it is :
This is a divide and conquer strategy. We basically divide the array into smaller arrays , sort the smaller arrays and merge them back.
public static void mergesort(int a[],int left, int right){
/*
* Time : O(n log n)
* Space : O(n)
*/
int b[] = new int[right -left+1];
domergesort(a,left,right,b);
}
public static void domergesort(int a[],int left,int right, int b[]){
if(left < right){
int mid = (left+right)/2;
domergesort(a,left,mid,b);
domergesort(a,mid+1,right,b);
merge(a,left,mid,a,mid+1,right,b);
for(int k=left;k<=right;k++)
a[k] = b[k-left];
}
}
Not many ifs too ..
Source : My Blog (http://cloudingitup.blogspot.com/p/reading-guide-arrays.html)
To merge them together as a Union :
public static void merge( int a[], int al, int ar, int b[], int bl, int br, int c[]){
// al : a's left index ar : a's right index c: merged array
int i= al;
int j = bl;
int k=0;
int prev = c[0];
while ( i<= ar && j <= br){
if (a[i] <= b[j])
if (prev != a[i]) // Too keep the union distinct
c[k++] = a[i++];
else
i++;
else
if (prev != b[j]) // Too keep the union distinct
c[k++] = b[j++];
else
j++;
prev = c[k-1];
}
while (i <= ar)
{
if (prev != a[i])
c[k++] = a[i++];
else
i++;
prev = c[k-1];
}
while (j <= br)
{
if (prev != b[j])
c[k++] = b[j++];
else
j++;
prev = c[k-1];
}
}
A driver code to illustrate the code :
int arr1[] = {1,1, 3, 4,4,4,5, 7};
int arr2[] = {2, 3, 5, 6,6,8};
int c[] = new int[8];
merge(arr1,0,7,arr2,0,5,c);
for(int i=0;i<8;i++)
System.out.print(c[i]);
Output: 12345678
public static void printUnion(int ar1[],int ar2[]) {
int m = ar1.length;
int n = ar2.length;
int i=0,j=0;
while(i<m && j<n) {
if( ar1[i] <ar2[j]) {
System.out.println(ar1[i]);
i++;
}else if(ar1[i] > ar2[j]) {
System.out.println(ar2[j]);
j++;
}else {
System.out.println(ar1[i]);
i++;
j++;
}
}
while(i < m)
System.out.println(ar1[i++]);
while(j < n)
System.out.println(ar2[j++]);
}
Same code will work for intersection with minimal changes....
In interviews, they usually want to see you solve the problem, rather than using library calls (e.g. arr1.union(arr2) probably wouldn't cut it.)
This is off the top of my head, but something like this should work, and I think is O(n^2). It assumes both arrays are sorted.
union.rb
arr1 = [0,2,4,9,11,12,13]
arr2 = [3,4,7,9,10,11]
def union(n, m)
if n.last > m.last
arr1 = n; arr2 = m
else
arr1 = m; arr2 = n
end
union_array = []
j = 0
arr1.each do |x|
while j < arr2.length && arr2[j] < x
if arr2[j] < x
union_array << arr2[j] unless arr2[j] == union_array.last
j += 1
end
end
union_array << x
end
union_array
end
puts union(arr1, arr2)
this method should work fairly well, and it will decide which array is bigger so there doesn't need to necessarily be a defined order.
Java:
public static <T> T[] combine(T[] a1, T[] a2)
{
return combine(a1, a2, a1.length + a2.length);
}
public static <T> T[] combine(T[] a1, T[] a2, int maxlength)
{
T[] front = null;
T[] back = null;
if(a1.length >= a2.length)
{
front = a1;
back = a2;
}
else
{
front = a2;
back = a1;
}
int len = front.length + back.length;
if(len > maxlength)
{
len = maxlength;
}
int n = 0;
T[] result = Arrays.copyOf(front, len);
int c = 0;
for(int i = 0;i < front.length;i++)
{
if(i < front.length && c < result.length)
{
result[c] = front[i];
c++;
}
if(i < back.length && c < result.length)
{
result[c] = back[i];
c++;
}
}
return result;
}
this is obviously not the most efficient method, but it does completely work. It also includes a capping, if you want to merge them, but only get the first, let's way 5 items, then you can add a parameter of 5 to the method.
You can actually get rid of a lot of waste, there's a lot of messy stuff in here, I'm away from my IDE so it's off my head, I may have stuff that's not needed.

List collection that replaces numbers with words

I am trying to improve a list collection that i have to replace values that are divisible by two and 10 and replace everything that is divisible by two with dTwo and ten with dTen?
My code works with one divisible statment but not two.
var num = new List<string>();
for (int n = 0; n < 101; n++)
{
num.Add(n % 2 == 0 ? "dTwo" : n.ToString());
num.Add(n % 10 == 0 ? "dTen" : n.ToString());
}
Since any number that is divisible by 10 is also divisible by 2 you have to switch your addition statements, and continue with the next number if you have a number divisible by 10:
var num = new List<string>();
for (int n = 0; n < 101; n++)
{
if( n % 10 == 0)
{
num.Add("dTen");
}
else num.Add(n % 2 == 0 ? "dTwo" : n.ToString());
}
If I can I try avoid using loop controls out side of the defined construct of the actual loop, ie. I prefer to avoid using continue if I can, it sort of feels like using goto statements. For this case, I would go for the plain and simple approach which I believe is readable, maintainable and simple albeit a little more verbose.
You can switch the order of the if/else if statements to change the priority if required, in this case the n % 10 has priority
var num = new List<string>();
for (int n = 0; n < 101; ++n)
{
if (n % 10 == 0)
{
num.Add("dTen");
}
else if (n % 2 == 0)
{
num.Add("dTwo");
}
else
{
num.Add(n.ToString());
}
}
There are two approaches I would take here, the first is verbose, but conveys what you're trying to do in a very readable manner:
var num = new List<string>(101);
for (int i = 0; i < 101 ; i++)
{
if (i == 0)
{
num.Add(i.ToString());
}
else if (i % 10 == 0)
{
num.Add("dTen");
}
else if (i % 2 == 0)
{
num.Add("dTwo");
}
else
{
num.Add(i.ToString());
}
}
The second uses a more concise LINQ-y type approach, like this.
var num = Enumerable.Range(0, 101)
.Select(
n => n == 0 ? n.ToString() :
n % 10 == 0 ? "dTen" :
n % 2 == 0 ? "dTwo" :
n.ToString())
.ToList();
Note that I've also taken into account the 0 edge case, where 0 would otherwise get reported as being divisible by 10.
Which one you go for is largely up to your taste. Personally I'd go for the latter implementation, as it's concise but still conveys the intent of the code. Some very rudimentary tests I've just done shows that it'll execute faster as well.

Categories