calculate combination in C# without recursive function - c#

i would like to calculate all the combination possible, but i don't want to use recursive function just some simple code in C# ?
Here is example :
col1 col2 col3
valueinf= 5 6 7
valuesup= 10 20 30
i want this for result:
res1 = 5+6+7
res2 = 5+6+30
res3 = 5+20+7
res4 = 5+20+30
res5 = 10+6+7
res6 = 10+6+30
res7 = 10+20+7
res8 = 10+20+30
the number of colonne is variable but i wil allways have 2 lines one inferior and one superior.
I don't know how to begin the algorithm. Some help will be gratefull just to begin

Well, will-nilly you have to loop:
using System.Linq;
...
private static IEnumerable<int> Sums(IEnumerable<int[]> columns) {
if (columns is null)
throw new ArgumentNullException(nameof(columns));
int[][] data = columns.ToArray();
int[] pos = new int[data.Length];
do {
yield return Enumerable.Range(0, data.Length).Sum(i => data[i][pos[i]]);
for (int i = pos.Length - 1; i >= 0; --i)
if (pos[i] == data[i].Length - 1)
pos[i] = 0;
else {
pos[i] += 1;
break;
}
}
while (!pos.All(p => p == 0));
}
The very same idea if you want to print formulae:
private static IEnumerable<string> Formulae(IEnumerable<int[]> columns) {
if (columns is null)
throw new ArgumentNullException(nameof(columns));
int[][] data = columns.ToArray();
int[] pos = new int[data.Length];
do {
yield return string.Join("+", Enumerable
.Range(0, data.Length).Select(i => data[i][pos[i]]));
for (int i = pos.Length - 1; i >= 0; --i)
if (pos[i] == data[i].Length - 1)
pos[i] = 0;
else {
pos[i] += 1;
break;
}
}
while (!pos.All(p => p == 0));
}
Demo:
List<int[]> columns = new List<int[]>() {
new int[] {5, 10},
new int[] {6, 20},
new int[] {7, 30},
};
var sums = Sums(columns);
var formulae = Formulae(columns);
Console.WriteLine(string.Join(Environment.NewLine, sums
.Select((v, i) => $"res{i+1} = {v}")));
Console.WriteLine();
Console.WriteLine(string.Join(Environment.NewLine, formulae
.Select((v, i) => $"res{i+1} = {v}")));
Outcome:
res1 = 18
res2 = 41
res3 = 32
res4 = 55
res5 = 23
res6 = 46
res7 = 37
res8 = 60
res1 = 5+6+7
res2 = 5+6+30
res3 = 5+20+7
res4 = 5+20+30
res5 = 10+6+7
res6 = 10+6+30
res7 = 10+20+7
res8 = 10+20+30
Edit: To find the best fit you can exploit the very same principle:
private static (int[] pos, int diff, string formula) BestFit(int target, IEnumerable<int[]> columns) {
if (columns is null)
throw new ArgumentNullException(nameof(columns));
int[][] data = columns.ToArray();
int[] pos = new int[data.Length];
int bestDiff = -1;
int[] bestPos = null;
do {
int diff = Math.Abs(target - Enumerable.Range(0, data.Length).Sum(i => data[i][pos[i]]));
if (diff < bestDiff || bestPos == null) {
bestPos = pos.ToArray();
bestDiff = diff;
}
for (int i = pos.Length - 1; i >= 0; --i)
if (pos[i] == data[i].Length - 1)
pos[i] = 0;
else {
pos[i] += 1;
break;
}
}
while (!pos.All(p => p == 0));
return (
bestPos,
bestDiff,
string.Join("+", Enumerable.Range(0, data.Length).Select(i => data[i][bestPos[i]]))
);
}
Demo:
int[][] data = new int[][] {
new int[] {5, 10},
new int[] {6, 20},
new int[] {7, 30},
};
var fit = BestFit(20, data);
Console.Write($"delta = {fit.diff}; formula = {fit.formula}");
Outcome:
delta = 2; formula = 5+6+7

Related

Numbers distribution

I have a problem with numbers distribution to perfectly fit given container. My numbers are:
int[] number = {50, 40, 30, 30, 25, 25};
I want to find a best combo which will be nearest to 100, and when no more options available start another container of 100. Simple solution like sorting and adding from max to min won't work, because:
int[] firstContainer = { 50, 40 }; //10 unused
int[] secontContainer = { 30, 30, 25 }; //15 unused
int[] thirdContainer = { 25 }; //75 unused
The result what I'm looking for is:
int[] firstContainer = { 50, 25, 25 }; //0 unused
int[] secontContainer = { 40, 30, 30 }; //0 unused
Is there any kind soul willing to help me solve the problem?
Here is one solution - it can be optimized and improved, but now you have a starting point. Starting point is to create all combinations of your initial array and then get the sum
static void Main(string[] args)
{
int[] number = { 50, 40, 30, 30, 25, 25 };
foreach (var kvp in Exercise(number, 100))
{
Console.WriteLine("Solution " + kvp.Key);
foreach (var sol in kvp.Value)
{
Console.Write(sol + " ");
}
Console.WriteLine();
}
}
private static Dictionary<int, List<int>> Exercise(int[] number, int sum)
{
Dictionary<int, List<int>> results = new Dictionary<int, List<int>>();
int counter = 0;
var numberOfCombinations = Math.Pow(2, number.Count());
for (int i = 0; i < numberOfCombinations; i++)
{
//convert an int to binary and pad it with 0, so I will get an array which is the same size of the input[] array. ie for example 00000, then 00001, .... 11111
var temp = Convert.ToString(i, 2).PadLeft(number.Count(), '0').ToArray();
List<int> positions = new List<int>();
int total = 0;
for (int k = 0; k < temp.Length; k++)
{
if (temp[k] == '1')
{
total += number[k];
positions.Add(number[k]);
}
}
if (total == sum)
{
results.Add(counter, positions);
counter++;
}
}
return results;
}
My solution is based on generating random and feasible answers, at the end we can find best answer :
static void Main(string[] args)
{
int[] number = { 50, 40, 30, 30, 25, 25 };
int bound = 100;
var numbers = new List<dynamic>();
Random rnd = new Random();
var ans_collection = new List<List<List<int>>>();
//number of random answers , best answer depends on i so you can't be sure this algorithm always finds optimal answer choose i big enough...
for (int i = 0; i < 100; i++)
{
for (int j = 0; j < number.Length; j++)
{
numbers.Add(new { num = number[j], seen = false });
}
var ans = new List<List<int>>();
var container = new List<int>();
var distSum = 0;
//while loop generates a distribution
while (numbers.Where(x => !x.seen).Count() > 0)
{
var chosen = numbers.OrderBy(x => rnd.NextDouble()).Where(x => !x.seen && distSum + x.num <= bound).FirstOrDefault();
if (numbers.Where(x => !x.seen && distSum + x.num <= bound).Count() > 0)
{
container.Add(chosen.num);
distSum += chosen.num;
numbers.Add(new { num = chosen.num, seen = true });
numbers.Remove(chosen);
if (numbers.Where(x => !x.seen && distSum + x.num <= bound).Count() == 0)
{
ans.Add(new List<int>(container));
container = new List<int>();
distSum = 0;
}
}
else
{
ans.Add(new List<int>(container));
container = new List<int>();
distSum = 0;
}
}
ans_collection.Add(new List<List<int>>(ans));
}
//find best answer based on sum of *unused* amounts
var min = ans_collection.Min(ans => ans.Sum(dis => (bound - dis.Sum())));
var best = ans_collection.Where(ans => ans.Sum(dis => (bound - dis.Sum())) == min).FirstOrDefault();
best.ForEach(x => Console.WriteLine(string.Join(",", x.Select(Y => Y.ToString()))));
}

How does ACCORDs Deep neural learning work?

I get an error when I try to run DeepNeuralLearning from ACCORDs toolbox. It works when I run it as:
var inputs = new double[3][];
inputs[0] = new double[] {1, 2, 3};
inputs[1] = new double[] {1, 2, 3};
inputs[2] = new double[] {1, 2, 3};
var classes = new[] {0, 1, 2};
var outputs = Tools.Expand(classes, -1, 1);
var network = new DeepBeliefNetwork(3, 4, 3, 2);
var teacher = new DeepNeuralNetworkLearning(network)
{
Algorithm = (ann, i) => new ParallelResilientBackpropagationLearning(ann),
LayerIndex = network.Layers.Length - 1
};
var error = teacher.RunEpoch(inputs, outputs);
However, when I tweak the code to accept a 21 x 30,000 matrix for inputs and a 5 x 30000 matrix for outputs, it gives me an index was out of bounds exception. This is very strange as alll I did was change the matrix size. I tried changing the numbers for hidden layers but to no resolve. Anyone have any ideas what I am doing wrong?
double[][] inputs;
int[] classes;
var outputsList = Outputs(out inputs, out classes);
GetPerformanceOfStock(outputsList, inputs, classes);
//reclassify as 0 -4
for (var i = 0; i < classes.Length; i++)
{
classes[i] = classes[i] - 1;
}
//mean subtract
for (var i = 0; i < inputs.Length; i++)
{
var avg = inputs[i].Average();
for (var j = 0; j < inputs[i].Length; j++)
{
inputs[i][j] = inputs[i][j] - avg;
}
}
var outputs = Tools.Expand(classes, -1, 1);
//SPLIT INTO TEST AND TRAINIG DATA
var trainingIndex = (int) Math.Floor(.1*inputs.Length);
var fullsize = inputs.Length;
var trainingInputs = new double[trainingIndex][];
var trainingOutputs = new double[trainingIndex][];
for (var i = 0; i < trainingIndex; i++)
{
trainingInputs[i] = inputs[i];
trainingOutputs[i] = outputs[i];
}
var testingInputs = new double[fullsize - trainingIndex][];
var testingOutputs = new double[fullsize - trainingIndex][];
var counter = 0;
for (var i = fullsize - 1; i >= trainingIndex; i--)
{
testingInputs[counter] = inputs[i];
testingOutputs[counter] = outputs[i];
counter++;
}
//Inmitialize network
var network = new DeepBeliefNetwork(inputs.Length, 400, 3, 2);
//var network = new DeepBeliefNetwork(new BernoulliFunction(), trainingInputs.Length, 50, 25, 10);
var teacher = new DeepNeuralNetworkLearning(network)
{
Algorithm = (ann, i) => new ParallelResilientBackpropagationLearning(ann),
LayerIndex = network.Layers.Length - 1
};
teacher.RunEpoch(inputs, outputs);

Algorithm for finding a group of numbers in a list that equal a target

So here is what I'm trying to do. I have a list of integers:
List<int> myList = new List<int>() {5,7,12,8,7};
And I also got a target:
int target = 20;
What I'm trying to do is find a way to create a new list of integer that when added together equal my target. So if my target is 20, I need a list like this:
{ 12, 8 }
If my target is 26, then I'll have this:
{ 7, 12, 7 }
Each number can only be used one time (7 is used twice because its in the list twice). If there is no solution, it should return an empty list. Anyone have any idea how I can do something like this?
That's a statistical problem. You want to find all possible combinations with a matching sum. I can recommend this project which is also worth reading:
http://www.codeproject.com/Articles/26050/Permutations-Combinations-and-Variations-using-C-G
Then it's easy and efficient:
List<int> myList = new List<int>() { 5, 7, 12, 8, 7 };
var allMatchingCombos = new List<IList<int>>();
for (int lowerIndex = 1; lowerIndex < myList.Count; lowerIndex++)
{
IEnumerable<IList<int>> matchingCombos = new Combinations<int>(myList, lowerIndex, GenerateOption.WithoutRepetition)
.Where(c => c.Sum() == 20);
allMatchingCombos.AddRange(matchingCombos);
}
foreach(var matchingCombo in allMatchingCombos)
Console.WriteLine(string.Join(",", matchingCombo));
Output:
12,8
5,7,8
5,8,7
Using recursion. Note that this solution will favor solutions that can be acquired by using the first items from the list. So for a target of 20, you won’t get 12+8 as the solution but 5+7+8.
List<int> findSum(List<int> numbers, int target, int index = 0)
{
// loop through all numbers starting from the index
for (var i = index; i < numbers.Count; i++)
{
int remainder = target - numbers[i];
// if the current number is too big for the target, skip
if (remainder < 0)
continue;
// if the current number is a solution, return a list with it
else if (remainder == 0)
return new List<int>() { numbers[i] };
else
{
// otherwise try to find a sum for the remainder later in the list
var s = findSum(numbers, remainder, i + 1);
// if no number was returned, we could’t find a solution, so skip
if (s.Count == 0)
continue;
// otherwise we found a solution, so add our current number to it
// and return the result
s.Insert(0, numbers[i]);
return s;
}
}
// if we end up here, we checked all the numbers in the list and
// found no solution
return new List<int>();
}
void Main()
{
List<int> myList = new List<int>() { 5, 7, 12, 8, 7 };
Console.WriteLine(findSum(myList, 12)); // 5, 7
Console.WriteLine(findSum(myList, 20)); // 5, 7, 8
Console.WriteLine(findSum(myList, 31)); // 5, 7, 12, 7
}
You can find all the solutions given below here: https://github.com/Mr-Zoidberg/Find-Possible-Combinations
1. Using recursion
static void Main(string[] args)
{
const int target = 20;
var numbers = new List<int> { 1, 2, 5, 8, 12, 14, 9 };
Console.WriteLine($"Number of Combinations: {SumCounter(numbers, target)}");
Console.ReadKey();
}
private static int SumCounter(IReadOnlyList<int> numbers, int target)
{
var result = 0;
RecursiveCounter(numbers, target, new List<int>(), ref result);
return result;
}
private static void RecursiveCounter(IReadOnlyList<int> numbers, int target, List<int> partial, ref int result)
{
var sum = partial.Sum();
if (sum == target)
{
result++;
Console.WriteLine(string.Join(" + ", partial.ToArray()) + " = " + target);
}
if (sum >= target) return;
for (var i = 0; i < numbers.Count; i++)
{
var remaining = new List<int>();
for (var j = i + 1; j < numbers.Count; j++) remaining.Add(numbers[j]);
var partRec = new List<int>(partial) { numbers[i] };
RecursiveCounter(remaining, target, partRec, ref result);
}
}
2. Get subsets using Linq
static void Main(string[] args)
{
const int target = 20;
var numbers = new int[] { 1, 2, 5, 8, 12, 14, 9 };
var matches = numbers.GetSubsets().Where(s => s.Sum() == target).ToArray();
foreach (var match in matches) Console.WriteLine(match.Select(m => m.ToString()).Aggregate((a, n) => $"{a} + {n}") + $" = {target}");
Console.WriteLine($"Number of Combinations: {matches.Length}");
Console.ReadKey();
}
}
public static class Extension
{
public static IEnumerable<IEnumerable<T>> GetSubsets<T>(this IEnumerable<T> collection)
{
if (!collection.Any()) return Enumerable.Repeat(Enumerable.Empty<T>(), 1);
var element = collection.Take(1);
var ignoreFirstSubsets = GetSubsets(collection.Skip(1));
var subsets = ignoreFirstSubsets.Select(set => element.Concat(set));
return subsets.Concat(ignoreFirstSubsets);
}
3. Another recursive method...
static void Main(string[] args)
{
const int target = 20;
var numbers = new [] { 1, 2, 5, 8, 12, 14, 9 };
var result = GetSubsets(numbers, target, "");
foreach (var subset in result) Console.WriteLine($"{subset} = {target}");
Console.WriteLine($"Number of Combinations: {result.Count()}");
Console.ReadLine();
}
public static IEnumerable<string> GetSubsets(int[] set, int sum, string values)
{
for (var i = 0; i < set.Length; i++)
{
var left = sum - set[i];
var vals = values != "" ? $"{set[i]} + {values}" : $"{set[i]}";
if (left == 0) yield return vals;
else
{
int[] possible = set.Take(i).Where(n => n <= sum).ToArray();
if (possible.Length <= 0) continue;
foreach (string s in GetSubsets(possible, left, vals)) yield return s;
}
}
}
4. Using binary search. Linear time.
static void Main(string[] args)
{
const int target = 20;
var numbers = new [] { 1, 2, 5, 8, 12, 14, 9 };
var subsets = GetSubsets(numbers, target);
foreach (var s in subsets) Console.WriteLine($"{s} = {target}");
Console.WriteLine($"Number of Combinations: {subsets.Count()}");
Console.ReadKey();
}
private static IEnumerable<string> GetSubsets(int[] array, int target)
{
Array.Sort((Array)array);
List<string> result = new List<string>();
for (int i = array.Length-1; i >= 0; i--)
{
var eq = $"{array[i]}";
var sum = array[i];
var toAdd = 0;
while (sum != target)
{
var mid = Array.BinarySearch(array, 0, sum <= target / 2 && sum != array[i] ? array.Length - 1 : i, target - sum);
mid = mid < 0 ? ~mid - 1 : mid;
if (mid == i || mid < 0 || toAdd == array[mid] ) break;
toAdd = array[mid];
sum += array[mid];
eq += $" + {array[mid]}";
if (sum == target) result.Add(eq);
}
}
return result;
}
This implementation of mine in C# will return all combinations(including repetitive use of same number) that equals a given number.
string r;
List<int> l = new List<int>();
void u(int w, int s, int K, int[] A) {
// If a unique combination is found
if (s == K) {
r += "(" + String.Join(" ", l) + ")";
return;
}
// For all other combinations
for (int i=w; i<A.Length; i++){
// Check if the sum exceeds K
int x = A[i];
if (s + x <= K){
l.Add(x);
u(i, s + x, K,A);
l.Remove(x);
}
}
}
string combinationSum(int[] a, int s) {
r = "";
u(0, 0, s, a.Distinct().OrderBy(x=>x).ToArray());
return r.Any() ? r : "Empty";
}
for a: [2, 3, 5, 9] and s = 9
the result will be :
"(2 2 2 3)(2 2 5)(3 3 3)(9)"

Combining two double[] arrays into double[,]

I frequently have two arrays that I need to combine to one matrix (same lenght and type). I was wondering whether there is a linq way that is more elegant than:
var result = new double[dt.Count, 2];
for (int i = 0; i < dt.Count; i++)
{
result[i, 0] = dts[i];
result[i, 1] = dt[i];
}
I tried
var result = dts.zip(dt, (a,b) => new{a,b})
and:
var result = dts.Concat(dt).ToArray()
But neither do what I would like to do...
There is nothing in the framework, but here is a general solution (that works for 2 or more arrays):
public static class ArrayConvert
{
public static T[,] To2DArray<T>(params T[][] arrays)
{
if (arrays == null) throw new ArgumentNullException("arrays");
foreach (var a in arrays)
{
if (a == null) throw new ArgumentException("can not contain null arrays");
if (a.Length != arrays[0].Length) throw new ArgumentException("input arrays should have the same length");
}
var height = arrays.Length;
var width = arrays[0].Length;
var result = new T[width, height];
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++)
{
result[i, j] = arrays[i][j];
}
return result;
}
}
Which can then be used as follows:
var convertedArray = ArrayConvert.To2DArray(new[]{1,2,3}, new[]{4,5,6}, new[]{7,8,9});
ok then use this
class Program {
static void Main(string[] args) {
double[,] x = { { 1, 2, 3 }, { 4, 5, 6 } };
double[,] y = { { 7, 8, 9 }, { 10, 11, 12 } };
var xy = new StitchMatrix<int>(x, y);
Console.WriteLine("0,0=" + xy[0, 0]); // 1
Console.WriteLine("1,1=" + xy[1, 1]); // 5
Console.WriteLine("1,2=" + xy[1, 2]); // 6
Console.WriteLine("2,2=" + xy[2, 2]); // 9
Console.WriteLine("3,2=" + xy[3, 2]); // 12
}
}
class StitchMatrix<T> {
private T[][,] _matrices;
private double[] _lengths;
public StitchMatrix(params T[][,] matrices) {
// TODO: check they're all same size
_matrices = matrices;
// call uperbound once for speed
_lengths = _matrices.Select(m => m.GetUpperBound(0)).ToArray();
}
public T this[double x, double y] {
get {
// find the right matrix
double iMatrix = 0;
while (_lengths[iMatrix] < x) {
x -= (_lengths[iMatrix] + 1);
iMatrix++;
}
// return value at cell
return _matrices[iMatrix][x, y];
}
}
}
Here is another solution. I "prepare" the input for LINQ processing. Don't sure that this is elegant, but it is LINQ:
// the input
double[] dts = { 1, 2, 3, 4, 5 };
double[] dt = { 10, 20, 30, 40, 50 };
// list of lists, for iterating the input with LINQ
double[][] combined = { dts, dt };
var indexes = Enumerable.Range(0, dt.Length);
var subIndexes = Enumerable.Range(0, 2);
// the output
var result = new double[dt.Length, 2];
var sss = from i in indexes
from j in subIndexes
select result[i, j] = combined[j][i];
// just to activate the LINQ iterator
sss.ToList();
I suggest against doing it directly in LINQ. You can write a generic method to do it for you, something like:
public static T[,] To2DArray<T>(this T[][] arr)
{
if (arr.Length == 0)
{
return new T[,]{};
}
int standardLength = arr[0].Length;
foreach (var x in arr)
{
if (x.Length != standardLength)
{
throw new ArgumentException("Arrays must have all the same length");
}
}
T[,] solution = new T[arr.Length, standardLength];
for (int i = 0; i < arr.Length; i++)
{
for (int j = 0; j < standardLength; j++)
{
solution[i, j] = arr[i][j];
}
}
return solution;
}
I know that wasnt the question but the most elegant answer is to use f#:
let combinearrays (arr1:array<'a>) (arr2:array<'a>) =
let rws = arr1|> Array.length
Array2D.init rws 2 (fun i j -> match j with |0 -> arr1.[i] |1 -> arr2.[i])
From John see here
Here is the solution Convert two 1d Arrays in one 2D Array which I developed for my own use.
(from a1 in array1.Select((n,index)=>new{Index=index,c1=n}).ToList()
join a2 in array2.Select((n,index)=>new {Index=index,c2=n}).ToList() on a1.Index equals a2.Index
select new {c1,c2}
).ToArray()

How to get index of same elements in an array..?

I am trying to find the index of elements of my array using,
int[] arr = { 10, 20, 10 };
for ( int i; i,arr.length; i++)
{
int Tempval = arr[i];
index = Array.IndexOf(arr, Tempval);
console.writeline(index);
}
But its returning the same index for 10 i.e. 0 everytime.
How can I control it..??
Please help.
Regards
Do it like this:
int[] arr = { 10, 20, 10 };
for ( int i=0; i<arr.length; i++)
{
int Tempval = arr[i];
index = Array.IndexOf(arr, Tempval);
console.writeline(index);
}
Using LINQ you can do:
int[] arr = { 10, 20, 10 };
var result =
arr.Select((r, index) => new { Value = r, Index = index })
.GroupBy(item => item.Value)
.Where(grp => grp.Count() > 1)
.Select(r => new { Indexes = r.Select(t => t.Index).ToArray() })
.FirstOrDefault();
For output:
foreach (var value in result.Indexes)
Console.WriteLine(value);
Output would be:
0
2
You are already using loop and i is your index, why find index again?
int[] arr = { 10, 20, 10 };
for ( int i=0; i<arr.length; i++)
{
int Tempval = arr[i];
index = Array.IndexOf(arr, Tempval);
console.writeline(i);
}
If you want all the indexes,
public IEnumerable<int> FindIndexes(int[] array, int value)
{
for (int i = 0; i < array.Length; i++)
{
int Tempval = array[i];
if (Tempval == value)
{
yield return i;
}
}
}
and call FindIndexes(arr, 10);

Categories