How to get array of fixed length from linq? - c#

How can I get array of fixed length from Linq?
I have tried this and it doesn't work:
void Main() {
// To Array doesn't accept int argument
// Enumerable.Range(1, 3).ToArray(10);
Enumerable.Range(1, 3).Take(10);
// Result is [1,2,3], I expect [1,2,3,null,null, ..., null] or [1,2,3,0,0, ..., 0]
}

You can define your own extension method to convert an IEnumerable<T> to a fixed-length T[] like this:
static class EnumerableExtensions
{
public static T[] ToFixedLength<T>(this IEnumerable<T> source, int length)
{
var result = new T[length];
var i = 0;
foreach (var e in source)
{
if (i < length)
{
result[i++] = e;
}
}
return result;
}
}
Usage:
Enumerable.Range(1, 3).ToFixedLength(10)

You can do something like this.
class Test
{
static void Main()
{
int[] data = Enumerable.Range(1, 10).Select(x => x > 3 ? 0 : x).ToArray();
foreach (var x in data)
Console.WriteLine(x);
}
}

Related

Generic as parameter, what am I doing wrong?

I am learning basic sort algorithms from some source in github. Now, I am trying to make a method that can be used for all sorter instance but I am facing error CS1503 which says that I can not convert int[] into T[]. The intellisense recommends me to add new method but I don't want to add it. Here is my code:
class Program
{
static void Main(string[] args)
{
test<int>(new BubbleSorter<int>(), new IntComparer());
}
static void test<T>(ISorter<T> sorter, IComparer<T> intComparer)
{
var (correctArray, testArray) = RandomHelper.GetArrays(10); //Generates random arrays
sorter.Sort(testArray, intComparer); //This line error
Array.Sort(correctArray);
Console.WriteLine(string.Join(",", testArray));
Console.WriteLine(string.Join(",", correctArray));
}
}
public interface ISorter<T>
{
void Sort(T[] array, IComparer<T> comparer);
}
class BubbleSorter<T> : ISorter<T>
{
public void Sort(T[] array, IComparer<T> comparer) {//Sort}
}
internal class IntComparer : IComparer<int>
{
public int Compare(int x, int y)
{
return x.CompareTo(y);
}
}
internal static class RandomHelper
{
public static (int[] testArray, int[] correctArray) GetArrays(int n)
{
int[] testArr = new int[n];
int[] correctArr = new int[n];
Random rnd = new Random();
for (int i = 0; i < n; i++)
{
int t = rnd.Next(1, 1000);
testArr[i] = t;
correctArr[i] = t;
}
return (testArr, correctArr);
}
}
What I want to achieve that I want to do this with one test method:
static void Main(string[] args)
{
test<int>(new BubbleSorter<int>(), new IntComparer());
test<int>(new SelectionSorter<int>(), new IntComparer());
test<int>(new MergeSorter<int>(), new IntComparer());
}
test is supposed to be able to work on any T, right? But RandomHelper.GetArrays can only return int[]! To make your test method able to test any T, you need to write a GetArrays method that can generate test cases for any T as well, not just for int.
So now you have two choices:
Make test non-generic because you only need to sort ints here.
Make GetArrays work on any T.
For option 1, you can just remove all the <T> and replace T with int, like this:
class Program
{
static void Main(string[] args)
{
test(new BubbleSorter(), new IntComparer());
}
static void test(ISorter sorter, IComparer<int> intComparer)
{
var (correctArray, testArray) = RandomHelper.GetArrays(10);
sorter.Sort(testArray, intComparer);
// Array.Sort(correctArray); // you should do this in GetArrays instead! You should also pass intComparer to Array.Sort as well!
Console.WriteLine(string.Join(",", testArray));
Console.WriteLine(string.Join(",", correctArray));
}
}
public interface ISorter
{
void Sort(int[] array, IComparer<int> comparer);
}
class BubbleSorter : ISorter
{
public void Sort(int[] array, IComparer<int> comparer) {//Sort}
}
One way to do option 2 is to add a Func<int, T> parameter to GetArrays telling it how to transform an int to a T. You would also need a IComparer<T> parameter to sort the correct array as I mentioned above,
public static (T[] testArray, T[] correctArray) GetArrays<T>(int n, Func<int, T> transform, IComparer<T> comparer)
{
T[] testArr = new T[n];
T[] correctArr = new T[n];
Random rnd = new Random();
for (int i = 0; i < n; i++)
{
int t = rnd.Next(1, 1000);
testArr[i] = transform(t);
correctArr[i] = transform(t);
}
Array.Sort(correctArray, comparer);
return (testArr, correctArr);
}
And you can call GetArrays like this:
static void test<T>(ISorter<T> sorter, IComparer<T> intComparer)
{
var (correctArray, testArray) = RandomHelper.GetArrays(10, x => x, intComparer);
sorter.Sort(testArray, intComparer);
Console.WriteLine(string.Join(",", testArray));
Console.WriteLine(string.Join(",", correctArray));
}

All combination of a list of tuples

I'm practicing some optimization problems and I'm stuck.
I have a list of tuples and I am doing the following:
private static int CalculateMinimumTotalCost(List<Tuple<int, int>> tuples)
{
int minimumCost = 0;
for(int i=0;i<tuples.Count()-1;i++)
{
minimumCost += Math.Max(Math.Abs(tuples[i].Item1 - tuples[i + 1].Item1), Math.Abs(tuples[i].Item2 - tuples[i + 1].Item2));
}
return minimumCost;
}
The idea is that given a list of tuples and this mathematical equation, I need to find the minimum cost. The catch is that the order of the tuples can be rearranged. My job is to find the LEAST costly arrangement of tuples.
So what I would like to do is loop through all possible combination of Tuples and return the combination with the minimum cost.
For example:
(1,2)(1,1)(1,3) = 3
(1,1)(1,2)(1,3) = 2
So in this case, i would return 2 because that arrangement is less costly.
I understand that when there are N tuples, the number of combinations is N!.
How do I get all the combinations possible for a list of tuples?
Thanks!
As other have suggested you should create the Point class:
public partial class Point
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
}
And, let's encapsulate the functions for computing distance and total cost :
public partial class Point
{
public static int CalculateDistance(Point p0, Point p1)
{
return Math.Max(
Math.Abs(p0.X - p1.X),
Math.Abs(p0.Y - p1.Y)
);
}
}
public static class PointExtensions
{
public static int GetTotalCost(this IEnumerable<Point> source)
{
return source
.Zip(source.Skip(1), Point.CalculateDistance)
.Sum();
}
}
Finally, you will need another extension method to create "all possible combination" :
public static class PermutationExtensions
{
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(this IEnumerable<T> source)
{
if (source == null || !source.Any())
throw new ArgumentNullException("source");
var array = source.ToArray();
return Permute(array, 0, array.Length - 1);
}
private static IEnumerable<IEnumerable<T>> Permute<T>(T[] array, int i, int n)
{
if (i == n)
yield return array.ToArray();
else
{
for (int j = i; j <= n; j++)
{
array.Swap(i, j);
foreach (var permutation in Permute(array, i + 1, n))
yield return permutation.ToArray();
array.Swap(i, j); //backtrack
}
}
}
private static void Swap<T>(this T[] array, int i, int j)
{
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
Source from Listing all permutations of a string/integer adapted to be more LINQ-friendly
Usage :
void Main()
{
var list = new List<Point>
{
new Point(1, 2),
new Point(1, 1),
new Point(1, 3),
};
// result: Point[] (3 items) : (1, 1), (1, 2), (1,3)
list.GetPermutations()
.OrderBy(x => x.GetTotalCost())
.First();
}
EDIT : As #EricLippert pointed out, source.OrderBy(selector).First() has some extra cost. This following extension method deals with this issue :
public static class EnumerableExtensions
{
public static T MinBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector, IComparer<TKey> comparer = null)
{
IEnumerator<T> etor = null;
if (source == null || !(etor = source.GetEnumerator()).MoveNext())
throw new ArgumentNullException("source");
if (keySelector == null)
throw new ArgumentNullException("keySelector");
var min = etor.Current;
var minKey = keySelector(min);
comparer = comparer ?? Comparer<TKey>.Default;
while (etor.MoveNext())
{
var key = keySelector(etor.Current);
if (comparer.Compare(key, minKey) < 0)
{
min = etor.Current;
minKey = key;
}
}
return min;
}
}
And, we can rewrite the above solution as :
list.GetPermutations().MinBy(x => x.GetTotalCost())
You can change the for loop to Foreach to make it more readable and rather than using index to fetch values.
private static int CalculateMinimumTotalCost(List<Tuple<int, int>> tuples)
{
int minimumCost = 0;
Tuple<int, int> currentTuple = tuples.First();
foreach (Tuple<int, int> tuple in tuples)
{
minimumCost += Math.Max(Math.Abs(currentTuple.Item1 - tuple.Item1), Math.Abs(currentTuple.Item2 - tuple.Item2));
currentTuple = tuple;
}
return minimumCost;
}

C#: making a class usable in foreach

I'm having a little problem with this thing:
I have to make a PrimeCollection class in C# that implements IEnumerable interface and generates prime numbers collection on the fly.
So if I write as a test something like this:
static void Main(string[] args) {
PrimeCollection pc = new PrimeCollection();
foreach (int p in pc)
Console.WriteLine(p);
}
It should generate primes until it reaches int32 limit.
So far I have this:
class PrimeCollection {
public IEnumerable<int> Primes() {
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0));
}
}
However to do the generating i need to call out it like this:
static void Main(string[] args) {
PrimeCollection pc = new PrimeCollection();
foreach (int p in pc.Primes())
Console.WriteLine(p);
}
I assume I need to make the class IEnumerable, not the method, however I have no idea how to generate the numbers on the fly.
If you want to specifically create your custom primes-enumerable, you can define it as a wrapper over your existing linq query. Like this:
public class PrimesEnumerable : IEnumerable<int> {
public PrimesEnumerable() {
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
_internalEnumerable = ints.Where(x => !ints.TakeWhile(y => y*y<=x).Any(y => x % y == 0));
}
public readonly IEnumerable<int> _internalEnumerable;
public IEnumerator<int> GetEnumerator() {
return _internalEnumerable.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _internalEnumerable.GetEnumerator();
}
}
Now you can foreach over it:
var primes = new PrimesEnumerable();
int i = 0;
foreach (var prime in primes) {
if (i == 10)
break;
Console.WriteLine(prime);
i++;
}
Console.ReadLine();
Note: do fix the bug that #CarstenKönig is talking about.
There is no reason to have an instantiable class at all. You are not holding a state.
public static class Prime
{
public static IEnumerable<int> Values()
{
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0));
}
}
Then you can use it like this:
static void Main(string[] args)
{
foreach (int p in Prime.Values())
Console.WriteLine(p);
}
You mean something like this?
class Program
{
static void Main(string[] args)
{
foreach(var prime in new PrimeCollection())
{
Console.WriteLine(prime);
}
Console.Read();
}
}
class PrimeCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
var ints = Enumerable.Range(2, Int32.MaxValue - 1);
return ints.Where(x => !ints.TakeWhile(y => y < Math.Sqrt(x)).Any(y => x % y == 0)).GetEnumerator();
}
}

Combination Creator?

I would like to send to a method a list of numbers, and to get in return all the possible combinations of numbers I gen generate from this list by putting the digits next to each other.
For example, for the numbers {1, 2, 3} I would to give in return:
{1, 2, 3, 12, 13, 21, 23, 31, 32, 123, 132, 213, 231, 312, 321}
This code for example (which I haven't finished) only "Knows" to deal with lists that contain 3 numbers in them.
private static void M1()
{
var intList = new List<int>() { 1, 2, 3 };
var resultList = AllPossibleCombinations(intList);
}
private static object AllPossibleCombinations(List<int> List)
{
var result = new List<int>();
result.Add(List[0]);
result.Add(List[1]);
result.Add(List[2]);
result.Add(List[0] * 10 + List[1]);
result.Add(List[1] * 10 + List[2]);
result.Add(List[0] * 10 + List[2]);
result.Add(List[1] * 10 + List[0]);
result.Add(List[2] * 10 + List[1]);
result.Add(List[2] * 10 + List[0]);
return result;
}
How can I write something more generic? How can I get a list with different number of elements and give in return all the possible combinations?
This isn't necessarily the most efficient, but here's how you could do this using non-recursive methods returning IEnumerable<T>. Something like this will probably require the least possible memory, since it doesn't require building all the permutations in memory. Instead, it just allows you to iterate over the permutations one by one.
private static void Main()
{
var input1 = new[] {"1", "2", "3"};
foreach (var output in EnumeratePermutations(input1))
Debug.WriteLine(String.Join(",", output));
}
private static IEnumerable<T[]> EnumeratePermutations<T>(T[] input)
{
return from partCount in Enumerable.Range(1, input.Length)
let inputs = Enumerable.Repeat(input, partCount).ToArray()
from indices in EnumerateCrossjoinIndices(inputs)
where indices.Distinct().Count() == indices.Length
select indices.Select(n => input[n]).ToArray();
}
private static IEnumerable<int[]> EnumerateCrossjoinIndices(params Array[] arrays)
{
var arrayCount = arrays.Length;
if (arrayCount == 0)
yield break;
if (arrays.Any(a => a.Length == 0))
yield break;
var indexer = new int[arrayCount];
yield return (int[]) indexer.Clone();
for (var dimension = arrayCount - 1; dimension >= 0; --dimension)
{
++indexer[dimension];
if (indexer[dimension] == arrays[dimension].Length)
indexer[dimension] = 0;
else
{
yield return (int[]) indexer.Clone();
dimension = arrayCount;
}
}
}
EnumerateCrossjoinIndices takes n arrays of potentially different lengths and yields an enumeration of the indices that would be used in a crossjoin operation. For example, given {"1","2"} and {"A","B","C"}, it would yield 6 arrays {0,0}, {0,1}, {0,2}, {1,0}, {1,1}, {1,2}. Note that the arrays yielded by this method contain indices into the input arrays, not the elements at those indices.
EnumeratePermutations takes an array and yields the permutations of the items of that array. It does this by enumerating over the indices that would be used to crossjoin the array against itself x times (where x = 1 to n, where n is the number of items in the array). It then filters out any set of crossjoin indices where the set isn't a distinct set.
Try this sample code:
private static List<int> AllPossibleCombinations(IList<int> alphabet)
{
List<int[]> combinations = new List<int[]>();
MakeCombination(combinations, alphabet.Count, new int[0]); // Start recursion
combinations.RemoveAt(0); // Remove empty combination
return combinations.ConvertAll(c => c.Aggregate(0, (sum, index) => sum * 10 + alphabet[index]));
}
private static void MakeCombination(List<int[]> output, int length, int[] usedIndices)
{
output.Add(usedIndices);
for (int i = 0; i < length; i++)
if (Array.IndexOf(usedIndices, i) == -1) // If the index wasn't used earlier
{
// Add element to the array of indices by creating a new one:
int[] indices = new int[usedIndices.Length + 1];
usedIndices.CopyTo(indices, 0);
indices[usedIndices.Length] = i;
if (length + 1 != indices.Length)
MakeCombination(output, length, indices); // Recursion
}
}
It uses recursion to generate desired combinations.
Usage:
var t = AllPossibleCombinations(new[] { 1, 2, 3 });
Solution 1
The more generic and type independent way is to create tree-based algorithm which returns collection of combinations of input objects.
Code:
public static class IEnumerableExtensions
{
private class Node<T>
{
public Node()
{
Children = new List<Node<T>>();
}
public T Value
{
get;
set;
}
public bool IsRoot
{
get;
set;
}
public List<Node<T>> Children
{
get;
private set;
}
public Node<T> Parent
{
get;
set;
}
public List<Node<T>> Path
{
get
{
List<Node<T>> Result = new List<Node<T>>();
Result.Add(this);
if (this.Parent.IsRoot == false)
{
Result.AddRange(this.Parent.Path);
}
return Result;
}
}
}
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> enumerable)
{
List<Node<T>> AllNodes = new List<Node<T>>();
// Create tree.
Node<T> Root = new Node<T>() { IsRoot = true };
Queue<Node<T>> Queue = new Queue<Node<T>>();
Queue.Enqueue(Root);
int CurrentLevel = 0;
int LevelsToCreate = enumerable.Count();
while (Queue.Count > 0)
{
var CurrentLevelNodes = Queue.ToList();
Queue.Clear();
foreach (var LoopNode in CurrentLevelNodes)
{
if (LoopNode.Children.Count == 0)
{
foreach (var LoopValue in enumerable)
{
var NewNode = new Node<T>() { Value = LoopValue, Parent = LoopNode };
AllNodes.Add(NewNode);
LoopNode.Children.Add(NewNode);
Queue.Enqueue(NewNode);
}
}
}
CurrentLevel++;
if (CurrentLevel >= LevelsToCreate)
{
break;
}
}
// Return list of all paths (which are combinations).
List<List<T>> Result = new List<List<T>>();
foreach (var LoopNode in AllNodes)
{
if (!LoopNode.IsRoot)
{
List<T> Combination = LoopNode.Path.Select(Item => Item.Value).ToList();
Result.Add(Combination);
}
}
return Result;
}
}
Example with numbers:
class Program
{
static void Main(string[] args)
{
List<int> Input = new List<int>() { 1, 2, 3 };
var Combinations = Input.Combinations();
}
}
Example with strings:
static void Main(string[] args)
{
var Input = new List<string>() { "a", "b" };
var Combinations = Input.Combinations();
foreach (var LoopCombination in Combinations)
{
string Combination = string.Join(String.Empty, LoopCombination);
Console.WriteLine(Combination);
}
Console.ReadKey();
}
Solution 2
The second idea is to not to use tree-based algorithm and create combinations step-by-step - it may be faster.
Code:
public class Combinator<T>
{
private readonly Dictionary<int, T> _Pattern;
private readonly int _Min = 0;
private readonly int _Max;
private List<int> _CurrentCombination;
public Combinator(IEnumerable<T> pattern)
{
_Pattern = new Dictionary<int, T>();
for (int i = 0; i < pattern.Count(); i++)
{
_Pattern.Add(i, pattern.ElementAt(i));
}
_CurrentCombination = new List<int>();
_Max = pattern.Count() - 1;
}
public bool HasFinised
{
get;
private set;
}
public IEnumerable<T> Next()
{
// Initialize or increase.
if (_CurrentCombination.Count == 0)
{
_CurrentCombination.Add(_Min);
}
else
{
MyIncrease(_CurrentCombination.Count - 1);
}
if (_CurrentCombination.Count - 1 == _Max && _CurrentCombination.All(Key => Key == _Max))
{
HasFinised = true;
}
return _CurrentCombination.Select(Key => _Pattern[Key]).ToList();;
}
private void MyIncrease(int index)
{
if (index >= 0)
{
_CurrentCombination[index] = _CurrentCombination[index] + 1;
if (_CurrentCombination[index] > _Max)
{
_CurrentCombination[index] = _Min;
if (index - 1 < 0)
{
_CurrentCombination.Insert(0, -1);
index++;
}
MyIncrease(index - 1);
}
}
}
}
Example:
class Program
{
static void Main(string[] args)
{
var Pattern = new List<string>() { "a", "b", "c" };
Combinator<string> Combinator = new Combinator<string>(Pattern);
while (Combinator.HasFinised == false)
{
var Combined = Combinator.Next();
var Joined = string.Join("-", Combined);
Console.WriteLine(Joined);
}
Console.ReadKey();
}
}
If you want to combine items with others only:
static void Main(string[] args)
{
Combinator<int> Combinator = new Combinator<int>(new List<int>() { 1, 2, 3 });
while (Combinator.HasFinised == false)
{
var NextCombination = Combinator.Next();
var DistinctCheck = NextCombination.ToList().Distinct();
if (DistinctCheck.Count() == NextCombination.Count())
{
Console.WriteLine(string.Join(String.Empty, NextCombination.Select(Item => Item.ToString())));
}
}
Console.ReadKey();
}

Refactor LINQ ForEach to return IEnumerable<T>

I am creating an array with the following CreateArray static method:
public static int[] CreateArray(int size)
{
var ret = new int[size];
ret[0] = 0;
ret[1] = 1;
Parallel.ForEach(Enumerable.Range(2, size - 2), i =>
{
ret[i] = Func(i).Count();
});
return ret;
}
Where Func looks like:
public static IEnumerable<int> Func(int i)
{
...
}
Is it possible to refactor the CreateArray method in something like:
public static int[] CreateArray(int size)
{
var tableFromIndex2 = ...
return new[] { 0, 1 }
.Concat(tableFromIndex2)
.ToArray();
}
I think PLINQ could be useful here:
var tableFromIndex = ParallelEnumerable.Range(2, size - 2)
.AsOrdered()
.Select(i => Func(i).Count());
return new[] { 0, 1 }
.Concat(tableFromIndex)
.ToArray();

Categories