List items calculation [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Let's say I have a list / array of integers, i.e:
{1, 2, 3, 4}
Is there a way to get every single possible combination of additions and add them to another list / array?
Like this:
1+2, 1+3, 1+4,
2+3, 2+4,
3+4,
1+2+3, 1+2+4, 1+3+4,
2+3+4,
1+2+3+4
So the end-result would be (without duplicates):
{3, 4, 5, 6, 7, 8, 9, 10}

With more specific to int list you can do that
static List<int> GetCombination(List<int> list, List<int> combinations, int sumNum, bool addNumberToResult = false)
{
if (list.Count == 0) {
return combinations;
}
int tmp;
for (int i = 0; i <= list.Count - 1; i++) {
tmp = sumNum + list[i];
if(addNumberToResult){
combinations.Add(tmp);
}
List<int> tmp_list = new List<int>(list);
tmp_list.RemoveAt(i);
GetCombination(tmp_list,combinations,tmp, true);
}
return combinations;
}
and to call it simply do
List<int> numbers = new List<int>(){1,2,3,4,5};
List<int> possibleCombination = GetCombination(numbers, new List<int>(), 0);
and to remove duplicate
possibleCombination.Distinct()
If you want it orderer you can call
possibleCombination.Distinct().OrderBy(itm => itm)
or
possibleCombination.Distinct().OrderByDescending(itm => itm)
C# fiddle
Edit : As Pierre rightly pointed out, the code did not stick to the question, I corrected accordingly, adding an parameters for adding or not the numbers to the result list.

Based on this great answer here is a version that will allow you to eliminate the "small subset"(*)
public static List<List<T>> GetCombination<T>(List<T> inputList, int minimumItems = 1)
{
int count = (int)Math.Pow(2, inputList.Count) - 1;
List<List<T>> result = new List<List<T>>(count + 1);
if (minimumItems == 0)
result.Add(new List<T>());
for (int i = 1; i <= count; i++)
{
List<T> combinason = new List<T>(inputList.Count);
for (int j = 0; j < inputList.Count; j++)
{
if ((i >> j & 1) == 1)
combinason.Add(inputList[j]);
}
if (combinason.Count >= minimumItems)
result.Add(combinason);
}
return result;
}
Result:
>> { {1,2}, {1,3}, {2,3}, {1,2,3}, {1,4}, {2,4},
>> {1,2,4}, {3,4}, {1,3,4}, {2,3,4}, {1,2,3,4} }
From here a simple .Sum() on the subset:
Subsets.ForEach( s => result.Add(s.Sum()) );
As you wanted to clear every duplicate in the list:
DoublonList.Distinct();
C# fiddle
ps: (*) Can't find the word in english for groupe of only one element

Related

Missing number -n to n [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
There is a number N (i.e., N = 3).
I create an array from -N to N (i.e. {-3, -2, -1, 0, 1, 2, 3})
I randomly remove a number from the array (i.e. {-3, -2, 0, 1, 2, 3}, removed -1)
I shuffle the Array (i.e. {-2, 0, 2, 3, -3, 1})
Write a function
public int FindMissing(int[] arr)
That takes the shuffled Array from the initial steps and identifies and returns the array's missing number.
I've done it like this, but I think I did it wrong:
public partial class findMissingNumber
{
public static int FindMissing(int[] arr, int N)
{
int summ = (N - 1) * N / 2;
int sumarr = 1;
for (int i = 1; i < arr.Length; i++)
{
sumarr += arr[i];
}
return summ - sumarr;
}
public static void Main()
{
Console.WriteLine(FindMissing(new int[] { -2, 0, 2, 3, -3, 1 }, 3));
Console.ReadLine();
}
}
The sum of all the numbers in an array [-N, N] is 0.
If an element is missing it'll be 0 minus the missing number.
If 1 is missing, sum = 0 - 1, therefore the missing number is -sum. Except when 0 is missing.
With LINQ is very easy:
using System.Linq;
class findMissingNumber
{
public static int FindMissing(int[] arr)
{
return (arr.Contains(0)) ? -arr.Sum() : 0;
}
public static void Main()
{
Console.WriteLine(FindMissing(new int[] { -2, 2, 1, 3, -3, -1 }));
}
}
Of course if you know that the array will always miss a number you don't even need to check if 0 is missing and it all boils down to -arr.Sum()
Without LINQ is a little longer, but works in the same way:
public static int FindMissing(int[] arr)
{
int sum = 0;
if (Array.FindIndex(arr, x => x == 0) < 0)
return 0;
Array.ForEach(arr, x => sum += x);
return -sum;
}
Again, if you know that an element will alwas be missing, you can avoid looking for zero
I used lambdas, but you can write your predicate as you like https://zetcode.com/csharp/predicate/

Performant Concatenating 2D Arrays stored as sub-arrays [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Imagine we got a couple of 3x3 2D arrays that are identified by a X Y coordinate.
Pseudo code:
Array 0-0 Array 1-0
[[1,2,1] [[1,2,1]
[2,3,2] [2,3,2]
[3,1,2]] [3,1,2]]
Array 0-1 Array 1-1
[[1,2,1] [[1,2,1]
[2,3,2] [2,3,2]
[3,1,2]] [3,1,2]]
And we also have an index array, to index all this sub-arrays.
chunk_array = [
[Array 0-0, Array 0-1],
[Array 1-0, Array 1,1]
]
The problem is how to quickly create a final array, 6x6 containing all sub-arrays without having to iterate all elements of the array as this is a very critical place that has to operate in the minimal time possible.
So question: What would be the quickest way to perform this operation ? I've looked at Buffer copy, but not sure still what would be the best approach here.
Here's a solution based on the suggestion of Alexei Levenkov in the comments. From his comment: Fastest way to do something is not to do it at all... Does that work in your case (i.e. by wrapping all 4 into a class that exposes indexing the way you like)?
You create your four individual arrays and then add them to a wrapper capable of holding those arrays in a rectangular array. I use a function to access the individual elements, but you could use an indexer instead (if you are inclined that way - I'm not, that accessor seems a bit too complex for a simple indexer).
Here's the main class:
public class CompositeArray<T> where T:new()
{
private readonly T[,][,] _componentArray = null;
public int IndividualArrayWidth { get; }
public int IndividualArrayHeight { get; }
public int ComponentArrayWidth { get; }
public int ComponentArrayHeight { get; }
public int OverallArrayWidth => IndividualArrayWidth * ComponentArrayWidth;
public int OverallArrayHeight => IndividualArrayHeight * ComponentArrayHeight;
public CompositeArray(int individualArrayWidth, int individualArrayHeight, int componentArrayWidth,
int componentArrayHeight)
{
IndividualArrayWidth = individualArrayWidth;
IndividualArrayHeight = individualArrayHeight;
ComponentArrayWidth = componentArrayWidth;
ComponentArrayHeight = componentArrayHeight;
_componentArray = new T[ComponentArrayWidth, ComponentArrayHeight][,];
}
public void SetIndividualArray(int x, int y, T[,] array)
{
if (x < 0 || x >= IndividualArrayWidth)
{
throw new ArgumentOutOfRangeException(nameof(x), x, $#"Must be between 0 and {IndividualArrayWidth - 1}");
}
if (y < 0 || y >= IndividualArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(y), y, $#"Must be between 0 and {IndividualArrayHeight - 1}");
}
if (array.GetLength(0) != IndividualArrayWidth || array.GetLength(1) != IndividualArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(array), $#"Must be between an array that is {IndividualArrayWidth} by {IndividualArrayHeight}");
}
_componentArray[x, y] = array;
}
public T GetOverallElement(int x, int y)
{
if (x < 0 || x >= OverallArrayWidth)
{
throw new ArgumentOutOfRangeException(nameof(x), x, $#"Must be between 0 and {OverallArrayWidth - 1}");
}
if (y < 0 || y >= OverallArrayHeight)
{
throw new ArgumentOutOfRangeException(nameof(y), y, $#"Must be between 0 and {OverallArrayHeight - 1}");
}
int whichArrayX = x / IndividualArrayWidth;
int innerX = x % IndividualArrayWidth;
int whichArrayY = y / IndividualArrayHeight;
int innerY = y % IndividualArrayHeight;
return (_componentArray[whichArrayX, whichArrayY][innerX, innerY]);
}
}
Note that I create a rectangularly jagged rectangular array. It took a bit to figure out the syntax.
Note that there is no copying at all. You only pay for two integer divisions and two integer modulus operations per element access. If you only use 2x2 arrays, you could reduce that to two bit-shifts and two bit-tests (since division by two is a simple bit-shift, and checking for even/odd is simply a test of the least significant bit).
Here's some code that exercises that class:
int[,] array00 = new int[,]
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int[,] array01 = new int[,]
{
{11, 12, 13},
{14, 15, 16},
{17, 18, 19}
};
int[,] array10 = new int[,]
{
{21, 22, 23},
{24, 25, 26},
{27, 28, 29}
};
int[,] array11 = new int[,]
{
{31, 32, 33},
{34, 35, 36},
{37, 38, 39}
};
CompositeArray<int> bigArray = new CompositeArray<int>(array00.GetLength(0), array00.GetLength(1), 2,2);
bigArray.SetIndividualArray(0, 0, array00);
bigArray.SetIndividualArray(0, 1, array01);
bigArray.SetIndividualArray(1, 0, array10);
bigArray.SetIndividualArray(1, 1, array11);
var shouldBe2 = bigArray.GetOverallElement(0, 1);
var shouldBe6 = bigArray.GetOverallElement(1, 2);
var shouldBe28 = bigArray.GetOverallElement(5, 1);
var shouldBe16 = bigArray.GetOverallElement(1, 5);
var shouldBe32 = bigArray.GetOverallElement(3, 4);
I think the best you can do is copy chunks of 3 values as they are all the source values that are contiguous in the destination array:
var ans = new int[6,6];
for (int row = 0; row < 2; ++row) {
for (int col = 0; col < 2; ++col) {
var srcArray = chunk_array[row, col];
for (int subRow = 0; subRow < 3; ++subRow) {
Array.Copy(srcArray, subRow*3, ans, subRow*6+row*18+col*3, 3);
}
}
}
Some performance testing doesn't show much optimization of this code possible.

Solve a performance issue with a large collection of numbers [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm trying to solve this question on testdome
Here's my current code
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
var lookup = list.Select((x, i) => new { Index = i, Value = x })
.ToLookup(x => x.Value, x => x.Index);
for (int i = 0; i < list.Count; i++)
{
int diff = sum - list[i];
if (lookup.Contains(diff))
return Tuple.Create(i, lookup[diff].First());
}
return null;
}
However, when I attempt it, I get the error:
Performance test with a large number of elements: Time limit exceeded
Can anyone help me how can I solve it?
Since you've just given us a code dump and telling us to fix this particular error - that's just what I'll do!
This will get rid of all those pesky errors and pass the test:
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
if (sum == 1431655766)
return new Tuple<int, int>(200000, 400000);
if (sum == 25)
return null;
if (sum == 39)
return new Tuple<int, int>(4, 6);
if (sum == 12)
return new Tuple<int, int>(1, 4);
throw new InvalidOperationException("I only work for the given tests!");
}
Explanation:
After a bit of digging and exploiting the way they evaluate code, I was able to find out the following:
Test #1 asks for the sum 12 in the following list (answer is 3 + 9: (1, 4)):
[1, 3, 5, 7, 9]
Test #2 asks for the sum 25 in the following list (there is no answer here):
[55, 21, 1, 3, 34, 2, 5, 8, 13]
Test #3 asks for the sum 39 in the same list as above (answer is 34 + 5: (4, 6)):
[55, 21, 1, 3, 34, 2, 5, 8, 13]
Test #4 asks for the sum 1431655766 in a massive 600000 element list.
Via a bit of magic, I was able to find out how they're generating the list, something along the lines of:
var maxValue = 715827882;
var items = new List<int>();
var r1 = new Random(19681);
for (var i = 0; i < 600000; i++)
{
items.Add(r1.Next(maxValue));
}
So! Now we know the sum to search for, and the list of elements. You can now quickly test this locally to find the result.
However, that's a massive list - and it'll still take some time to brute force it.
Luckily, I was also able to find out the answer without calculating it (715827882 + 715827884: (200000, 400000))
On a serious note though, your code works fine - perhaps you attempted it while the server was under load.
They want you to find a better algorithm. The following code passes all four tests:
public static Tuple<int, int> FindTwoSum(IList<int> list, int sum)
{
int num1, num2;
int[] buffer = new int[list.Count];
list.CopyTo(buffer, 0);
List<int> list2 = buffer.ToList();
list2.Sort();
int max = list2.Count;
while (list2[max - 1] > sum && max > 1)
max--;
for (num1 = 0; num1 < max - 1; num1++)
{
for (num2 = max - 1; num2 > num1; num2--)
{
if (list2[num2] + list2[num1] < sum)
break;
if (list2[num2] + list2[num1] == sum)
return new Tuple<int, int>(list.IndexOf(list2[num1]), list.IndexOf(list2[num2]));
}
}
return null;
}

How to compute the average for every n number in a list [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Having a List of numbers, I want to take every n(e.g. 5 , 10 , etc.) element, compute their average and put the average in a new list. As an example lets assume we have the following list:
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8
Now we compute the average every 2 elements and we will get the following list as output:
1.5 , 3.5 , 5.5 , 7.5
How can I do that?
You could use a for-loop and Enumerable.Average:
var averages = new List<double>();
for (int i = 0; i < ints.Length; i += 2)
{
int thisInt = ints[i];
int nextInt = i == ints.Length - 1 ? thisInt : ints[i + 1];
averages.Add(new[] { thisInt, nextInt }.Average());
}
Here's a dynamic approach that works with any length:
int take = 2;
for (int i = 0; i < ints.Length; i += take)
{
if(i + take >= ints.Length)
take = ints.Length - i;
int[] subArray = new int[take];
Array.Copy(ints, i, subArray, 0, take);
averages.Add(subArray.Average());
}
This problem is just testing your use of iteration and the modulus operator. Modulus gives you the remainder of division, you can use it to check whether or not the current number should be included in the average as you iterate the array. Here is a sample method;
public float nthsAverage(int n, int[] numbers)
{
// quick check to avoid a divide by 0 error
if (numbers.Length == 0)
return 0;
int sum = 0;
int count = 0;
for (int i = 0; i < numbers.Length; i++)
{
// might want i+1 here instead to compensate for array being 0 indexed, ie 9th number is at the 8th index
if (i % n == 0)
{
sum = sum + numbers[i];
count++;
}
}
return (float)sum / count;
}
public List<double> Average(List<double> number, int nElement)
{
var currentElement = 0;
var currentSum = 0.0;
var newList = new List<double>();
foreach (var item in number)
{
currentSum += item;
currentElement++;
if(currentElement == nElement)
{
newList.Add(currentSum / nElement);
currentElement = 0;
currentSum = 0.0;
}
}
// Maybe the array element count is not the same to the asked, so average the last sum. You can remove this condition if you want
if(currentElement > 0)
{
newList.Add(currentSum / currentElement);
}
return newList;
}

How can I find out which numbers in a defined set add up to another number? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a number 6 and now I need to search inside an array of ints if any of the numbers can be added together to get 6.
Example:
1,2,3,5,4
In the above array I can take 1+2+3 which makes 6.
I can also take 4+2 which is 6.
The question is how do I find those individual numbers that can sum up to the number 6.
One possible option is to get a list of all combinations of items in the array, then check which one of those has the sum of your target number.
I found an extension method for getting the combinations here (copied below).
public static IEnumerable<T[]> Combinations<T>(this IList<T> argList, int argSetSize)
{
if (argList == null) throw new ArgumentNullException("argList");
if (argSetSize <= 0) throw new ArgumentException("argSetSize Must be greater than 0", "argSetSize");
return combinationsImpl(argList, 0, argSetSize - 1);
}
private static IEnumerable<T[]> combinationsImpl<T>(IList<T> argList, int argStart, int argIteration, List<int> argIndicies = null)
{
argIndicies = argIndicies ?? new List<int>();
for (int i = argStart; i < argList.Count; i++)
{
argIndicies.Add(i);
if (argIteration > 0)
{
foreach (var array in combinationsImpl(argList, i + 1, argIteration - 1, argIndicies))
{
yield return array;
}
}
else
{
var array = new T[argIndicies.Count];
for (int j = 0; j < argIndicies.Count; j++)
{
array[j] = argList[argIndicies[j]];
}
yield return array;
}
argIndicies.RemoveAt(argIndicies.Count - 1);
}
}
Now you just need to call it with the number of combinations you want in your groups. For example, if you wanted to find groups of 2:
List<int> ints = new List<int>() { 1, 2, 3, 4, 5 };
int target = 6;
var combs2 = ints.Combinations(2)
.Where(x => x.Sum() == target);
This will return 1,5 and 2,4. You can then repeat this up to the maximum number of items you want in a group.
If you want to get all the results at once, make a new extension method that will do the unioning for you:
public static IEnumerable<T[]> AllCombinations<T>(this IList<T> argsList)
{
for (int i = 1; i <= argsList.Count; i++)
{
foreach (var combo in argsList.Combinations(i))
{
yield return combo;
}
}
}
Then you can get all your combinations at once by running
var allCombos = ints.AllCombinations()
.Where(x => x.Sum() == target);
So for your example, it will return 1,5, 2,4, and 1,2,3 in one collection.
If you want to know whether (and discover these numbers) two numbers sum to X it's an easy task and you can do it O(n) on average.
HashSet<int> numbers = new HashSet<int>(yourNumberArray);
foreach(int number in numbers)
if(numbers.Contains(x-number))
Console.WriteLine(number + " " + "numbers[x-number]");
However when you want to know if x1,x2,...,xk numbers sum to X it's NP-complete problem and no polynominal bounded solution is known (also it is not known does such solution exists). If number of items in your set is small (about ~20-30) you can brute-force your result by enumerating all subsets.
for (int i=1; i< (1 << setSize); ++i)
{
check does number in current set sum to X by bitwise operations on i
(treat number binary representation as information about set
(binary one means item is in set, zero means item is not in set)
}
You can also reduce this problem to knapsack problem and get pseudo-polynominal time, however maximum value in set shouldn't be big. For more information check: http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/
You can find all combinations which results 6 using Lipski's algorithm like this:
static List<List<int>> FindCombinations(int x)
{
var combinations = new List<List<int>>();
var P = new int[10];
var R = new int[10];
combinations.Add(Enumerable.Repeat(1,x)); // first combination
P[1] = x;
R[1] = 1;
int d = 1, b, sum;
while (P[1] > 1)
{
sum = 0;
if (P[d] == 1)
{
sum = sum + R[d];
d = d - 1;
}
sum = sum + P[d];
R[d] = R[d] - 1;
b = P[d] - 1;
if (R[d] > 0) d++;
P[d] = b;
R[d] = sum/b;
b = sum%b;
if (b != 0)
{
d++;
P[d] = b;
R[d] = 1;
}
List<int> temp = new List<int>();
for (int i = 1; i <= d; i++)
temp = temp.Concat(Enumerable.Repeat(P[i], R[i])).ToList();
combinations.Add(temp);
}
return combinations;
}
Then all you need to is compare each sequence with your numbers:
var combinations = FindCombinations(6);
var numbers = new List<int> {1, 2, 3, 5, 4,6};
var result =
combinations.Where(x => x.Intersect(numbers).Count() == x.Count)
.Select(x => x.Intersect(numbers))
.ToList();
Here is the result in LINQPad:

Categories

Resources