I have the following
1000 people
50 objects
Some "rules"
Each person must have exactly 1 object
All people can have the same object (people can share an object)
Not all objects have to be used
I want to chart out the permutations - How would I go about generating this structure in say C#?
I've currently just been randomly selecting an object for a person and remembering what I selected so I don't select it again in the next iteration - not useful I know.
Having 100 people and 50 objects you are going to have
100 ^ 50 = 1e100 # `^` means raising into power
googol solutions; it's by far more than elementary particles in the visible part of the Universe. That's why let not materialize the solution into any collection (2d array etc. - we are not looking for OutOfMemoryException) but enumerate them; at least you can stop enumerating whenever you want:
Code:
using System.Linq;
...
private static IEnumerable<(K key, V value)[]> MySampling<K, V>(IEnumerable<K> keys,
IEnumerable<V> values) {
if (keys is null)
throw new ArgumentNullException(nameof(keys));
if (values is null)
throw new ArgumentNullException(nameof(values));
IReadOnlyList<K> keysList = keys is IReadOnlyList<K> keysFound
? keysFound : keys.ToList();
IReadOnlyList<V> valuesList = values is IReadOnlyList<V> valuesFound
? valuesFound : values.ToList();
if (keysList.Count <= 0 || valuesList.Count <= 0)
yield break;
int[] indexes = new int[keysList.Count];
do {
yield return Enumerable
.Range(0, keysList.Count)
.Select(i => (key: keysList[i], value: valuesList[indexes[i]]))
.ToArray();
for (int i = indexes.Length - 1; i >= 0; --i)
if (++indexes[i] == valuesList.Count)
indexes[i] = 0;
else
break;
}
while (indexes.Any(index => index != 0));
}
Demo:
char[] people = { 'A', 'B', 'C', 'D' };
int[] objects = { 1, 2, 3 };
var result = MySampling(people, objects);
var report = string.Join(Environment.NewLine, result
.Select(line => string.Join(" ", line.Select(item => $"({item.key} : {item.value})"))));
Console.Write(report);
Output:
(A : 1) (B : 1) (C : 1) (D : 1) # all people - A, B, C, D - chose 1st object
(A : 1) (B : 1) (C : 1) (D : 2) # people A, B, C chose 1st, D chose 2nd object
(A : 1) (B : 1) (C : 1) (D : 3)
(A : 1) (B : 1) (C : 2) (D : 1)
(A : 1) (B : 1) (C : 2) (D : 2)
(A : 1) (B : 1) (C : 2) (D : 3)
(A : 1) (B : 1) (C : 3) (D : 1)
(A : 1) (B : 1) (C : 3) (D : 2)
(A : 1) (B : 1) (C : 3) (D : 3)
(A : 1) (B : 2) (C : 1) (D : 1)
(A : 1) (B : 2) (C : 1) (D : 2)
(A : 1) (B : 2) (C : 1) (D : 3)
(A : 1) (B : 2) (C : 2) (D : 1)
(A : 1) (B : 2) (C : 2) (D : 2)
(A : 1) (B : 2) (C : 2) (D : 3)
(A : 1) (B : 2) (C : 3) (D : 1)
(A : 1) (B : 2) (C : 3) (D : 2)
(A : 1) (B : 2) (C : 3) (D : 3)
(A : 1) (B : 3) (C : 1) (D : 1)
(A : 1) (B : 3) (C : 1) (D : 2)
(A : 1) (B : 3) (C : 1) (D : 3)
(A : 1) (B : 3) (C : 2) (D : 1)
(A : 1) (B : 3) (C : 2) (D : 2)
(A : 1) (B : 3) (C : 2) (D : 3)
(A : 1) (B : 3) (C : 3) (D : 1)
(A : 1) (B : 3) (C : 3) (D : 2)
(A : 1) (B : 3) (C : 3) (D : 3)
(A : 2) (B : 1) (C : 1) (D : 1)
(A : 2) (B : 1) (C : 1) (D : 2)
(A : 2) (B : 1) (C : 1) (D : 3)
(A : 2) (B : 1) (C : 2) (D : 1)
(A : 2) (B : 1) (C : 2) (D : 2)
(A : 2) (B : 1) (C : 2) (D : 3)
(A : 2) (B : 1) (C : 3) (D : 1)
(A : 2) (B : 1) (C : 3) (D : 2)
(A : 2) (B : 1) (C : 3) (D : 3)
(A : 2) (B : 2) (C : 1) (D : 1)
(A : 2) (B : 2) (C : 1) (D : 2)
(A : 2) (B : 2) (C : 1) (D : 3)
(A : 2) (B : 2) (C : 2) (D : 1)
(A : 2) (B : 2) (C : 2) (D : 2)
(A : 2) (B : 2) (C : 2) (D : 3)
(A : 2) (B : 2) (C : 3) (D : 1)
(A : 2) (B : 2) (C : 3) (D : 2)
(A : 2) (B : 2) (C : 3) (D : 3)
(A : 2) (B : 3) (C : 1) (D : 1)
(A : 2) (B : 3) (C : 1) (D : 2)
(A : 2) (B : 3) (C : 1) (D : 3)
(A : 2) (B : 3) (C : 2) (D : 1)
(A : 2) (B : 3) (C : 2) (D : 2)
(A : 2) (B : 3) (C : 2) (D : 3)
(A : 2) (B : 3) (C : 3) (D : 1)
(A : 2) (B : 3) (C : 3) (D : 2)
(A : 2) (B : 3) (C : 3) (D : 3)
(A : 3) (B : 1) (C : 1) (D : 1)
(A : 3) (B : 1) (C : 1) (D : 2)
(A : 3) (B : 1) (C : 1) (D : 3)
(A : 3) (B : 1) (C : 2) (D : 1)
(A : 3) (B : 1) (C : 2) (D : 2)
(A : 3) (B : 1) (C : 2) (D : 3)
(A : 3) (B : 1) (C : 3) (D : 1)
(A : 3) (B : 1) (C : 3) (D : 2)
(A : 3) (B : 1) (C : 3) (D : 3)
(A : 3) (B : 2) (C : 1) (D : 1)
(A : 3) (B : 2) (C : 1) (D : 2)
(A : 3) (B : 2) (C : 1) (D : 3)
(A : 3) (B : 2) (C : 2) (D : 1)
(A : 3) (B : 2) (C : 2) (D : 2)
(A : 3) (B : 2) (C : 2) (D : 3)
(A : 3) (B : 2) (C : 3) (D : 1)
(A : 3) (B : 2) (C : 3) (D : 2)
(A : 3) (B : 2) (C : 3) (D : 3)
(A : 3) (B : 3) (C : 1) (D : 1)
(A : 3) (B : 3) (C : 1) (D : 2)
(A : 3) (B : 3) (C : 1) (D : 3)
(A : 3) (B : 3) (C : 2) (D : 1)
(A : 3) (B : 3) (C : 2) (D : 2)
(A : 3) (B : 3) (C : 2) (D : 3)
(A : 3) (B : 3) (C : 3) (D : 1)
(A : 3) (B : 3) (C : 3) (D : 2)
(A : 3) (B : 3) (C : 3) (D : 3)
Related
I have a task, that gives me a little headache here. The goal is to find Greatest Common Divisor with three integers, I succeded in doing it with two fairly easily, but with three it get's a little complicated when I can't use any arrays.
Here is the full code I used, finding gcd from two integers, tests all green:
public static int GetGcdByEuclidean(int a, int b)
{
if (a == 0 && b == 0)
{
throw new ArgumentException(null);
}
else if (a == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(a));
}
else if (b == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(b));
}
else
{
int abs1 = Math.Abs(a);
int abs2 = Math.Abs(b);
a = abs1;
b = abs2;
while (a != 0 && b != 0)
{
if (a > b)
{
a %= b;
}
else
{
b %= a;
}
}
return a | b;
}
}
And now I used the same principle for the GCD by three, but used something I found on web: gcd(a, b, c) = gcd(a, gcd(b, c)) = gcd(gcd(a, b), c) = gcd(gcd(a, c), b)..
public static int GetGcdByEuclidean(int a, int b, int c)
{
int result = 0;
if ((a == 0 && b == 0) && c == 0)
{
throw new ArgumentException(null);
}
else if (a == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(a));
}
else if (b == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(b));
}
else if (c == int.MinValue)
{
throw new ArgumentOutOfRangeException(nameof(c));
}
else
{
int abs1 = Math.Abs(a);
int abs2 = Math.Abs(b);
int abs3 = Math.Abs(c);
a = abs1;
b = abs2;
c = abs3;
while (a != 0 && b != 0 && c != 0)
{
if (a > b && a > c && b > c)
{
b %= c;
a %= b;
result = a;
}
else if (a > b && a > c && b < c)
{
c %= b;
a %= c;
result = a;
}
else if (b > a && b > c && a > c)
{
a %= c;
b %= a;
result = b;
}
else if (b > a && b > c && a < c)
{
c %= a;
b %= c;
result = b;
}
else if (c > a && c > b && a > b)
{
a %= b;
c %= a;
result = c;
}
else
{
b %= a;
c %= b;
result = c;
}
}
return result;
}
}
Just keep your solution for 2 numbers and call it from the one for three numbers by using this formula: gcd(a, b, c) = gcd(a, gcd(b, c))
public static int GetGcdByEuclidean(int a, int b)
{
// Your working solution for two numbers...
}
public static int GetGcdByEuclidean(int a, int b, int c)
{
return GetGcdByEuclidean(a, GetGcdByEuclidean(b, c));
}
Note, in C# you can have several methods with the same name, as long as the parameter lists are different. The names of the parameters do not matter, only the number or types of the parameters must be different. This is called overloading.
A solution with an arbitrary number of numbers (but at least two):
public static int GetGcdByEuclidean(int a, int b, params int[] other)
{
int gcd = GetGcdByEuclidean(a, b);
foreach (int x in other) {
gcd = GetGcdByEuclidean(gcd, x);
}
return gcd;
}
I have this code:
int a, b;
if (a > 0)
{
a--;
DoSomething()
}
else if (b > 0)
{
b--;
DoSomething();
}
I heard it's better to not write the same line (DoSomething();) twice, so is there a way to do this:
int a, b;
if (a > 0 /* if true a--; */ || b > 0 /* if true b--; */)
{
DoSomething();
}
In other words, is there a better way to do this (without writing DoSomething(); twice):
int a, b;
if (a > 0)
{
a--;
DoSomething()
}
else if (b > 0)
{
b--;
DoSomething();
}
If these are the only or the last statements in the method, you could return in an additional else statement:
if (a > 0)
{
a--;
}
else if (b > 0)
{
b--;
}
else
{
return;
}
DoSomething();
If these are the last statements in a loop you can use continue instead of return. In a switch case you can use break.
If DoSomething involves something more complex, then using a flag would be appropriate. Otherwise calling DoSomething twice is just fine.
bool isDecremented = false;
if (a > 0)
{
a--;
isDecremented = true;
}
else if (b > 0)
{
b--;
isDecremented = true;
}
if (isDecremented)
{
// Do something more complex.
}
int a, b;
if (a > 0 || b > 0)
{
if(a > 0)
a--;
else
b--;
DoSomething();
}
You could use a local method to avoid the repetition:
void DecrementAndDoSomething(ref int i)
{
i--;
DoSomething();
}
if (a > 0) DecrementAndDoSomething(ref a);
else if (b > 0) DecrementAndDoSomething(ref b);
How about writing like this?
if ((a > 0 && a-- > 0) || (b > 0 && b-- > 0))
DoSomething();
I want to remove parentheses only when the whole text is surrounded by them. For example:
(text (text) text)
need's to be convert to:
text (text) text
I have a very simple check:
value = (value [0] == '(' && value [value .Length - 1] == ')') ? value.Substring(1, value .Length - 2) : value;
but it fails and incorrectly removes the parentheses of these kind of strings:
(text (text) ) text (text)
Could anyone tell a way to handle all cases? Using regular expression is OK as well.
Note, that the parentheses are balanced. For example, such case is not possible:
( text ( text )
Use a simple loop for testing, if it's "valid" for removal, remove first & last:
bool isValid = value[0] == '(' && value[value.Length - 1] == ')';
int i = 1;
int c = 0;
for(; isValid && c >= 0 && i < value.Length - 1; i++)
{
if(value[i] == '(')
c++;
else if(value[i] == ')')
c--;
}
if(isValid && i == (value.Length - 1) && c == 0)
value = value.Substring(1, value.Length - 2);
This extension method should work;
public static class StringExtensions
{
public static string RemoveParentheses(this string value)
{
if (value == null || value[0] != '(' || value[value.Length - 1 ] != ')') return value;
var cantrim = false;
var openparenthesesIndex = new Stack<int>();
var count = 0;
foreach (char c in value)
{
if (c == '(')
{
openparenthesesIndex.Push(count);
}
if (c == ')')
{
cantrim = (count == value.Length - 1 && openparenthesesIndex.Count == 1 && openparenthesesIndex.Peek() == 0);
openparenthesesIndex.Pop();
}
count++;
}
if (cantrim)
{
return value.Trim(new[] { '(', ')' });
}
return value;
}
}
Use it like this
Console.WriteLine("(text (text) ) text (text)".RemoveParentheses());
Ran a few test cases and I think this is good
public string CleanString(string CleanMe)
{
if (string.IsNullOrEmpty(CleanMe)) return CleanMe;
string input = CleanMe.Trim();
if (input.Length <= 2) return input;
if (input[0] != '(') return input;
if (input[input.Length-1] != ')') return input;
int netParen = 1; // starting loop at 1 have one paren already
StringBuilder sb = new StringBuilder();
for (int i = 1; i < input.Length-1; i++)
{
char c = input[i];
sb.Append(c);
if (c == '(') netParen++;
else if (c == ')') netParen--;
if (netParen == 0) return input; // this is the key did the () get closed out
}
return sb.ToString();
}
I started this before the answer from Amit but I think it is the same basic logic
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have an if...else if statement as follows:
If(x > y && order.invoice != 1)
{
DoSomething();
x = x + y;
}
else if(order.invoice == 1)
{
x = x + y;
}
Is there a better way to re-factor this. I kind of not feeling well having x = x + y in both if and else if.
if (order.invoice != 1 && x > y) {
DoSomething();
}
if (order.invoice == 1 || x > y) {
x = x + y;
}
You can either do the assignment twice or do one of the if statements twice. This calculation is simple enough that I wouldn't worry about it.
It can be shortened as such, though:
if(x > y && order.invoice != 1)
{
DoSomething();
x += y;
}
else if(order.invoice == 1)
{
x += y;
}
One more option could be to use an flag to see whether or not to increment, but you still have the same tug-of-war between complexity and single calls vs. simplicity and semi-redundant code.
bool increment = false;
if(x > y && order.invoice != 1)
{
DoSomething();
increment = true;
}
else if(order.invoice == 1)
{
increment = true
}
if (increment) { x += y; }
Here's a proof/systematic way to refactor it. Start with:
if (x > y && order.invoice != 1)
{
DoSomething();
x = x + y;
}
else if (order.invoice == 1)
{
x = x + y;
}
So the question is, what set of inputs leads to x = x + y? Well:
x = x + y
<=> (x > y && order.invoice != 1) ||
(!(x > y && order.invoice != 1) && order.invoice == 1)
<=> (x > y && order.invoice != 1) ||
((x <= y || order.invoice == 1) && order.invoice == 1)
<=> (x > y && order.invoice != 1) ||
((x <= y && order.invoice == 1) || (order.invoice == 1 && order.invoice == 1)
<=> (x > y && order.invoice != 1) ||
((x <= y && order.invoice == 1) || order.invoice == 1)
<=> (x > y && order.invoice != 1) ||
order.invoice == 1
<=> (x > y || order.invoice == 1) && (order.invoice != 1 || order.invoice == 1)
<=> (x > y || order.invoice == 1)
Thus it's equivalent to
if (x > y && order.invoice != 1)
{
DoSomething();
}
if (x > y || order.invoice == 1)
{
x = x + y;
}
You can also use a truth table
x > y | order.invoice == 1 | x = x + y
F | F | N
F | T | Y
T | F | Y
T | T | Y
which again gives you
x = x + y
<=> !(x <= y && order.invoice != 1)
<=> x > y || order.invoice == 1
Lastly, I disagree with this sort of refactoring unless it actually makes the code more understandable.
Saving lines of code doesn't mean you made the code more readable (and therefore does not make it
obviously more maintainable)
I want to find the sum of all the multiples of 3 or 5 below 1000.
My traditional for loop way is
for(int i=0;i<1000;i++)
{
if ((i % 3 == 0) || (i % 5 == 0))
{
result += i;
}
}
Console.WriteLine(result);
How can I do this using a lambda instead?
Enumerable.Range(0, 1000).Where(i => i % 3 == 0 || i % 5 == 0).Sum()
Or
Enumerable.Range(0, 1000).Sum(i => i % 3 == 0 || i % 5 == 0 ? i : 0)
result = Enumerable
.Range(0, 1000)
.Sum(i => (i % 3 == 0) || (i % 5 == 0) ? i : 0);
This should do it.