Copy part of 3-d array to 2-d array - c#

Let's say I have a multidimensional array:
var arr = new double[2, 5, 5]
{
{
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 }
},
{
{ 1, 1, 1, 1, 1 },
{ 1, 2, 2, 2, 1 },
{ 1, 2, 2, 2, 1 },
{ 1, 2, 2, 2, 1 },
{ 1, 1, 1, 1, 1 }
},
};
I want to copy 3 by 3 part of that array starting from index [1,1,1] till index [1,3,3] (all 2 values).
What is the most efficient way of doing so ? So far, I do it with a loop:
var arr2 = new int[3, 3];
int x_start = 1;
int y_start = 1;
for (int i = 0; i < arr2.GetLength(0); i++)
{
for (int j = 0; j < arr2.GetLength(1); j++)
{
arr2[i, j] = arr[1, x_start + i, y_start + j];
}
}
But I wonder if there is a more efficient way of doing it ?

poke already made the same point in their comment, but this is essentially the best way of doing this.
That’s the most efficient way to do it. You are using fast loops and only loop over those indexes you are interested in. - poke
You could possibly cache the two GetLength() calls in an integer, but I doubt that'd make any meaningful difference in performance.

Related

Solve non square linear system with Math.net

I'm trying to solve a non square linear system with Math.net.
But I get an error Matrix dimensions must agree: 3x7.
Here is some example code:
using MathNet.Numerics.LinearAlgebra;
var mBuilder = Matrix<double>.Build;
var vBuilder = Vector<double>.Build;
var A = mBuilder.DenseOfArray(new double[,]
{
{ 3, 2, 1, 5, -1, 0, 0 },
{ 2, 1, 1, 2, 0, -1, 0 },
{ 5, 1, 3, 4, 0, 0, -1 }
});
var b = vBuilder.DenseOfArray(new double[] { -3, -5, -2 });
Vector<double> x;
x = A.Solve(b);
Cleary the system has a solution (e.g. X = {0, 0, 0, 0, 3, 5, 2}).
How can I solve such a system with Math.Net?
You can not use the Matrix.Solve function with a non-square matrix because there is no inverse and no unique solutions for a rectangular matrix. Google "inverse of rectangular matrix" for explanations galore. You can use pseudoinverse however, as shown below.
var mBuilder = Matrix<double>.Build;
var A = mBuilder.DenseOfArray(new double[,]
{
{ 3, 2, 1, 5, -1, 0, 0 },
{ 2, 1, 1, 2, 0, -1, 0 },
{ 5, 1, 3, 4, 0, 0, -1 }
});
Matrix<double> b = Matrix<double>.Build.Dense(3, 1);
b[0, 0] = -3.0;
b[1, 0] = -5.0;
b[2, 0] = -2.0;
var p = A.PseudoInverse();
var x = p * b;
// verify
var o = A * x;

Loop around an array

Let's say I have an Array:
arr[3]={0,1,2};
and I am generating a Random value:
int r = Random.Range(0,4);
And in my code just after that I want to use:
print(arr[r-1]+arr[r]+arr[r+1]);
In this case it will only work if arr[r] is 1, because if r=0 then r-1 will be -1 , what can I do so if I increment the last index, it goes back to a certain point?
So that if r=2, so arr[r]=2, arr[r+1]=0 , and arr[r+4] is also 0 because it did an extra loop.
I know I could use ifs, if r=0 then r-1=3 but it's less than ideal.
Thanks
Here's something that I think you can work with:
var random = new Random();
var arr = new [] { 0, 1, 2 };
for (var i = 0; i < 20; i++)
{
int r = random.Next(1, 1 + arr.Length);
Console.WriteLine(String.Join(", ", (r - 1) % 3, r % 3, (r + 1) % 3));
}
That produces:
1, 2, 0
2, 0, 1
2, 0, 1
1, 2, 0
2, 0, 1
2, 0, 1
1, 2, 0
1, 2, 0
2, 0, 1
1, 2, 0
1, 2, 0
1, 2, 0
2, 0, 1
1, 2, 0
1, 2, 0
1, 2, 0
0, 1, 2
1, 2, 0
1, 2, 0
0, 1, 2
You can try modulus %. I'm not too sure if the operation will always return a positive value, but you can always do r = random.range(3,7);, and then use r-1 % 3 etc.

How to create single dimensional, two dimensional,three dimensional as well as multi dimensional array using C#?

I am trying to keep all the combinations (5C1, 5C2, 5C3, 5C4, 5C5) of 1,2,3,4,5 into individual array. So I need to create dynamic array using for loop in c#.
Say for example,
Here n = 5 and r = 1 to 5.
if r = 1 then
My array will be single dimensional array, when r = 2 then it will be two dimensional array, when r = 3 then three dimensional, when r = 4 then four dimensional array and it will e continued up to end of 5.
My code is given below
string[] ShipArrayObj;
public frmResult( string[] ShipArray )
{
InitializeComponent();
ShipArrayObj = ShipArray;
}
private void frmResult_Load(object sender, EventArgs e)
{
string[] arr = ShipArrayObj;
int n = ShipArrayObj.Count();
for (int r = 1; r <= n; r++)
{
StoreCombination(arr, n, r);
richTextBox1.Text = richTextBox1.Text + "/";
}
}
void StoreCombination(string[] arr, int n, int r)
{
string[] data = new string[r];
createCombination (arr, data, 0, n - 1, 0, r);
}
private void createCombination(string[] arr, string[] data, int start, int end, int index, int r)
{
if (index == r)
{
int j = 0;
for (j = 0; j < r; j++)
richTextBox1.Text = richTextBox1.Text + data[j].ToString();//Where I want to set array to keep combination values
return;
}
int i = 0;
for (i = start; i <= end && end - i + 1 >= r - index; i++)
{
data[index] = arr[i];
CreateCombination(arr, data, i + 1, end, index + 1, r);
}
}
I am storing all the combination into a Rich Text Box, but want to keep into array. If anybody help me then I will be grateful to you.
If you're used to something like Java then multidimensional arrays are a little different in syntax in C#.
Here's a page describing how to do them in C#. Here's a snippet from said page:
// 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 } } };
If you're interested in different combinations of things with a fixed number of them, something like this should be all you need.
If you're interested in different combinations of things with a dynamic number of them, something like this should be all you need.
(Unless you're trying to optimize performance, it's better to be readable/expressive, generally speaking.)
You may need to consider whether or not order matters (un-ordered set vs. ordered list). I would assume it doesn't from your code (in which case sorting is good to eliminate "duplicates"), but I can't tell for sure.
Here's a good example that's easy to read and modify for variations and isn't so bad for small numbers:
// -1, 0, ..., 5
var choices = Enumerable.Range(-1, 6);
var possibleChoices =
from a in choices
from b in choices
from c in choices
from d in choices
from e in choices
select (IEnumerable<int>)new [] { a, b, c, d, e };
// Remove -1's because they represent not being in the choice.
possibleChoices =
possibleChoices.Select(c => c.Where(d => d >= 0));
// Remove choices that have non-unique digits.
possibleChoices =
possibleChoices.Where(c => c.Distinct().Count() == c.Count());
// Sort the choices to indicate order doesn't matter
possibleChoices =
possibleChoices.Select(c => c.OrderBy(d => d));
// Remove duplicates
possibleChoices =
possibleChoices.Select(c => new
{
Key = string.Join(",", c),
Choice = c
}).
GroupBy(c => c.Key).
Select(g => g.FirstOrDefault().Choice);
foreach (var choice in possibleChoices) {
Console.Out.WriteLine(string.Join(", ", choice));
}
Output:
0
1
2
3
4
0, 1
0, 2
0, 3
0, 4
1, 2
1, 3
1, 4
2, 3
2, 4
3, 4
0, 1, 2
0, 1, 3
0, 1, 4
0, 2, 3
0, 2, 4
0, 3, 4
1, 2, 3
1, 2, 4
1, 3, 4
2, 3, 4
0, 1, 2, 3
0, 1, 2, 4
0, 1, 3, 4
0, 2, 3, 4
1, 2, 3, 4
0, 1, 2, 3, 4
This is probably a little more dense to understand, hard-coded to this specific variation of combination and involves recursion but is a bit more generic/isn't hard-coded to 5 (and took 0.047s on dotnetfiddle.net instead of 0.094s). It's also completely lazy/IEnumerable.
public static void Main()
{
var possibleChoices = Choose(5);
foreach (var choice in possibleChoices) {
Console.Out.WriteLine(string.Join(", ", choice));
}
}
public static IEnumerable<IEnumerable<int>> Choose(int max)
{
var remaining = Enumerable.Range(0, max);
return ChooseRecursive(remaining, Enumerable.Empty<int>());
}
public static IEnumerable<IEnumerable<int>> ChooseRecursive(IEnumerable<int> remaining, IEnumerable<int> chosen)
{
yield return chosen;
foreach (var digit in remaining)
{
var choices = ChooseRecursive(
remaining.Where(d => d > digit),
chosen.Concat(new [] { digit })
);
foreach (var choice in choices)
{
yield return choice;
}
}
}
Output:
0
0, 1
0, 1, 2
0, 1, 2, 3
0, 1, 2, 3, 4
0, 1, 2, 4
0, 1, 3
0, 1, 3, 4
0, 1, 4
0, 2
0, 2, 3
0, 2, 3, 4
0, 2, 4
0, 3
0, 3, 4
0, 4
1
1, 2
1, 2, 3
1, 2, 3, 4
1, 2, 4
1, 3
1, 3, 4
1, 4
2
2, 3
2, 3, 4
2, 4
3
3, 4
4

How many values are in sequence from an array

I want to find how many values, in an array, are in sequence without sorting.
For Instance, if I have.
int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 9 } //0, 1, 2, 3, 4, 5, 6 are in sequence
int value = HighestSequence(arr);
//value prints 7
int[] arr = new int[] { 0, 4, 1, 2, 3, 4, 7, 9 } //1, 2, 3, 4 are in sequence
int value = HighestSequence(arr);
//value prints 4
int[] arr = new int[] { 0, 1, 2 } //0, 1, 2 is in sequence
int value = HighestSequence(arr);
//value prints 3
You don't specify what should happen if there is more than one subsequence in order, but I've assumed there will be only one.
Try this:
int length = 1;
int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 9 }; //0, 1, 2, 3, 4, 5, 6 are in sequence
//value prints 7
List<int> temp = arr.Zip(arr.Skip(1), (i1, i2) => length += (i2 - i1 == 1 ? 1 : 0)).ToList();
Length will contain the number of integers in sequence where arr[n] == arr[n+1] - 1
Cheers
EDIT:
In the case where there is more than one subsequence that is ordered such that arr[n] == arr[n+1] - 1, we'd need to decide how to handle it.
One way would be to reset the length when we find a value that doesn't meet the criteria:
arr = new int[] { 0, 1, 2, 5, 4, 5, 6, 9 }; //Possible bug ?
length = 1;
temp = arr.Zip(arr.Skip(1), (i1, i2) =>
{
if(i2 - i1 == 1)
{
length++;
}
else
{
length = 1;
}
return i1;
}).ToList();
But then this will not consider the "longest" subsequence, it will return the length of the "last" subsequence in the sequence.
The OP should specify what action he wants in such cases.
EDIT #2:
If we want to have the longest subsequence, then this could be used:
arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 5, 4, 5, 6, 7, 9 }; //Possible bug ?
length = 1;
int longest = length;
temp = arr.Zip(arr.Skip(1), (i1, i2) =>
{
if (i2 - i1 == 1)
{
if (++length > longest)
longest = length;
}
else
{
length = 1;
}
return i1;
}).ToList();
Caching the longest ordered subsequence length. Then use longest instead of length as the result.
EDIT #3:
Edits #1 & 2 should now contain the appropriate solution. I was obviously trying to come up with a solution to a comment from a user too quickly and I didn't realize that the current code in my VS solution was different than the code I posted here.
It is to be mentioned that the OP didn't have those additional constraints, and that I did mention right from the get go that my solution didn't address those additional constraints.
Nonetheless, it was an interesting problem to solve ;-)
Cheers
Try this out. I got the results of (7,4,3). Although Peter is correct about StackOverflow you should give your attempt and say your issue not just ask for an answer. I only provided it because it was a neat challenge.
var set1 = new [] { 0, 1, 2, 3, 4, 5, 6, 9 };
var result1 = HighestSequence(set1);
var set2 = new[] { 0, 4, 1, 2, 3, 4, 7, 9 };
var result2 = HighestSequence(set2);
var set3 = new [] { 0, 1, 2 };
var result3 = HighestSequence(set3);
public int HighestSequence(int[] values)
{
IList<int> sequenceCounts = new List<int>();
var currentSequence = 0;
for (var i = 0; i < values.Length; i++)
{
if (i == (values.Length - 1)) //End edge case
{
if (values[i] - values[i - 1] == 1)
{
currentSequence++;
sequenceCounts.Add(currentSequence);
}
}
else if ((values[i] + 1) == values[i + 1])
{
currentSequence++;
}
else
{
currentSequence++;
sequenceCounts.Add(currentSequence);
currentSequence = 0;
continue;
}
sequenceCounts.Add(currentSequence);
}
return sequenceCounts.Max();
}

Fastest algorithm to merge 2 arrays such that elements are interlocked at even intervals

Requirements:
Integer operations only (no floats)
Elements are interlocked at intervals as evenly as possible
Note:
"Intervals as evenly as possible" can be defined as having each length of intervals as close to one value as possible.
Micro-optimizations are welcome and desired.
Example inputs and outputs:
//Inputs
[ 1, 2, 3, 4, 5, 6, 7 ]
[ 10, 20, 30, 40 ]
//Correct output
[ 1, 10, 2, 20, 3, 30, 4, 5, 40, 6, 7]
//Wrong output ([5, 6, 7] is not an optimal interval)
[ 1, 10, 2, 20, 3, 30, 4, 40, 5, 6, 7]
-
//Inputs
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[ 2, 2, 2 ]
//Correct output
[ 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 3, 1, 1]
//Wrong output (last [1] is not an optimal interval)
[ 1, 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, 3, 1]
Here's my own implementation with as much optimization as I can think of for a managed language. In C++, it may be faster to use a triple XOR swap for the array pointers, but I'm not sure. It may be necessary to look at the JITed assembly to further optimize this particular code.
In the meantime, let's see if other people have better algorithms.
int[] InterlockMerge(int[] a1, int[] a2) {
var longSet = a1;
var shortSet = a2;
//Swap if a2 is longer
if (a1.Length < a2.Length){
longSet = a2;
shortSet = a1;
}
var ll = longSet.Length;
var ls = shortSet.Length;
var totalLength = ll + ls;
int[] res = new int[totalLength]; //The resulting set
int l = ll / (ls + 1); //Initial testing ratio (an int)
int li = 0; //index for longSet
int si = 0; //index for shortSet
for (int i = 0; i < totalLength; i++) {
if (l > 0) {
res[i] = longSet[li++];
l--;
continue;
}
res[i] = shortSet[si++];
l = (ll - li) / (ls - si + 1); //Recalculate the testing ratio
}
return res;
}

Categories

Resources