Separating values in list when it decrease and increase - c#

This is what I would like to do.
I have huge number of number in a list, but it has a sequence of either increasing or decreasing.
Such as,
100
200
300
400
500
600
500
400
300
200
100
500
700
800
900
Lets say this values are stored in a list or maybe an array. How could I separate these to multiple arrays or list consisting of the sequence.
Such as, List 1: 100 200 300 400 500 600
List 2 :500 400 300 200 100
List 3:500 700 800 900
This is what I have done. I am stuck.
for (int i = 0; i < p.Count - 1; i++)
{
double v = p.ElementAt(i);
if (initialP > v)
{
if (low == 1)
{
sep.Add(sep_index);
low = 0;
}
else
{
}
high = 1;
}
if (initialP < v)
{
if (high == 1)
{
sep.Add(sep_index);
high = 0;
}
low = 1;
}
initialP = v;
sep_index++;
if (i == p.Count - 2)
{
sep.Add(sep_index);
}
}

As suggested in the comments, you should use a list of of lists and while looping use a new list when there is a switch in the direction of the sort:
EDIT: Fixed to take into account equal numbers and strict comparaisons.
public static List<List<int>> GetLists(int[] nums, bool strict) {
List<List<int>> lists = new List<List<int>>();
List<int> list = new List<int>();
lists.Add(list);
list.AddRange(nums.Take(1));
if (nums.Length <= 1) {
return lists;
}
if (strict && nums[0] == nums[1]) {
list = new List<int>();
lists.Add(list);
list.Add(nums[1]);
}
else
list.Add(nums[1]);
if (nums.Length == 2)
{
return lists;
}
int direction = Math.Sign(nums[2] - nums[1]);
for (int i = 2; i < nums.Length; i++) {
int d = Math.Sign(nums[i] - nums[i - 1]);
if ((d == direction && (d != 0 || !strict))
|| (d != 0 && strict)
|| (Math.Abs(d + direction) == 1 && !strict))
{
list.Add(nums[i]);
if (d != 0 && direction == 0) direction = d;
}
else
{
direction = d;
list = new List<int>();
list.Add(nums[i]);
lists.Add(list);
}
}
return lists;
}
static void Main(string[] args)
{
int[] nums = new int[] { 2, 2, 2, 1, 1, 3, 3, 4, 4 };
var lists = GetLists(nums, false);
foreach (var list in lists) {
foreach (var item in list)
{
Console.Write(item + " ");
}
Console.WriteLine();
}
/*
* Prints:
* 2 2 2 1 1
* 3 3 4 4
* */
}

Derivation, or spin. If it is positive -- one direction. Otherwise -- another.
Use spin, which will show you direction (up or down): (n+1/n). When spin changes, then store elements in a list.

Possible solution:
public static IList<IList<int>> UpDownSeparator(IEnumerable<int> value) {
if (Object.ReferenceEquals(null, value))
throw new ArgumentNullException("value");
List<IList<int>> result = new List<IList<int>>();
List<int> current = new List<int>();
result.Add(current);
// +1 - asceding, -1 - descending, 0 - to be determined later
int direction = 0;
foreach(int item in value) {
if (direction == 0) {
if (current.Count > 0) {
if (item > current[current.Count - 1])
direction = 1;
else if (item < current[current.Count - 1])
direction = -1;
}
current.Add(item);
}
else if (direction < 0) {
if (item > current[current.Count - 1]) {
direction = 1;
current = new List<int>() { item };
result.Add(current);
}
else
current.Add(item);
}
else {
if (item < current[current.Count - 1]) {
direction = -1;
current = new List<int>() { item };
result.Add(current);
}
else
current.Add(item);
}
}
return result;
}
....
List<int> list = new List<int>() { 100, 200, 300, 400, 500, 600, 500, 400, 300, 200, 100, 500, 700, 800, 900};
// [[100, 200, 300, 400, 500, 600], [500, 400, 300, 200, 100], [500, 700, 800, 900]]
IList<IList<int>> result = UpDownSeparator(list);

I would do something like this:
private static List<int[]> SplitOnDirection(int[] input)
{
List<int[]> output = new List<int[]>();
List<int> currentList = new List<int>();
bool? isRaising = null;
int? previousNumber = null;
foreach (int number in input)
{
// do we have a previous value?
if (previousNumber.HasValue)
{
// only if the number is different, then we have to check the direction.
if (number != previousNumber.Value)
{
bool isHigherNumber = (number > previousNumber.Value);
// do we already know if we start with raise/lowering
if (isRaising.HasValue)
{
// if we have a higher number and we're not raising, change direction.
if (isHigherNumber != isRaising.Value)
{
// We changed direction..
output.Add(currentList.ToArray());
currentList = new List<int>();
}
}
isRaising = isHigherNumber;
}
}
previousNumber = number;
currentList.Add(number);
}
// if we didn't changed direction, we should 'flush' these.
if (currentList.Count > 0)
output.Add(currentList.ToArray());
return output;
}
int[] input = new int[] { 100, 200, 300, 400, 500, 600, 500, 400, 300, 200, 100, 500, 700, 800, 900 };
List<int[]> output = SplitOnDirection(input);

Took around 20 min, but I would do something like this below. Using Java, I am sure could easily be written using other language syntax.
Input
1, 1, 1, -1, 2, 3, 4, 4, 4, 5, 6, 5, 4, 4, 3, 3, 6, 6, 2, 1, 5, 7, 8, 9
Output
1 1 1 -1
2 3 4 4 4 5 6
5 4 4 3 3
6 6
2 1
5 7 8 9
Code
public static void main(String[] args) {
int[] input = new int[]{1, 1, 1, -1, 2, 3, 4, 4, 4, 5, 6, 5, 4, 4, 3, 3, 6, 6, 2, 1, 5, 7, 8, 9};
List<List<Integer>> lists = split(input);
for (List<Integer> list : lists) {
for (Integer integer : list) {
System.out.print(integer+" ");
}
System.out.println("");
}
}
public static List<List<Integer>> split(int[] input) {
List<List<Integer>> listOfList = new ArrayList<List<Integer>>();
if(input.length >= 1) {
List<Integer> list = newList(listOfList, input[0]);
Order lastO = null;
int last = input[0];
for (int i = 1; i < input.length; i++) {
Order currentO = Order.getOrder(input[i], last);
boolean samePattern = Order.sameDirection(currentO, lastO);
if(lastO == null || samePattern) {
list.add(input[i]);
} else {
list = newList(listOfList, input[i]);
lastO = null;
}
if(currentO != Order.Equal){
lastO = currentO;
}
last = input[i];
}
}
return listOfList;
}
private static List<Integer> newList(List<List<Integer>> listOfList, int element) {
List<Integer> list = new ArrayList<Integer>();
listOfList.add(list);
list.add(element);
return list;
}
private static enum Order {
Less, High, Equal;
public static Order getOrder(int first, int second) {
return first > second ? High : first < second ? Less : Equal;
}
public static boolean sameDirection(Order current, Order last) {
if(last == Order.Less && (current == Order.Less || current == Order.Equal)) {
return true;
} else if(last == Order.High && (current == Order.High || current == Order.Equal)) {
return true;
}
return false;
}
}

Related

how to get the array containing minimum difference array elements

[Image of the actual problem]
we have to choose the best item/items based on input3 which is items to be selected. the choice should be such that we don't take maximum item always. Instead we take items which are not having much difference.
input1: total items
input2: array of items
input3: items to be selected
Scenario 1:
input: 6, {44,55,605,100,154,190}, 1
output should be: {605}
input: 5, {15,85,32,31,2}, 2
output should be: {32,31}
as we increase the number of items to be selected, output should have more item in selected with minimum difference.
Below is the code i am trying, i am new to this please help:
i am stuck how to make this dynamic.
public static int[] Find(int totalItems, int[] values, int totalToBeSelected)
{
var i = values;
int[] results = new int[totalToBeSelected];
var resultList = new List<int>();
if (totalToBeSelected == 1)
{
resultList.Add(values.Max());
return resultList.ToArray();
}
Array.Sort(i);
var minmumDiff = (i[0] - i[1]) * -1;
for (int k = 1; k < i.Length; k++)
{
var differnce = i[k] - i[k - 1];
if (differnce < minmumDiff)
{
resultList.Add(i[k]);
resultList.Add(i[k - 1]);
minmumDiff = differnce;
}
}
return resultList.ToArray();
}
You can look at this function.
public static int[] Find(int totalItems, int[] values, int totalToBeSelected)
{
Array.Sort(values);
Array.Reverse(values); // We need any value greater than max items diff. Max array item (first item after the sort) enough for it.
int diff = values[0];
int indx = 0;
for (int i = 0; i < totalItems - totalToBeSelected +1; i++)
{
int temp_diff = values[i] - values[i + totalToBeSelected - 1]; // We are looking for any items group that max and min value difference is minimum
if (temp_diff < diff )
{
diff = temp_diff;
indx = i;
}
}
int[] results = new int[totalToBeSelected];
Array.Copy(values, indx, results, 0, totalToBeSelected);
return results;
}
Sample:
Find( 6, new int[] { 44, 55, 605, 100, 154, 190 }, 1 );
Out: { 605 }
Find( 5, new int[] { 15, 85, 32, 31, 2 }, 2 );
Out: { 32, 31 }
The conditions in the question are unclear, some assumptions had to be made.
class Program
{
static void Main(string[] args)
{
var items = new[] {12,14,22,24,6};//new[] { 15, 85, 32, 31, 2};//new[] { 44, 55, 605, 100, 154, 190 };
var totalItems = items.Count();
var numberOfItemsToSelect = 3;
var result = Find(totalItems, items, numberOfItemsToSelect);
PrintList(result);
Console.ReadLine();
}
static void PrintList(IEnumerable<int> scoreList)
{
foreach (var score in scoreList)
{
Console.Write(score);
Console.Write(" ");
}
}
public static int[] Find(int totalItems, int[]values, int totalTobeSelected)
{
var result = new List<int>();
if (totalTobeSelected <= 1)
{
result.Add(values.Max());
}
else if (totalTobeSelected == totalItems)
{
result.AddRange(values.OrderBy(i => i).ToList());
}
else
{
var mainSet = values.OrderBy(i => i).ToList();
var setDic = new Dictionary<int, IEnumerable<int>>();
for (int i = 0; (totalItems - i >= totalTobeSelected); i++)
{
var set = mainSet.GetRange(i, totalTobeSelected);
//Inside a set, we choose the difference between the first and the second number
// ex: set = {2, 4, 9} => diff = |2-4| = 2.
var diff = Math.Abs(set[0] - set[1]);
// given two sets with the same diff, we select the first one base on the sort order of the main set:
// ex: main set = {2,4,8,10}. Both {2,4} and {6,8} have a diff of 2 so we select {2,4}
if (setDic.ContainsKey(diff)) continue;
setDic.Add(diff, set);
}
if (setDic.Count > 0)
{
var minKey = setDic.Keys.Min();
result.AddRange(setDic[minKey]);
}
}
return result.ToArray();
}
}

Sum of Numbers as Distinct Primes

//List Style
using System;
using System.Collections.Generic;
using System.Linq;
public class pr{
static public void Main (){
int n, i, j, k, l, sum,flag = 0;
//int sum = i+j;
//int k = (n-i);
//int l = (n-j);
//System.Console.WriteLine ("Enter a number");
//n = Convert.ToInt32 (Console.ReadLine());
//List <int> primes = new List <int>(); //list to handle the numbers
//HashSet <int> myPrimes = new HashSet <int> (primes);
System.Console.WriteLine ("Enter a number");
n = Convert.ToInt32 (Console.ReadLine());
//myPrimes.Add(n);
//myPrimes.Add(i);
//myPrimes.Add(j);
// var count = string.Join(", ", primes);
//System.Console.WriteLine("The value of n is {0}",myPrimes);
for(i=3; i<n/2; i++){
for(j=3; j<n/2; j++){
if(checkPrime(i) == 1){
if(checkPrime(j) == 1){
if (checkPrime(n-i) == 1){
if (checkPrime(n-j) == 1){
//if(i == j){
//sum = i+j;
System.Console.WriteLine("{0}={1}+{2}\n",n,i,n-i);
//}
}
}
}
}
if (flag == 0 && (n-i) <= 0 && (n-j) <= 0){ //check to avoid dupes
if (n <= 0 && i <= 0 && j <= 0){
Console.Write("{0}\n",n);
}
}
}
}
}
public static int checkPrime(int n){
int i, j, flag = 1;
for (i = 2; i<=(Math.Sqrt(n)); i++){
for (j = 2; j<=(Math.Sqrt(n)); j++){
if (n%i == 0 && n%j == 0 ){ //even number check
i++;
j++;
flag = 0;
}
}
}
return flag;
}
}
So I have been experimenting with this for a while now. I cant seem to print all possible solutions. For example for 24 I am able to print 7+17 but not 2+5+17. There are also some answers being repeated and this might have to do with the fact that I dont have duplicate checks. I tried to push the integers in a list and then use a hashset to only have distinct integers but I got stuck and tried to brute force it. All the numbers to be printed are supposed to be distinct prime integers. I dont understand how to print all distinct numbers and is there an elegant way to print out all the possible.
Thanks for the help!
Don't know if it's elegant enough for you, but I've just mashed a dirty way to make it work:
static void Main()
{
Console.WriteLine("Enter a number");
var numberToSum = Convert.ToInt32(Console.ReadLine());
var primesInRange = GetPrimesUpTo(numberToSum);
var foundSolutions = primesInRange.SubSetsOf().Where(prime => prime.Sum() == numberToSum);
foreach (var solution in foundSolutions.ToList())
{
var formatOperation = solution
.Select(x => x.ToString())
.Aggregate((a, n) => a + " + " + n) + " = " + numberToSum;
Console.WriteLine(formatOperation);
}
Console.ReadLine();
}
public static IEnumerable<int> GetPrimesUpTo(int end)
{
var primes = new HashSet<int>();
for (var i = 2; i <= end; i++)
{
var ok = true;
foreach (var prime in primes)
{
if (prime * prime > i)
break;
if (i % prime == 0)
{
ok = false;
break;
}
}
if (ok)
primes.Add(i);
}
return primes;
}
public static IEnumerable<IEnumerable<T>> SubSetsOf<T>(this IEnumerable<T> source)
{
if (!source.Any())
return Enumerable.Repeat(Enumerable.Empty<T>(), 1);
var element = source.Take(1);
var haveNots = SubSetsOf(source.Skip(1));
var haves = haveNots.Select(set => element.Concat(set));
return haves.Concat(haveNots);
}
I've found your solution quite dirty so I divided the problem to be more understandable. GetPrimesUpTo returns all prime number from 2 to the number you've provided in the input, SubSetsOf returns combination of numbers that summed up equals the input number you've provided and finally the foreach in Main produces formatted output that is easy on the eye. Hope it helps!
Providing that you have collection of primes and IsPrime method
private static int[] primes = new[] {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
private static bool IsPrime(int value) {
return primes.Contains(value);
}
You can implement recoursive solution
private List<List<int>> ToListOfPrimes(int value, List<int> parts = null) {
if (null == parts)
parts = new List<int>();
List<List<int>> result = new List<List<int>>();
if (value == 0) {
result.Add(parts.ToList());
return result;
}
int minPrime = parts.Count <= 0 ? 0 : parts[parts.Count - 1];
if (value <= minPrime)
return result;
// not that efficient: binary search will be a better choice here
for (int i = 0; i < primes.Length; ++i) {
int p = primes[i];
if (p <= minPrime)
continue;
else if (p > value)
break;
var list = parts.ToList();
list.Add(p);
var outcome = ToListOfPrimes(value - p, list);
foreach (var solution in outcome)
result.Add(solution);
}
return result;
}
Test
var result = ToListOfPrimes(28);
string report = String.Join(Environment.NewLine, result
.Select(line => String.Join(", ", line)));
Console.Write(report);
Outcome (28)
2, 3, 5, 7, 11
2, 3, 23
2, 7, 19
3, 5, 7, 13
5, 23
11, 17
For 24
2, 3, 19
2, 5, 17
5, 19
7, 17
11, 13
If you really want to implement it in other languages just throw your solution to rubbish bin. You should be more explicit about what is happening during execution. Nested for loops with multiple if statements are not explicit at all. What's even worse in the sample - you'll need to add new for loop every time you want more numbers in the sum. I do believe it's hard to understand it for a novice, but I find recursion the only way to go here.
See for yourself:
it's hard to say why output of your program is wrong, because of the logic
Variables should be named meaningfully so you know what they store instead of blind guessing.
Your checkPrime method returns int even though you return 0 or 1 so it should really return bool type
Use debugger and a piece of paper to understand how recursion works either in my previous answer or the one provided by Dmitry Bychenko

Recursion in place of multiple nested for loops?

Im having some issues with trying to update a nested for loop to use recursion instead. Is it possible to access the a,b and c variables from the earlier for loops when using recursion? Below is a simple example of what im trying to convert into a recursive call.
for(int a= 0; a < 10; a++)
{
for(int b = 0; b < 20; b++)
{
for(int c = 0; c < 10; c++)
{
int[] indexes = new int[3]{a,b,c}
collection.add(indexes);
}
}
}
EDIT: The solution needs to be able to be adjusted at runtime, such that a user can select how many levels are required.
Here's a recursive solution (using a functional programming style):
public static IEnumerable<IEnumerable<int>> GetCombinations(IEnumerable<int> limits)
{
if (limits.Any() == false)
{
// Base case.
yield return Enumerable.Empty<int>();
}
else
{
int first = limits.First();
IEnumerable<int> remaining = limits.Skip(1);
IEnumerable<IEnumerable<int>> tails = GetCombinations(remaining);
for (int i = 0; i < first; ++i)
foreach (IEnumerable<int> tail in tails)
yield return Yield(i).Concat(tail);
}
}
// Per http://stackoverflow.com/q/1577822
public static IEnumerable<T> Yield<T>(T item)
{
yield return item;
}
Sample use:
var sequences = GetCombinations(new [] { 5, 3, 2, 4 /* ... */ });
foreach (var sequence in sequences)
Console.WriteLine(string.Join(", ", sequence));
/* Output:
0, 0, 0, 0
0, 0, 0, 1
0, 0, 0, 2
0, 0, 0, 3
0, 0, 1, 0
0, 0, 1, 1
0, 0, 1, 2
0, 0, 1, 3
0, 1, 0, 0
0, 1, 0, 1
0, 1, 0, 2
... */
For OP's specific scenario (adding arrays to collection):
var sequences = GetCombinations(new [] { 10, 20, 10 });
collection.AddRange(sequences.Select(s => s.ToArray()));
Ok, try with this
static void AddToCollectionRecursive(
List<int[]> collection,
params int[] counts)
{
AddTo(collection, new List<int>(), counts, counts.Length - 1);
}
static void AddTo(
List<int[]> collection,
IEnumerable<int> value,
IEnumerable<int> counts,
int left)
{
for (var i = 0; i < counts.First(); i++)
{
var list = value.ToList();
list.Add(i);
if (left == 0)
{
collection.Add(list.ToArray());
}
else
{
AddTo(collection, list, counts.Skip(1), left - 1);
}
}
}
Usage is like this AddToCollectionRecursive(collection, 10, 20, 10);.
something like this will work:
public void CreateIndexes(int a, int b, int c, Collection collection)
{
if(c == 10) {b++; c = 0;}
if(b == 20) {a++; b = 0;}
if(a == 10) return;
int[] indexes = new int[3]{a,b,c}
collection.add(indexes);
c++;
CreateIndexes(a, b, c, collection);
}
Off the top of my head, i.e. not tested, something like this might work:
List<int[]> collection = new List<int[]>();
private void AddValues(int a, int b, int c)
{
collection.Add(new[] { a, b, c });
if (c < 10)
{
c++;
AddValues(a, b, c);
}
if (b < 20)
{
b++;
c = 0;
AddValues(a, b, c);
}
if (a < 10)
{
a++;
b = 0;
c = 0;
AddValues(a, b, c);
}
}
Start it by calling:
AddValues(0, 0, 0);
Well, i think that if u resolve this problem using recursion, it will consume more memory and other resources!
But there is my suggestion:
private void FunctionName(int a, int b, int c, List<int[]> list)
{
if (a<10)
{
if (b<20)
{
if (c<10)
{
list.Add(new[] { a, b, c });
c++;
FunctionName(a,b,c,list);
}
else
{
c=0;
b++;
FunctionName(a,b,c,list);
}
}
else
{
b=0;
a++;
FunctionName(a,b,c,list);
}
}
}
You call like this : FunctionName(0,0,0,list).
Hope it works! ^^
This solution takes an Action for the work to be done at the leafs:
void ForEachCombo(int from, int to, int nrLevels, Action<int[]> action)
{
int[] d = new int[nrLevels];
InnerFor(from, to, 0);
void InnerFor(int from, int to, int level)
{
if (level == nrLevels)
action(d);
else
for (d[level] = from; d[level] <= to - nrLevels + level + 1; d[level]++)
InnerFor(d[level] + 1, to, level + 1);
}
}
Use like this:
ForEachCombo(0, 9, 3, (d) =>
{
Console.WriteLine(string.Join(", ", d));
});
// Output
0, 1, 2
0, 1, 3
0, 1, 4
0, 1, 5
...
6, 7, 9
6, 8, 9
7, 8, 9
//
If you want to you can save a level of recursion by writing like this:
void ForEachCombo(int from, int to, int nrLevels, Action<int[]> action)
{
int[] d = new int[nrLevels];
InnerFor(from, to, 0);
void InnerFor(int from, int to, int level)
{
if (level == nrLevels - 1)
for (d[level] = from; d[level] <= to - nrLevels + level + 1; d[level]++)
action(d);
else
for (d[level] = from; d[level] <= to - nrLevels + level + 1; d[level]++)
InnerFor(d[level] + 1, to, level + 1);
}
}

Finding all numbers that sum to a specified target number (integer partition)

First i want to say i'm still learning so my programming skills are not very good, and i'm willing to accept any advice you have.
Second i'm still learning english so i want to say sorry for the inconvenience.
Well my problem is this, i need help improving my algorithm or any information about it, i don't know what words use for searching this.
The algorithm is supposed to find all the combinations of numbers that added is equal to a given number. Example: if i have the number 6 my results are supposed to be: [1,5],[2,4],[2,2,2],[3,3]
i have the following:
public List<List<int>> discompose(int number)
{
List<List<int>> discomposedPairs = new List<List<int>>();
if (number <= 3)
return discomposedPairs;
int[] numsForCombine = new int[number-1];
for(int i = 1; i < number;i++){
numsForCombine[i - 1] = i;
}
int ini = 0;
int end = numsForCombine.Length - 1;
while (ini <= end)
{
List<int> pair = new List<int>();
pair.Add(numsForCombine[ini++]);
pair.Add(numsForCombine[end--]);
discomposedPairs.Add(pair);
}
return discomposedPairs;
}
public List<List<int>> discomposePair(List<int> pair)
{
List<List<int>> parDisc = new List<List<int>>();
for (int i = 0; i < pair.Count; i++) {
if (pair[i] > 3)
{
List<List<int>> disc = discomposeList(discompose(pair[i]));
foreach (List<int> item in disc)
{
if (i > 0)
{
var temp = pair.GetRange(0, i);
temp.AddRange(item);
parDisc.Add(temp);
} else {
item.AddRange(pair.GetRange(i+1, pair.Count-(i+1)));
parDisc.Add(item);
}
}
}
}
return parDisc;
}
public List<List<int>> discomposeList(List<List<int>> list)
{
List<List<int>> mainDiscomposedList = new List<List<int>>();
for (int i = 0; i < list.Count; i++)
{
mainDiscomposedList.Add(list[i]);
List<List<int>> discomposedSubset = discomposePair(list[i]);
foreach(List<int> item in discomposedSubset){
mainDiscomposedList.Add(item);
}
}
return mainDiscomposedList;
}
The first method descompose the number given in pairs that added are equal the number given.
The second and the third method are the ugliest they are recursive and have bucles so they don't have any good performance. Between the two generates a List with numbers as i the problem says but there are a few inconvenients:
1) Don't have good performance
2) Gives a lot of repetitive sequences
here is the output for the number 10
[2,8,]
[2,2,6,]
[2,2,2,4,]
[2,2,2,2,2,]
[2,2,3,3,]
[2,3,5,]
[2,3,2,3,]<-------------repeated
[2,4,4,]
[2,2,2,4,]<-------------repeated
[2,4,2,2,]<-------------repeated
[3,7,]
[3,2,5,]<-------------repeated
[3,2,2,3,]<-------------repeated
[3,3,4,]
[3,3,2,2,]
[4,6,]
[2,2,6,]<-------------repeated
[4,2,4,]<-------------repeated
[4,2,2,2,]<-------------repeated
[4,3,3,]<-------------repeated
[5,5,]
[2,3,5,]<-------------repeated
[5,2,3,]<-------------repeated
Finally i want to improve the performance and have the less possible repeated items being a repeated item [1,1,3], [1,3,1], [3,1,1]
[Here is the full project link]1
Here's one approach that first builds the combinations into a tree structure, then arranges them into lists of ints:
internal class Combination
{
internal int Num;
internal IEnumerable<Combination> Combinations;
}
internal static IEnumerable<Combination> GetCombinationTrees(int num, int max)
{
return Enumerable.Range(1, num)
.Where(n => n <= max)
.Select(n =>
new Combination
{
Num = n,
Combinations = GetCombinationTrees(num - n, n)
});
}
internal static IEnumerable<IEnumerable<int>> BuildCombinations(
IEnumerable<Combination> combinations)
{
if (combinations.Count() == 0)
{
return new[] { new int[0] };
}
else
{
return combinations.SelectMany(c =>
BuildCombinations(c.Combinations)
.Select(l => new[] { c.Num }.Concat(l))
);
}
}
public static IEnumerable<IEnumerable<int>> GetCombinations(int num)
{
var combinationsList = GetCombinationTrees(num, num);
return BuildCombinations(combinationsList);
}
public static void PrintCombinations(int num)
{
var allCombinations = GetCombinations(num);
foreach (var c in allCombinations)
{
Console.WriteLine(string.Join(", ", c));
}
}
When run with the input value 6, this produces:
1, 1, 1, 1, 1, 1
2, 1, 1, 1, 1
2, 2, 1, 1
2, 2, 2
3, 1, 1, 1
3, 2, 1
3, 3
4, 1, 1
4, 2
5, 1
6

How to repeat the array elements with specific sequence according to some number?

If I have this array of integers :
int[] columns_index = { 2, 3, 4};
How can i repeat this sequence according to given number (size)?
For example :
if i give u 4 as a size then the array will be
{2,3,4,2}
if i give u 5 as a size then the array will be
{2,3,4,2,3}
if i give u 6 as a size then the array will be
{2,3,4,2,3,4}
if i give u 7 as a size then the array will be
{2,3,4,2,3,4,2}
And so on ...
Just use the modulo operator to iterate through the columns_index
int input = 7; // change this to user input of whatever it needs to be
int[] numbers = new int[ input ];
for ( int i = 0; i < input; i++ ){
int index = i % ( columns_index.length )
numbers[i] = columns_index[ index ];
}
public static class Extensions
{
public static T[] Multiply<T>(this T[] array, int length)
{
if ( array == null || array.Length == 0 || length <= array.Length )
return array;
var x = length % array.Length;
var y = length / array.Length;
return Enumerable.Range(1,y)
.SelectMany(c=>array)
.Concat(array.Take(x))
.ToArray();
}
}
One can use the Linq Repeat() and Take() functions to get the result.
private readonly static int[] Source = { 2, 3, 4 };
[TestMethod]
public void TestMethod1() {
Assert.IsTrue(new []{ 2, 3, 4, 2}.SequenceEqual(GetSequence(Source,4)));
Assert.IsTrue(new[] { 2, 3, 4, 2, 3 }.SequenceEqual(GetSequence(Source, 5)));
Assert.IsTrue(new[] { 2, 3, 4, 2, 3, 4 }.SequenceEqual(GetSequence(Source, 6)));
Assert.IsTrue(new[] { 2, 3, 4, 2, 3, 4, 2 }.SequenceEqual(GetSequence(Source, 7)));
}
private static int[] GetSequence(IEnumerable<int> src, int count) {
var srcRepeatCount = count / src.Count() + 1;
return Enumerable.Repeat(src, srcRepeatCount).SelectMany(itm => itm).Take(count).ToArray();
}
If you preferred to seperate the part where you use all in columns_index with the rest
int input = 1000001;
int[] columns_index = { 2, 3, 4 };
int[] numbers = new int[input];
// Times we can use everything in columns_index
int times = input/columns_index.Length; // 333333
List<int> numbersList = new List<int>();
for (int i = 0; i < times; i++)
{
numbersList.AddRange(columns_index);
}
// numbersInt.Count is now 999999..
// Times for the rest
int modTimes = input%(columns_index.Length); // 2
for (int j = 0; j < modTimes; j++)
{
numbersList.Add(columns_index[j]);
}
numbers = numbersList.ToArray();

Categories

Resources