How to convert ND array to 1D and revert it back - c#

I need to convert n array (dimension is not known) to 1d and revert it back to nd array.
I loop through the whole array and add elements to 1d to convert, but I don't know how to revert it back.
public class ArrayND<T>
{
private int[] _lengths;
private Array _array;
public ArrayND(int[] length)
{
_lengths = length;
_array = Array.CreateInstance(typeof (T), _lengths);
}
}
///Loop through
public float[] ConvertTo1D(ArrayND<float> ndArray)
{
float[] OneDArray = new float[ndArray.Values.Length];
System.Collections.IEnumerator myEnumerator = ndArray.Values.GetEnumerator();
int cols = ndArray.Values.GetLength(ndArray.Values.Rank - 1);
int j = 0;
while (myEnumerator.MoveNext())
{
OneDArray[j] = (float)myEnumerator.Current;
j++;
}
return OneDArray;
}

public class ArrayND<T>
{
private int[] _lengths;
private Array _array;
public ArrayND(int[] length)
{
_lengths = length;
_array = Array.CreateInstance(typeof(T), _lengths);
}
public T GetValue(int[] index) => (T)_array.GetValue(index);
public void SetValue(T value, int[] index) => _array.SetValue(value, index);
public T[] ToOneD() => _array.Cast<T>().ToArray();
public static ArrayND<T> FromOneD(T[] array, int[] lengths)
{
if (array.Length != lengths.Aggregate((i, j) => i * j))
throw new ArgumentException("Number of elements in source and destination arrays does not match.");
var factors = lengths.Select((item, index) => lengths.Skip(index).Aggregate((i, j) => i * j)).ToArray();
var factorsHelper = factors.Zip(factors.Skip(1).Append(1), (Current, Next) => new { Current, Next }).ToArray();
var res = new ArrayND<T>(lengths);
for (var i = 0; i < array.Length; i++)
res.SetValue(array[i],
factorsHelper.Select(item => i % item.Current / item.Next).ToArray());
return res;
}
public override bool Equals(object obj) =>
(obj is ArrayND<T> ndArray) &&
_lengths.SequenceEqual(ndArray._lengths) &&
_array.Cast<T>().SequenceEqual(ndArray._array.Cast<T>());
public override int GetHashCode() =>
new[] { 17 }
.Concat(_lengths.Select(i => i.GetHashCode()))
.Concat(_array.Cast<T>().Select(i => i.GetHashCode()))
.Aggregate((i, j) => unchecked(23 * i + j));
}
It works with any number of dimensions.
Test it:
int I = 2, J = 3, K = 4;
var a = new ArrayND<int>(new[] { I, J, K });
var v = 0;
for (var i = 0; i < I; i++)
for (var j = 0; j < J; j++)
for (var k = 0; k < K; k++)
a.SetValue(++v, new[] { i, j, k });
var b = a.ToOneD();
var c = ArrayND<int>.FromOneD(b, new[] { I, J, K });
Console.WriteLine(a.Equals(c)); // True
or:
int I = 2, J = 3;
var a = new ArrayND<int>(new[] { I, J });
var v = 0;
for (var i = 0; i < I; i++)
for (var j = 0; j < J; j++)
a.SetValue(++v, new[] { i, j });
var b = a.ToOneD();
var c = ArrayND<int>.FromOneD(b, new[] { I, J });
Console.WriteLine(a.Equals(c)); // True
or:
int I = 2, J = 3, K = 4, M = 5;
var a = new ArrayND<int>(new[] { I, J, K, M });
var v = 0;
for (var i = 0; i < I; i++)
for (var j = 0; j < J; j++)
for (var k = 0; k < K; k++)
for (var m = 0; m < M; m++)
a.SetValue(++v, new[] { i, j, k, m });
var b = a.ToOneD();
var c = ArrayND<int>.FromOneD(b, new[] { I, J, K, M });
Console.WriteLine(a.Equals(c)); // True

Well, I solve it in a weird way. I am open to better approaches
public ArrayND<string> convert1DtoND(string[] oneDarray, int[] dimension)
{
ArrayND<string> ndArray = new ArrayND<string>(dimension);
int[] index = new int[ndArray.Values.Rank];
int[] length = new int[ndArray.Values.Rank];
int j = 0;
for (int i = 0; i < length.Length; i++)
{
length[i] = ndArray.Values.GetLength(i);
}
do
{
ndArray[index] = oneDarray[j];
j++;
} while (Increment(index, length));
return ndArray;
}
public static bool Increment(int[] index, int[] length)
{
int i = index.Length - 1;
index[i]++;
while (i >= 0 && index[i] == length[i] && length[i] > 0)
{
index[i--] = 0;
if (i >= 0)
index[i]++;
}
if (i < 0 || length[i] == 0)
return false;
else
return true;
}

Related

Multiplication matrix on vector

I need to multiply the matrix on the vector and print the result. There are classes of integer vector and integer matrix. When outputting, displays only the first element. Can you tell me what the error is? Below I show the overloading of the * operator that I made, the method for displaying the matrix and exactly how I display it. Here is an example
public class VectorInt//class VectorInt
{
protected int[] IntArray;
protected uint size;
protected int codeError;
protected static uint num_vec;
public VectorInt()
{
codeError = 1;
size = 1;
IntArray = new int[size];
IntArray[0] = 0;
num_vec++;
}
public VectorInt(uint n)//конструктор з одним параметром
{
codeError = 1;
size = n;
IntArray = new int[size];
for (int i = 0; i < n; i++)
{
IntArray[i] = 0;
}
num_vec++;
}
public VectorInt(uint n, int b)
{
codeError = 1;
size = n;
IntArray = new int[size];
for (int i = 0; i < n; i++)
{
IntArray[i] = b;
}
num_vec++;
}
~VectorInt()
{
num_vec--;
Console.WriteLine("Dipsosed");
}
public void Input()
{
Console.WriteLine("\nSize of vector: ");
size = uint.Parse(Console.ReadLine());
IntArray = new int[size];
for (int i = 0; i < size; i++)
{
Console.WriteLine("Element {0}: ", i);
Console.WriteLine(" v [ {0} ] = {1} ", i, IntArray[i] = int.Parse(Console.ReadLine()));
}
}
public void Output()
{
Console.WriteLine("\nMatrix");
for (int i = 0; i < n; i++)//n-amount of rows
{
for (int j = 0; j < m; j++)//m-amount of columns
{
Console.Write(" m [ {0}{1} ] = {2} ", i, j, IntArray[i, j]);
}
Console.WriteLine();
}
}
public uint Size
{
get
{
return (uint)IntArray.Length;
}
}
public int[] NewIntArray
{
get => IntArray;
}
////////////////////////////////////////////////////////
public class MatrixInt//class MatrixInt
{
protected int[,] IntArray;
protected int n, m;
protected int codeError;
protected static int num_m;
public MatrixInt()
{
n = 1; m = 1;
IntArray = new int[n, m];
IntArray[0, 0] = 0;
num_m++;
}
public MatrixInt(int r, int c)
{
n = r; m = c;
IntArray = new int[n, m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
IntArray[i, j] = 0;
}
num_m++;
}
public MatrixInt(int r, int c, int b)
{
n = r; m = c;
IntArray = new int[n, m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
IntArray[i, j] = b;
}
num_m++;
}
~MatrixInt()
{
num_m--;
Console.WriteLine("Disposed");
}
public void Input()
{
Console.WriteLine("Number of rows: ");
n = int.Parse(Console.ReadLine());
Console.WriteLine("Number of columns: ");
m = int.Parse(Console.ReadLine());
IntArray = new int[n, m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
Console.WriteLine("Element {0}{1}: ", i, j);
Console.WriteLine(" m [ {0}{1} ] = {2} ", i, j, IntArray[i, j] = int.Parse(Console.ReadLine()));
}
}
}
public void Output()
{
Console.WriteLine("\nMatrix");
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
Console.Write(" m [ {0}{1} ] = {2} ", i, j, IntArray[i, j]);
}
Console.WriteLine();
}
}
public int Rows
{
get
{
return n;
}
}
public int Columns
{
get
{
return m;
}
}
/////////////////////////////////////////////////////////////
public static MatrixInt operator *(MatrixInt obj, VectorInt obj1)
{
MatrixInt obj3 = new MatrixInt();
if (obj.Columns != obj1.NewIntArray.Length)
{
throw new Exception("Error!");
}
obj3.IntArray = new int[obj.Rows, 1];
for (int i = 0; i < obj.Rows; i++)
{
obj3.IntArray[i, 0] = 0;
for (int j = 0; j < obj.Columns; j++)
{
obj3.IntArray[i, 0] += obj.IntArray[i, j] * obj1.NewIntArray[j];
//Console.WriteLine(" m [ {0}{1} ] = {2} ", i, j, obj3.IntArray[i, 0]);
}
}
return obj3;
}
////////////////////////////////////////////////////////
MatrixInt obj = new MatrixInt();
VectorInt obj1 = new VectorInt();
obj.Input();
obj.Output();
obj1.Input();
obj1.Output();
obj *= obj1;
obj.Output();

How to turn a recursive algorithm into a parallel processing recursive algorithm

I'm doing my homework for Algorithms and I stumbled into a problem. I was not able to transform a recursive algorithm to parallel process recursive algorithm.
This is the given equation I was given:
Equation
This is my code for this equation without parallel processing:
class Program
{
static void Main(string[] args)
{
List<int> p = new List<int> { 1, 2, 3, 4};
Console.WriteLine(F(4, 4, p));
}
public static int F(int k, int n, List<int> p)
{
List<int> maxList = new List<int>();
int ats = 0;
if (n == 0) { return 0; }
else if (k == 1)
{
ats = 0;
for (int i = 0; i < n; i++)
{
ats += p[i];
}
return ats;
}
else
{
for (int i = 0; i < n; i++)
{
ats = 0;
for (int j = i; j < n; j++)
{
ats += p[j];
}
int funkcija = F(k - 1, n - 1, p);
if (ats > funkcija)
{
maxList.Add(ats);
}
else
{
maxList.Add(funkcija);
}
}
}
ats = maxList.Min();
return ats;
}
}
I need to make this code to process parallel.
I tried changing for cycles into
I tried like this
public static int FPara(int k, int n, List<int> p)
{
List<int> maxList = new List<int>();
int ats = 0;
if (n == 0) { return 0; }
else if (k == 1)
{
ats = 0;
for (int i = 0; i < n; i++)
{
ats += p[i];
}
return ats;
}
else
{
Parallel.For(0, n - 1, i =>
{
ats = 0;
for (int j = i; j < n; j++)
{
ats += p[j];
}
int funkcija = F(k - 1, n - 1, p);
if (ats > funkcija)
{
maxList.Add(ats);
}
else
{
maxList.Add(funkcija);
}
});
}
ats = maxList.Min();
return ats;
}
however, it doesn't work.

Failed Gauss-Jordan elimination implementation in C#

Based on the alorithm given here https://en.wikipedia.org/wiki/Gaussian_elimination#Pseudocode,
I tried to implement a C# version of the Gaussian Elimination:
public Matrix GaussianElimination(double epsilon = 1e-10)
{
var result = Copy();
var kMax = Math.Min(result.RowCount, result.ColumnCount);
for (var k = 0; k < kMax; k++)
{
// Find k-th pivot, i.e. maximum in column max
var iMax = result.FindColumnAbsMax(k);
if (Math.Abs(result[iMax, k]) < epsilon)
{
throw new ArithmeticException("Matrix is singular or nearly singular.");
}
// Swap maximum row with current row
SwapRows(k, iMax);
// Make all rows below the current one, with 0 in current column
for (var i = k + 1; i < result.RowCount; i++)
{
var factor = result[i, k] / result[k, k];
for (var j = k + 1; j < result.ColumnCount; j++)
{
result[i, j] = result[i, j] - result[k, j] * factor;
}
result[i, k] = 0;
}
}
return result;
}
It works in most cases (note that this is not performing the back substitution step). However, for the first example given in Wikipedia, the algorithm stop on the singular matrix case and throw the related exception on the row echelon form right before back substitution step with:
public class Program
{
public static void Main(string[] args)
{
var matrix = Matrix.Parse("[1 3 1 9; 1 1 -1 1; 3 11 5 35]");
Console.WriteLine(matrix);
Console.WriteLine(matrix.GaussianElimination());
Console.ReadKey();
}
}
k = 2
kMax = 3
iMax = 2
result = [1 3 1 9; 0 -2 -2 -8; 0 0 0 0]
[EDIT]
The Matrix implementation is a bit lengthy but here is what it is used in regard to the string parsing and the elimination method:
public class Matrix
{
public const string MatrixStart = "[";
public const string MatrixStop = "]";
public const char RowSeparator = ';';
public const char RowCellSeparator = ' ';
public int RowCount { get; }
public int ColumnCount { get; }
public int CellCount => _data.Length;
public bool IsSquare => RowCount == ColumnCount;
public bool IsVector => ColumnCount == 1;
private readonly double[] _data;
public double this[int rowIndex, int columnIndex]
{
get => _data[Convert2DIndexTo1DIndex(rowIndex, columnIndex)];
set => _data[Convert2DIndexTo1DIndex(rowIndex, columnIndex)] = value;
}
public Matrix(Matrix matrix)
: this(matrix.RowCount, matrix.ColumnCount)
{
for (var i = 0; i < _data.Length; i++)
{
_data[i] = matrix._data[i];
}
}
public Matrix(int size, double placeHolder = 0)
: this(size, size, placeHolder)
{
}
public Matrix(int rowCount, int columnCount, double initializationValue = 0)
{
if (rowCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(rowCount));
}
if (columnCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(columnCount));
}
RowCount = rowCount;
ColumnCount = columnCount;
_data = new double[RowCount * ColumnCount];
if (Math.Abs(initializationValue) > 0)
{
Set(initializationValue);
}
}
public Matrix(int rowCount, int columnCount, double[] initializationValues)
{
if (rowCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(rowCount));
}
if (columnCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(columnCount));
}
if (initializationValues.Length != rowCount * columnCount)
{
throw new ArgumentOutOfRangeException(nameof(initializationValues));
}
RowCount = rowCount;
ColumnCount = columnCount;
_data = new double[initializationValues.Length];
initializationValues.CopyTo(_data, 0);
}
private int Convert2DIndexTo1DIndex(int rowIndex, int columnIndex)
{
return rowIndex * ColumnCount + columnIndex;
}
public void Set(double value)
{
for (var i = 0; i < _data.Length; i++)
{
_data[i] = value;
}
}
public Matrix Transpose()
{
var result = new Matrix(ColumnCount, RowCount);
for (var i = 0; i < result.RowCount; i++)
{
for (var j = 0; j < result.ColumnCount; j++)
{
result[i, j] = this[j, i];
}
}
return result;
}
public Matrix Copy()
{
return new Matrix(this);
}
private int FindColumnAbsMax(int index)
{
return FindColumnAbsMax(index, index);
}
private int FindColumnAbsMax(int rowStartIndex, int columnIndex)
{
var maxIndex = rowStartIndex;
for (var i = rowStartIndex + 1; i < RowCount; i++)
{
if (Math.Abs(this[maxIndex, columnIndex]) <= Math.Abs(this[i, columnIndex]))
{
maxIndex = i;
}
}
return maxIndex;
}
public void SwapRows(int rowIndexA, int rowIndexB)
{
for (var j = 0; j < ColumnCount; j++)
{
var indexA = Convert2DIndexTo1DIndex(rowIndexA, j);
var indexB = Convert2DIndexTo1DIndex(rowIndexB, j);
_data.Swap(indexA, indexB);
}
}
public void SwapColumns(int columnIndexA, int columnIndexB)
{
for (var i = 0; i < RowCount; i++)
{
var indexA = Convert2DIndexTo1DIndex(i, columnIndexA);
var indexB = Convert2DIndexTo1DIndex(i, columnIndexB);
_data.Swap(indexA, indexB);
}
}
public static Matrix Parse(string matrixString)
{
if (!matrixString.StartsWith(MatrixStart) || !matrixString.EndsWith(MatrixStop))
{
throw new FormatException();
}
matrixString = matrixString.Remove(0, 1);
matrixString = matrixString.Remove(matrixString.Length - 1, 1);
var rows = matrixString.Split(new[] { RowSeparator }, StringSplitOptions.RemoveEmptyEntries);
if (rows.Length <= 0)
{
return new Matrix(0, 0);
}
var cells = ParseRow(rows[0]);
var matrix = new Matrix(rows.Length, cells.Length);
for (var j = 0; j < cells.Length; j++)
{
matrix[0, j] = cells[j];
}
for (var i = 1; i < matrix.RowCount; i++)
{
cells = ParseRow(rows[i]);
for (var j = 0; j < cells.Length; j++)
{
matrix[i, j] = cells[j];
}
}
return matrix;
}
private static double[] ParseRow(string row)
{
var cells = row.Split(new [] { RowCellSeparator }, StringSplitOptions.RemoveEmptyEntries);
return cells.Select(x => Convert.ToDouble(x.Replace(" ", string.Empty))).ToArray();
}
}
And the 1D Array extension for swapping two items:
public static class ArrayHelpers
{
public static void Swap<TSource>(this TSource[] source, int indexA, int indexB)
{
var tmp = source[indexA];
source[indexA] = source[indexB];
source[indexB] = tmp;
}
}

sum middle number with jagged array in C#

I write some code with jagged array but when i sum middle number program not working and i cant fix it...:
public class JaggedArray
{
public static void Array()
{
int[][] arrayOfArray = ArrayOfArray();
var tong = 0;
for (var i = 1; i < arrayOfArray.Length; i++)
{
for (var j = 0; j < arrayOfArray[i].Length; j++)
{
var bienTam = arrayOfArray[i].Length;
var tamThoi = j;
if (bienTam%2==0&&tamThoi==bienTam/2)
{
tamThoi++;
tong += arrayOfArray[i][tamThoi];
}
}
}
OutPut(arrayOfArray, tong);
}
private static int[][] ArrayOfArray()
{
Random ngauNhien = new Random();
int[][] arrayOfArray = new int[13][];
for (var i = 0; i <arrayOfArray.Length; i++)
{
arrayOfArray[i] = new int[i];
for (var j = 0; j < arrayOfArray[i].Length; j++)
{
arrayOfArray[i][j] = ngauNhien.Next(0, 99); //throw exception
}
}
return arrayOfArray;
}
can someone explain reason why i wrong and how ti fix it?
The problem you are solving is the one Linq is very good for:
int[][] arrayOfArray = new int[][] {
new[] {1, 2, 3}, // 2 is the middle item
new[] {4, 5} // in case of tie, let 5 (right) be the middle item
new[] {7}, // 7
new int[] {}, // should be ignored
};
// 2 + 5 + 7 == 14
var result = arrayOfArray
.Where(line => line != null && line.Length > 0)
.Sum(line => line[line.Length / 2]);
So I've got it compiling:
public class JaggedArray
{
public static void Array()
{
int[][] arrayOfArray = ArrayOfArray();
var tong = 0;
for (var i = 1; i < arrayOfArray.Length; i++)
{
for (var j = 0; j < arrayOfArray[i].Length; j++)
{
var bienTam = arrayOfArray[i].Length;
var tamThoi = j;
if (j % 2 == 0 && j / 2 == bienTam / 2)
{
tamThoi++;
// You need to check here that tamThoi isn't
// outside the bounds of your array
if (tamThoi >= arrayOfArray[i].Length)
{
continue;
}
tong += arrayOfArray[i][tamThoi];
}
}
}
}
private static int[][] ArrayOfArray()
{
Random ngauNhien = new Random();
int[][] arrayOfArray = new int[13][];
for (var i = 0; i < 13; i++)
{
arrayOfArray[i] = new int[i];
// here you're better off using i
// instead of the arrayOfArray[i].Length - because you know the length
for (var j = 0; j < i; j++)
{
arrayOfArray[i][j] = ngauNhien.Next(0, 99);
}
}
return arrayOfArray;
}
}
You can make this far more succinct with LINQ.

Displaying result of KMP compute prefix function

I'm trying to solve homework for school, it concerns KMP algorithm. Here is my compute prefix function, it is suppose to output a prefix table, however all it does is every time it returns all 0s. Could help me understand what am I doing wrong? Thanks!
static int[] computePrefixFunction(string P)
{
int m = P.Length;
int[] pi = new int[m];
pi[1] = 0;
int k = 0;
for (int j = 2; j < m; j++)
{
while (k > 0 && P[k + 1] != P[j])
{
k = pi[k];
}
if (P[k+1] == P[j])
{ k = k + 1; };
pi[j] = k;
}
for (int i = 0; i < pi.Length; i++)
{
Console.WriteLine(pi[i]);
}
return pi;
}
You a have messed up indexes offsets. Here is fixed version:
static int[] computePrefixFunction(string P)
{
int m = P.Length;
int[] pi = new int[m];
int k = 0;
for (int j = 1; j < m; j++)
{
k = pi[j - 1];
while (k > 0 && P[k] != P[j])
k = pi[k-1];
if (P[k] == P[j])
k = k + 1;
pi[j] = k;
}
return pi;
}
Live demo: https://dotnetfiddle.net/YQknMp

Categories