Is there a efficient way to join blocks in the arrays, as shown here:
original_array = [[1,2], [4,7], [8,10], [15,20], [21,25]]
new_array = [[1,2], [4,10], [15,25]]
Basically I want to join 2 indexes of an array if the distance between them is 1.
I tried something like this but it didin't work.
int[,] new_array = new int[500, 2];
int new_var = 0;
for (int k = 0; k < original_indexes; k++)
{
int dista = original_array [k + 1, 0] - original_array [k, 1];
if (dista < 10)
{
new_array[k, 0] = original_array[k, 0];
new_array[k, 1] = original_array[k + 1, 1];
new_var++;
}
else
{
new_array[k, 0] = original_array[k + new_var, 0];
new_array[k, 1] = original_array[k + new_var, 1];
}
}
Sorry, but I don't know how to be more specific and I don't even know how to search for this.
You can try something like this:
using System.Linq;
...
private static int[,] MyCombine(int[,] source) {
List<int[]> list = new List<int[]>();
int[] last = null;
for (int r = 0; r < source.GetLength(0); ++r)
if (last == null || last[1] + 1 < source[r, 0]) {
if (last != null)
list.Add(last);
last = new int[] { source[r, 0], source[r, 1] };
}
else
last[1] = source[r, 1];
if (last != null)
list.Add(last);
int[,] result = new int[list.Count, 2];
for (int r = 0; r < list.Count; ++r)
for (int c = 0; c < list[r].Length; ++c)
result[r, c] = list[r][c];
return result;
}
Demo:
int[,] original = new int[,] {
{ 1, 2 },
{ 4, 7 },
{ 8, 10 },
{15, 20 },
{21, 25 },
};
int[,] result = MyCombine(original);
string report = "[" + string.Join(", ", Enumerable
.Range(0, result.GetLength(0))
.Select(r => $"[{result[r, 0]}, {result[r, 1]}]")) + "]";
Console.Write(report);
Outcome:
[[1, 2], [4, 10], [15, 25]]
Related
I am learning C#, and I am doing Multidimensional Arrays at the moment. I want to write a program that reads a matrix and then finds the biggest sum of 2x2 submatrix and prints it.
int[] dimensions = Console.ReadLine()
.Split(", ", StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
int rows = dimensions[0];
int columns = dimensions[1];
int[,] matrix = new int[rows,columns];
for (int i = 0; i < rows; i++)
{
int[] numbers = Console.ReadLine()
.Split(", ", StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
for (int j = 0; j < columns; j++)
{
matrix[i, j] = numbers[j];
}
}
int maxSum = int.MinValue;
int selectedRow = -1;
int selectedCol = -1;
for (int row = 0; row < matrix.GetLength(0) - 1; row++)
{
for (int col = 0; col < matrix.GetLength(1) - 1; col++)
{
int currentSum = matrix[row, col] + matrix[row, col + 1] + matrix[row + 1, col] + matrix[row + 1, col + 1];
if (currentSum > maxSum)
{
maxSum = currentSum;
selectedRow = row;
selectedCol = col;
}
}
}
Console.WriteLine($"{matrix[selectedRow, selectedCol]} {matrix[selectedRow, selectedCol + 1]}");
Console.WriteLine($"{matrix[selectedRow + 1, selectedCol]} {matrix[selectedRow + 1, selectedCol + 1]}");
Console.WriteLine(maxSum);
So, I read the matrix, but I am not sure how to start finding the submatrices and compare their sums. I would be very grateful if you could give me some hints.
You need to check values only current, under positions of your i and current, right positions of your j.
I mean it will check like this:
[7,1] [1,3] [3,3]
[1,3] [3,9] [9,8]
And so on.
After every compare, calculate sum of this 2x2 matrix and save it to dictionary.
For return, you just need to find the max value of key and get value of it key.
public class MatrixTest
{
public static IEnumerable<object[]> TestData =>
new List<object[]>
{
new object[]
{
new int[,]
{
{7, 1, 3, 3, 2, 1},
{1, 3, 9, 8, 5, 6},
{4, 6, 7, 9, 1, 0}
},
new int[,]
{
{9, 8},
{7, 9}
},
33
},
new object[]
{
new int[,]
{
{10, 11, 12, 13},
{14, 15, 16, 17}
},
new int[,]
{
{12, 13},
{16, 17}
},
58
}
};
[Theory]
[MemberData(nameof(TestData))]
public void Test(int[,] input, int[,] expectedArray, int expectedSum)
{
MatrixHandler m = new MatrixHandler();
var resp = m.GetMax2x2Matrix(input);
resp.Item1.Should().Be(expectedSum);
resp.Item2.Should().BeEquivalentTo(expectedArray);
}
}
public class MatrixHandler
{
public (int, int[,]) GetMax2x2Matrix(int[,] source)
{
var sumsPlusTempArrays = new Dictionary<int, int[,]>();
int[,] temp;
int sum = 0;
for (int i = 0, n0 = source.GetLength(0) - 1; i <= n0; i++)
{
for (int j = 0, n1 = source.GetLength(1) - 1; j <= n1; j++)
{
if (i + 1 <= n0 && j + 1 <= n1)
{
temp = new int[2,2];
temp[0, 0] = source[i, j];
temp[0, 1] = source[i, j + 1];
temp[1, 0] = source[i + 1, j];
temp[1, 1] = source[i + 1, j + 1];
sum = CalculateSum(temp);
sumsPlusTempArrays.TryAdd(sum, temp);
}
}
}
var key = sumsPlusTempArrays.Select(x => x.Key).Max();
var value = sumsPlusTempArrays[key];
return (key, value);
}
private int CalculateSum(int[,] source)
{
int sum = 0;
for (int i = 0, n0 = source.GetLength(0); i < n0; i++)
{
for (int j = 0, n1 = source.GetLength(1); j < n1; j++)
{
sum += source[i, j];
}
}
return sum;
}
}
I have 3 arrays: x, y and z. How can I write all three to one in one-after-one mode?
For example: I have X=1,2 Y=3,4 Z=5,6
I need an array W = X[1],Y[1],Z[1],X[2],Y[2],Z[2] ... X[n],Y[n],Z[n]
float[] posX = new float[rmv2.lod[0].VerticesCount[0]];
float[] posY = new float[rmv2.lod[0].VerticesCount[0]];
float[] posZ = new float[rmv2.lod[0].VerticesCount[0]];
for (int i = 0; i < 1; i += 3)
{
posX[i] = rmv2.lod[0].Mesh[0].Vertex[i].X;
posY[i + 1] = rmv2.lod[0].Mesh[0].Vertex[i].Y;
posZ[i + 2] = rmv2.lod[0].Mesh[0].Vertex[i].Z;
}
I don't see the w array you're trying to write the output to. Are you looking for something like this?
int n = rmv2.lod[0].VerticesCount[0];
float[] posX = new float[n];
float[] posY = new float[n];
float[] posZ = new float[n];
float[] w = new float[n * 3];
for (int i = 0; i < n; i++)
{
posX[i] = rmv2.lod[0].Mesh[0].Vertex[i].X;
posY[i] = rmv2.lod[0].Mesh[0].Vertex[i].Y;
posZ[i] = rmv2.lod[0].Mesh[0].Vertex[i].Z;
w[i * 3 + 0] = rmv2.lod[0].Mesh[0].Vertex[i].X;
w[i * 3 + 1] = rmv2.lod[0].Mesh[0].Vertex[i].Y;
w[i * 3 + 2] = rmv2.lod[0].Mesh[0].Vertex[i].Z;
}
Perhaps you should look at jagged arrays...
https://msdn.microsoft.com/en-us/library/2s05feca.aspx
Try this:
float[] x = new float[] { 1, 2, 9 };
float[] y = new float[] { 3, 4 };
float[] z = new float[] { 5, 6 };
int max = Math.Max(x.Length, Math.Max(y.Length, z.Length));
List<float> combined = new List<float>();
for (int i = 0; i < max; i++)
{
if (x.Length > i) combined.Add(x[i]);
if (y.Length > i) combined.Add(y[i]);
if (z.Length > i) combined.Add(z[i]);
}
Produces a list with the combined arrays, regardless of their original lengths.
1, 3, 5, 2, 4, 6, 9
If I right understand you, try this solution. With this method arrays can have different length
static T[] ConcatOneAfterOne<T>(params T[][] arrays)
{
int outputArrayLength = 0;
for (int i = 0; i < arrays.Length; i++)
{
outputArrayLength += arrays[i].Length;
}
T[] output = new T[outputArrayLength];
int outputIndex = 0;
int sourceIndex = 0;
while (outputIndex != outputArrayLength)
{
for (int arrayIndex = 0; arrayIndex < arrays.Length; arrayIndex++)
{
if (sourceIndex < arrays[arrayIndex].Length)
{
output[outputIndex++] = arrays[arrayIndex][sourceIndex];
}
}
sourceIndex++;
}
return output;
}
[Test]
static void ConcatOneAfterOneTest()
{
int[] result = ConcatOneAfterOne(new[] { 1, 2 }, new[] { 3, 4 }, new[] { 5, 6 });
CollectionAssert.AreEqual(new int[] { 1, 3, 5, 2, 4, 6 }, result);
}
I'm using C# and Microsoft Visual Studio. I'm able to display my array through this code:
private void btnDisplay_Click(object sender, EventArgs e)
{
double[,] initialArray = new double[3, 4] { { 5, 1, 9, 3 }, { 7, 8, 6, 4 }, { 2, 4, 9, 5 } };
string rowOfInts = "";
string columnsAndRow = "";
for (int r = 0; r < initialArray.GetLength(0); r++)
{
string tempString = "";
for (int c = 0; c < initialArray.GetLength(1); c++)
{
rowOfInts = tempString + " " + initialArray[r, c];
tempString = rowOfInts;
}
columnsAndRow = columnsAndRow + rowOfInts + "\n";
lblDisplay.Text = Convert.ToString(columnsAndRow);
}
// displays Display = new displays(initialArray, rowOfInts, columnsAndRow);
if (chkRowTotals.Checked == true)
{
for (int r = 0; r < initialArray.GetLength(0); r++)
{
int intTotal = 0;
string tempString = "";
for (int c = 0; c <initialArray.GetLength(1); c++)
{
rowOfInts = tempString + " " + initialArray[r, c];
tempString = rowOfInts;
}
columnsAndRow = columnsAndRow + rowOfInts;
intTotal += Convert.ToInt32(columnsAndRow);
lblDisplay.Text = Convert.ToString(intTotal);
}
}
}
but I don't know how to add the numbers by rows. Is there any way that I can total the numbers in my array by row and then display them in my label (lblDisplay)?
edit: I don't want the entire array added up- just the rows. So, the output would be 18, 25, and 20.
There are many things wrong in your code, to be completely honest. I will just put what I think is the solution you are looking for:
private void Button_Click(object sender, RoutedEventArgs e)
{
double[,] initialArray = new double[3, 4] { { 5, 1, 9, 3 }, { 7, 8, 6, 4 }, { 2, 4, 9, 5 } };
string rowOfInts = "";
string columnsAndRow = "";
for (int r = 0; r < initialArray.GetLength(0); r++)
{
string tempString = "";
double inttotal = 0;
for (int c = 0; c < initialArray.GetLength(1); c++)
{
rowOfInts = tempString + " " + initialArray[r, c];
tempString = rowOfInts;
inttotal += initialArray[r, c];
}
columnsAndRow = columnsAndRow + rowOfInts + " row total of = " + inttotal.ToString() + "\n";
}
txtbx.Text = Convert.ToString(columnsAndRow);
}
Something to the effect of:
const int numRows = 3;
const int numColumns = 4;
double[,] initialArray = new double[numRows, numColumns] { { 5, 1, 9, 3 }, { 7, 8, 6, 4 }, { 2, 4, 9, 5 } };
double[] rowTotal = new double[numRows];
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j < numColumns; j++)
{
rowTotal[i] += initialArray[i, j];
}
Console.WriteLine("Current row total: {0}", rowTotal[i]);
}
Try this:
var initialArray = new double[3, 4] { { 5, 1, 9, 3 }, { 7, 8, 6, 4 }, { 2, 4, 9, 5 } };
// List that will hold the sum of each row
List<double> rowSums = new List<double>();
for (int i = 0; i < initialArray.GetLength(0); i++)
{
// accumulator
double rowSum = 0;
for (int j = 0; j < initialArray.GetLength(1); j++)
{
rowSum += initialArray[i, j];
}
// add the row sum to our list
rowSums.Add(rowSum);
}
// will put "18, 25, 20" in your label's Text
lblDisplay.Text = string.Join(", ", rowSums);
You should consider using a flattening your array as it has better performance.
You can use the following Linq:
var numberOfRows = initialArray.GetLength(0);
var numberOfColumns = initialArray.GetLength(1);
var sumOfRows = Enumerable
.Range(0, numberOfRows)
.Select(r => Enumerable.Range(0, numberOfColumns).
Aggregate(0d, (a, i) => a += initialArray[r, i]));
lblDisplay.Text = string.Join(", ", sumOfRows);
However, it might be a lot easier to use a Jagged array instead. The Linq expression would be a lot easier.
I have an array {1,2,3,4,5,6,7,8,9,10} and I have to find all combinations of k elements from array and k will be dynamic. So for 4 elements below code is sufficient but i have to make this dynamic means,it is not fixed that how many for loops will be used, so please suggest some solution for this.
for (i = 0; i < len - 3; i++)
{
for (j = i + 1; j < len - 2; j++)
{
for (y = j + 1; y < len - 1; y++)
{
for (k = y + 1; k < len; k++)
Console.WriteLine("{0},{1},{2},{3}", s[i], s[j],s[y], s[k]);
}
}
}
All you need is to replace i, j, y, ... with array and manually unroll the for loops like this
static void PrintCombinations(int[] input, int k)
{
var indices = new int[k];
for (int pos = 0, index = 0; ; index++)
{
if (index <= input.Length - k + pos)
{
indices[pos++] = index;
if (pos < k) continue;
// Consume the combination
for (int i = 0; i < k; i++)
{
if (i > 0) Console.Write(",");
Console.Write(input[indices[i]]);
}
Console.WriteLine();
pos--;
}
else
{
if (pos == 0) break;
index = indices[--pos];
}
}
}
You can use this methods for generating combinations of size l
public static List<List<T>> GenerateCombinations<T>(List<T> items, int l)
{
if (l == 0)
return new List<List<T>> { new List<T>() };
var allCombs = new List<List<T>>();
for (int i = 0; i < items.Count(); i++)
{
var listWithRemovedElement = new List<T>(items);
listWithRemovedElement.RemoveRange(0, i + 1);
foreach (var combination in GenerateCombinations(listWithRemovedElement, l - 1))
{
var comb = new List<T>(listWithRemovedElement.Count + 1);
comb.Add(items[i]);
comb.AddRange(combination);
allCombs.Add(comb);
}
}
return allCombs;
}
You can use this methods for generating permutations of size l
public static List<List<T>> GeneratePermutations<T>(List<T> items, int l)
{
if (l == 0)
return new List<List<T>> { new List<T>() };
var allCombs = new List<List<T>>();
for (int i = 0; i < items.Count(); i++)
{
var listWithRemovedElement = new List<T>(items);
listWithRemovedElement.RemoveAt(i);
foreach (var combination in GeneratePermutations(listWithRemovedElement, l - 1))
{
var comb = new List<T>(listWithRemovedElement.Count + 1);
comb.Add(items[i]);
comb.AddRange(combination);
allCombs.Add(comb);
}
}
return allCombs;
}
Permutationsof { 1, 2, 3 } with size of 2
var result = GeneratePermutations(new List<int>() { 1, 2, 3 }, 2);
foreach (var perm in result)
Console.WriteLine(string.Join(",", perm));
1,2
1,3
2,1
2,3
3,1
3,2
Combinations of { 1, 2, 3 } with size of 2
var result = GenerateCombinations(new List<int>() { 1, 2, 3 }, 2);
foreach (var comb in result)
Console.WriteLine(string.Join(",", comb));
1,2
1,3
2,3
This isn't how I'd do it in "real life", but since this seems to be a simple homework-style problem aimed at getting you to use recursion and with the aim of simply writing out the combinations, this is a reasonably simple solution:
class Program
{
public static void Main()
{
int[] test = { 1, 2, 3, 4, 5 };
int k = 4;
WriteCombinations(test, k);
Console.ReadLine();
}
static void WriteCombinations(int[] array, int k, int startPos = 0, string prefix = "")
{
for (int i = startPos; i < array.Length - k + 1; i++)
{
if (k == 1)
{
Console.WriteLine("{0}, {1}", prefix, array[i]);
}
else
{
string newPrefix = array[i].ToString();
if (prefix != "")
{
newPrefix = string.Format("{0}, {1}", prefix, newPrefix);
}
WriteCombinations(array, k - 1, i + 1, newPrefix);
}
}
}
}
If having optional parameters is not "basic" enough, then you can either take away the default values and pass in 0 and "" on the first call, or you can create another "wrapper" method that takes fewer parameters and then calls the first method with the defaults.
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()