NUnit subsequence assertion - c#

NUnit has various ways to test collections against each other with CollectionAssert and Collection Constraints. But I do not see a way to test if one IEnumerable is a subsequence of another, i.e. it is subset with elements in the same order as in the superset.
Am I overlooking something, or do I need to implement this myself?
EDIT: This is the kind of test I have in mind
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 3, 4, 5, 6 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 4, 5 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3, 5 })] // PASS
public void TestSubsequnce(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
AssertSubsequence(subsequence, supersequence, Comparer<int>.Default);
}

It's not the most efficient algorithm with worst case of O(n log(n)), but here's how you can do it
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 3, 4, 5, 6 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 3, 3, 5 })] // PASS
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 2, 4, 5 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3 })] // FAIL
[TestCase(new[] { 1, 3, 5 }, new[] { 1, 5, 3, 5 })] // PASS
public void TestSubsequnce(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
AssertSubsequenceWithGaps(subsequence, supersequence);
}
public static void AssertSubsequenceWithGaps(IEnumerable<int> subsequence, IEnumerable<int> supersequence)
{
// iterating multiple times, cast sequences to List
var listSub = subsequence.ToList();
var listSuper = supersequence.ToList();
int expected = listSub.Count;
int innerPointer = 0;
int actual = 0;
for (int i = 0; i < listSub.Count; i++)
{
for ( /* start from where we left before */; innerPointer < listSuper.Count; innerPointer++)
{
var valueSub = listSub[i];
var valueSuper = listSuper[innerPointer];
if (valueSub == valueSuper)
{
actual++;
break;
}
}
}
Assert.AreEqual(expected, actual);
}

Since there does not seem to be an out-of-the-box solution, here is what I came up with in the mean time.
private static void AssertSubsequence<T>(IEnumerable<T> subsequence, IEnumerable<T> superSequence, IComparer<T> comparer)
{
var superEnumerator = superSequence.GetEnumerator();
foreach (var subElement in subsequence)
{
if (!superEnumerator.MoveNext())
{
Assert.Fail("Expected a subsequence, but there is no match for {0} from the proposed subsequence.", subElement);
}
while (comparer.Compare(subElement, superEnumerator.Current) != 0)
{
if (!superEnumerator.MoveNext())
{
Assert.Fail("Expected a subsequence, but there is no match for {0} from the proposed subsequence", subElement);
}
}
}
}

Related

Unit test runs only once with array as parameter

I have two unit tests as follows:
[DataTestMethod]
[DataRow(1, 1, 2)]
[DataRow(2, 2, 4)]
[DataRow(3, 3, 6)]
public void AddTest1(int x, int y, int expected)
{
Assert.AreEqual(expected, x + y);
}
[DataTestMethod]
[DataRow(new int[] { 1, 2, 3, 4 }, new int[] { 1, 3, 6, 10 })]
[DataRow(new int[] { 1, 1, 1, 1, 1 }, new int[] { 1, 2, 3, 4, 5 })]
[DataRow(new int[] { 3, 1, 2, 10, 1 }, new int[] { 3, 4, 6, 16, 17 })]
public void AddTest2(int[] input, int[] expectedOutput)
{
Assert.AreEqual(input[0], expectedOutput[0]);
}
The first unit test runs 3 times, once for each data row.
The second unit test only runs once for the first DataRow.
How can I run the second UnitTests with the arrays once for each DataRow as well?
Most test frameworks require the test cases to use compile-time constants as parameters.
This works because the parameters are constant at compile time:
[DataTestMethod]
[DataRow(1, 1, 2)]
[DataRow(2, 2, 4)]
[DataRow(3, 3, 6)]
public void AddTest1(int x, int y, int expected)
{
Assert.AreEqual(expected, x + y);
}
This doesn't work because you're not using compile-time constants:
[DataTestMethod]
[DataRow(new int[] { 1, 2, 3, 4 }, new int[] { 1, 3, 6, 10 })]
[DataRow(new int[] { 1, 1, 1, 1, 1 }, new int[] { 1, 2, 3, 4, 5 })]
[DataRow(new int[] { 3, 1, 2, 10, 1 }, new int[] { 3, 4, 6, 16, 17 })]
public void AddTest2(int[] input, int[] expectedOutput)
{
Assert.AreEqual(input[0], expectedOutput[0]);
}
The new keyword with an array doesn't allow the test framework to differentiate (looking at the image you linked, it just says System.Int32[]).
A workaround might be this:
[DataTestMethod]
[DataRow(0, new int[] { 1, 2, 3, 4 }, new int[] { 1, 3, 6, 10 })]
[DataRow(1, new int[] { 1, 1, 1, 1, 1 }, new int[] { 1, 2, 3, 4, 5 })]
[DataRow(2, new int[] { 3, 1, 2, 10, 1 }, new int[] { 3, 4, 6, 16, 17 })]
public void AddTest2(int run, int[] input, int[] expectedOutput)
{
Assert.AreEqual(input[0], expectedOutput[0]);
}
That way, the different test cases can be differentiated by a compile-time constant.

Problem with writing method to shift elements in array by Array.Copy method. My solution is not good enough

Task - Implement the Shift method using for statements, array indices and Array.Copy method for copying array elements. The method has two arguments. The source arguments has the array of integers to shift and return. Do not create a new array. The iterations argument has the array of integers. Each value in the iterations array is a shift instruction that tells the number of shift iterations. The odd elements (an element with odd index) tells the number of right shift iterations. The even elements (an element with even index or zero index) tells the number of left shift iterations. The first and the last elements in the source array should be wrapped to the other side of the array.
I have a problem with copying the elements more than one times.
My solution so far:
public static int[] Shift(int[]? source, int[]? iterations)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (iterations == null)
{
throw new ArgumentNullException(nameof(iterations));
}
if (source == Array.Empty<int>())
{
throw new ArgumentNullException(nameof(source));
}
foreach (var currentIteration in iterations)
{
if (currentIteration == 0)
{
break;
}
else if (currentIteration % 2 == 0)
{
for (int i = 0; i < currentIteration; i++)
{
var temp = source[0];
Array.Copy(source, 0, source, 1, source.Length - 1);
source[source.Length - 1] = temp;
}
}
else
{
for (int i = 0; i < currentIteration; i++)
{
var temp = source[source.Length - 1];
Array.Copy(source, 1, source, 0, source.Length - 1);
source[0] = temp;
}
}
}
return source;
}
There are unit tests, which can be helpful in finding a solution.
[TestCase(new[] { 1 }, new[] { 2, 2 }, ExpectedResult = new[] { 1 })]
[TestCase(new[] { 1 }, new[] { 2, 3 }, ExpectedResult = new[] { 1 })]
[TestCase(new[] { 1 }, new[] { 2, 4 }, ExpectedResult = new[] { 1 })]
[TestCase(new[] { 1, 2 }, new int[] { }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 0 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 1 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 2 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 3 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 4 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 0, 1 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 0, 2 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 0, 3 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 0, 4 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 1, 1 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 1, 2 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 1, 3 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 1, 4 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 2, 1 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 2, 2 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 2, 3 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 2, 4 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 3, 1 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 3, 2 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 3, 3 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 3, 4 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 4, 1 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 4, 2 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2 }, new[] { 4, 3 }, ExpectedResult = new[] { 2, 1 })]
[TestCase(new[] { 1, 2 }, new[] { 4, 4 }, ExpectedResult = new[] { 1, 2 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new int[] { }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 0 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 0, 0 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 0, 0, 0 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1 }, ExpectedResult = new[] { 2, 3, 4, 5, 1 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 0, 1 }, ExpectedResult = new[] { 5, 1, 2, 3, 4 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 1 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 1, 1 }, ExpectedResult = new[] { 2, 3, 4, 5, 1 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 1, 1, 1 }, ExpectedResult = new[] { 1, 2, 3, 4, 5 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 2 }, ExpectedResult = new[] { 5, 1, 2, 3, 4 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 2, 1 }, ExpectedResult = new[] { 2, 3, 4, 5, 1 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 2, 3 }, ExpectedResult = new[] { 3, 4, 5, 1, 2 })]
[TestCase(new[] { 1, 2, 3, 4, 5 }, new[] { 1, 2, 3, 4 }, ExpectedResult = new[] { 4, 5, 1, 2, 3 })]
public int[] Shift_SourceAndIterationsAreNotNull_ReturnsArrayWithShiftedElements(int[] source, int[] iterations)
{
return Shifter.Shift(source, iterations);
}
I would be grateful, if someone can help me, or explain how to find the best code for this.
Based on the discription the direction of movement is indicated via iterations elemente index NOT value as you made in your original code.
you made some logical errors within your original method:
if odd index you should move right(based on description) not left.
if even index you should move left(based on description) not right.
The method below have comments regarding lines you have issues in,
hopefully it would achieve your task.
public static int[] Shift(int[]? source, int[]? iterations)
{
if (source == null || iterations == null || source == Array.Empty<int>())
throw new ArgumentNullException(nameof(source));
// use for loop instead of foreach due to ease access of index of each element
// i => iteration index
for (int i = 0; i < iterations.Length; i++)
{
//----------------------------------------
// you have to check the state(odd or even) of each iteration index and not the iteration value itself.
//----------------------------------------
// if no movments to do contineu to next loop iteration
if (iterations[i] == 0)
continue;
// if even index
if (i % 2 == 0)
{
for (int j = 0; j < iterations[i]; j++)
{
var temp = source[0];
// Array.Copy(source, 0, source, 1, source.Length - 1);
// Note you passed reversed arguments
Array.Copy(source, 1, source, 0, source.Length - 1);
source[source.Length - 1] = temp;
}
}
// if odd index
else
{
for (int j = 0; j < iterations[i]; j++)
{
var temp = source[source.Length - 1];
// Array.Copy(source, 1, source, 0, source.Length - 1);
// Note you passed reversed arguments
Array.Copy(source, 0, source, 1, source.Length - 1);
source[0] = temp;
}
}
}
return source;
}
}

Sort 2D array based on user provided indices

In python there is a functionality (numpy.take) to sort arrays within an array, for example if I have an array (3x3):
a = [[1, 2, 3],[7,9,10],[3, 5,6]]
and I have an array of set indices
indices = [2, 0, 1]
the result shall be
array([[ 3, 5, 6], [ 1, 2, 3], [ 7, 9, 10]]).
Are there any direct approach methods/ functions as these in C# where I can pass in a jagged array and produce the same output?
Not directly, but you can achieve the same thing with Linq
var a = new[] { new[] { 1, 2, 3 }, new[] { 7, 9, 10 }, new[] { 3, 5, 6 } };
var indices = new [] { 2, 0, 1 };
var sorted = indices.Select(i => a[i]).ToArray();
foreach(var s in sorted) Console.WriteLine(string.Join(", ", s));
Note this does not check that your indices are all in range.
You can do it easily with LINQ:
var a = new[] { new[] { 1, 2, 3 }, new[] { 7, 9, 10 }, new[] { 3, 5, 6 } };
var indices = new[] { 2, 0, 1};
var result = indices
.Select(i => a[i])
.ToArray();
Or .ToList() if you prefer lists.
There is also the Array.Sort(keys, values) - MSDN
var a = new[]
{
new[] {1, 2, 3},
new[] {7, 9, 10},
new[] {3, 5, 6}
};
var indices = new[] {2, 0, 1};
var sortedArray = a.SortEx(indices);
Where SortEx is
public static class Extensions
{
public static T[][] SortEx<T>(this T[][] source, int[] indices)
{
return indices.Select(index => source[index]).ToArray();
}
}
This assumes that the all the indices in the indices array are not out of bound in a.

How to declare 2D integer array in C#?

I am at beginner level of programming, and I would like to know how to declare a 2-dimension array in C#. I did look it up on Google but I couldn't find a solution.
Please answer this question at my level.
Thanks
you can do it like this. See details here
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
2D integer array
Declaration
int[,] array = new int[4, 2];
Initialization
int[,] array = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
Complete explanation with example :http://msdn.microsoft.com/en-us/library/2yd9wwz4.aspx
// Two-dimensional array.
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// The same array with dimensions specified.
int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// A similar array with string elements.
string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" },
{ "five", "six" } };
// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
// The same array with dimensions specified.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
i think you have not searched google....
follow below link to see tutorial
http://www.tutorialspoint.com/csharp/csharp_multi_dimensional_arrays.htm
int [,] a = int [3,4] = {
{0, 1, 2, 3} , /* initializers for row indexed by 0 */
{4, 5, 6, 7} , /* initializers for row indexed by 1 */
{8, 9, 10, 11} /* initializers for row indexed by 2 */
};
Use MSDN for Micrsoft technologies, it is well documented http://msdn.microsoft.com/en-us/library/2yd9wwz4.aspx
It ranked #1 in google search for me when writing: 2d integer array c#
This page might also provide useful information: What are the differences between a multidimensional array and an array of arrays in C#?
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
The sum2D() Method
private double sum2D(double[,] ar)
{
double sum = 0.0;
foreach (double d in ar)
sum += d;
return sum;
}

Declare multi dimensional array

I have this array that I need it to be convert from JS to C#:
var allwinning = new Array(
["000", "001", "002"],
["000", "010", "020"],
["000", "011", "022"],
["000", "100", "200"],
["000", "101", "202"],
["000", "110", "220"],
["001", "002", "003"],
["001", "011", "021"])
The array has to be this way because at one point of the game I will have to compare and match element by element to see if you match the combo to decide if you win.
Should I convert it to List<string> or to ArrayList?
// Two-dimensional array.
int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// The same array with dimensions specified.
int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
// A similar array with string elements.
string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" },
{ "five", "six" } };
// Three-dimensional array.
int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };
// The same array with dimensions specified.
int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 10, 11, 12 } } };

Categories