array in array in array and also one - c#

I need to write a factorial using an array but the problem is only Show 120 five times and what i want is 1, 2, 6, 24, 120 showing in the textBox
int factProg = 1;
public void factArray(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
factProg = factProg * arr[i];
}
}
int[] arr = {1,2,3,4,5};
for (int i = 0; i < arr.Length; i++)
{
factArray(arr);
textBox1.Text += Convert.ToString(factProg);
textBox1.Text += Environment.NewLine;
}

Simply put - your factArray method always calculates the factorial for the length of the whole array which is a fixed size. You need to pass an extra parameter - being the position in the array you want to stop calculating
Try this if you want to calculate using your array :
int factProg;
public void factArray(int[] arr, int len)
{
factProg = arr[0];
for (int i = 1; i <= len; i++)
{
factProg = factProg * arr[i];
}
}
int[] arr = {1,2,3,4,5};
for (int i = 0; i < arr.Length; i++)
{
factArray(arr, i);
textBox1.Text += Convert.ToString(factProg);
textBox1.Text += Environment.NewLine;
}
You would need to add a check in the method that you are not exceeding the array length.

Please find the code below
public static void FactorialJohn(int[] arr)
{
List<int> Resarr = new List<int>();
arr.ToList().ForEach(x => Resarr.Add(Enumerable.Range(1, x).Aggregate((a, b) => a * b)));
foreach (var item in Resarr)
{
Console.WriteLine(item);
}
}
The above code gets you factorial of every element in the array.

Related

Getting Time limit Exceed for last 3 Test Cases in a Program:C# [duplicate]

Given an array of n integers and a number, d, perform left rotations on the array. Then print the updated array as a single line of space-separated integers.
Sample Input:
5 4
1 2 3 4 5
The first line contains two space-separated integers denoting the respective values of n (the number of integers) and d (the number of left rotations you must perform).
The second line contains n space-separated integers describing the respective elements of the array's initial state.
Sample Output:
5 1 2 3 4
static void Main(String[] args)
{
string[] arr_temp = Console.ReadLine().Split(' ');
int n = Int32.Parse(arr_temp[0]);
int d = Int32.Parse(arr_temp[1]);
string[] arr = Console.ReadLine().Split(' ');
string[] ans = new string[n];
for (int i = 0; i < n; ++i)
{
ans[(i + n - d) % n] = arr[i];
}
for (int j = 0; j < n; ++j)
{
Console.Write(ans[j] + " ");
}
}
How to use less memory to solve this problem?
This will use less memory in most cases as the second array is only as big as the shift.
public static void Main(string[] args)
{
int[] n = { 1, 2, 3, 4, 5 };
LeftShiftArray(n, 4);
Console.WriteLine(String.Join(",", n));
}
public static void LeftShiftArray<T>(T[] arr, int shift)
{
shift = shift % arr.Length;
T[] buffer = new T[shift];
Array.Copy(arr, buffer, shift);
Array.Copy(arr, shift, arr, 0, arr.Length - shift);
Array.Copy(buffer, 0, arr, arr.Length - shift, shift);
}
This problem can get a bit tricky but also has a simple solution if one is familiar with Queues and Stacks.
All I have to do is define a Queue (which will contain the given array) and a Stack.
Next, I just have to Push the Dequeued index to the stack and Enqueue the Popped index in the Queue and finally return the Queue.
Sounds confusing? Check the code below:
static int[] rotLeft(int[] a, int d) {
Queue<int> queue = new Queue<int>(a);
Stack<int> stack = new Stack<int>();
while(d > 0)
{
stack.Push(queue.Dequeue());
queue.Enqueue(stack.Pop());
d--;
}
return queue.ToArray();
}
Do you really need to physically move anything? If not, you could just shift the index instead.
Actually you asked 2 questions:
How to efficiently rotate an array?
and
How to use less memory to solve this problem?
Usually efficiency and low memory usage are mutually exclusive. So I'm going to answer your second question, still providing the most efficient implementation under that memory constraint.
The following method can be used for both left (passing negative count) or right (passing positive count) rotation. It uses O(1) space (single element) and O(n * min(d, n - d)) array element copy operations (O(min(d, n - d)) array block copy operations). In the worst case scenario it performs O(n / 2) block copy operations.
The algorithm is utilizing the fact that
rotate_left(n, d) == rotate_right(n, n - d)
Here it is:
public static class Algorithms
{
public static void Rotate<T>(this T[] array, int count)
{
if (array == null || array.Length < 2) return;
count %= array.Length;
if (count == 0) return;
int left = count < 0 ? -count : array.Length + count;
int right = count > 0 ? count : array.Length - count;
if (left <= right)
{
for (int i = 0; i < left; i++)
{
var temp = array[0];
Array.Copy(array, 1, array, 0, array.Length - 1);
array[array.Length - 1] = temp;
}
}
else
{
for (int i = 0; i < right; i++)
{
var temp = array[array.Length - 1];
Array.Copy(array, 0, array, 1, array.Length - 1);
array[0] = temp;
}
}
}
}
Sample usage like in your example:
var array = Enumerable.Range(1, 5).ToArray(); // { 1, 2, 3, 4, 5 }
array.Rotate(-4); // { 5, 1, 2, 3, 4 }
Isn't using IEnumerables better? Since It won't perform all of those maths, won't allocate that many arrays, etc
public static int[] Rotate(int[] elements, int numberOfRotations)
{
IEnumerable<int> newEnd = elements.Take(numberOfRotations);
IEnumerable<int> newBegin = elements.Skip(numberOfRotations);
return newBegin.Union(newEnd).ToArray();
}
IF you don't actually need to return an array, you can even remove the .ToArray() and return an IEnumerable
Usage:
void Main()
{
int[] n = { 1, 2, 3, 4, 5 };
int d = 4;
int[] rotated = Rotate(n,d);
Console.WriteLine(String.Join(" ", rotated));
}
I have also tried this and below is my approach...
Thank you
public static int[] RotationOfArray(int[] A, int k)
{
if (A == null || A.Length==0)
return null;
int[] result =new int[A.Length];
int arrayLength=A.Length;
int moveBy = k % arrayLength;
for (int i = 0; i < arrayLength; i++)
{
int tmp = i + moveBy;
if (tmp > arrayLength-1)
{
tmp = + (tmp - arrayLength);
}
result[tmp] = A[i];
}
return result;
}
I have tried to used stack and queue in C# to achieve the output as follows:
public int[] rotateArray(int[] A, int rotate)
{
Queue<int> q = new Queue<int>(A);
Stack<int> s;
while (rotate > 0)
{
s = new Stack<int>(q);
int x = s.Pop();
s = new Stack<int>(s);
s.Push(x);
q = new Queue<int>(s);
rotate--;
}
return q.ToArray();
}
I've solve the challange from Hackerrank by following code. Hope it helps.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace ConsoleApp1
{
class ArrayLeftRotationSolver
{
TextWriter mTextWriter;
public ArrayLeftRotationSolver()
{
mTextWriter = new StreamWriter(#System.Environment.GetEnvironmentVariable("OUTPUT_PATH"), true);
}
public void Solve()
{
string[] nd = Console.ReadLine().Split(' ');
int n = Convert.ToInt32(nd[0]);
int d = Convert.ToInt32(nd[1]);
int[] a = Array.ConvertAll(Console.ReadLine().Split(' '), aTemp => Convert.ToInt32(aTemp))
;
int[] result = rotLeft(a, d);
mTextWriter.WriteLine(string.Join(" ", result));
mTextWriter.Flush();
mTextWriter.Close();
}
private int[] rotLeft(int[] arr, int shift)
{
int n = arr.Length;
shift %= n;
int[] vec = new int[n];
for (int i = 0; i < n; i++)
{
vec[(n + i - shift) % n] = arr[i];
}
return vec;
}
static void Main(string[] args)
{
ArrayLeftRotationSolver solver = new ArrayLeftRotationSolver();
solver.Solve();
}
}
}
Hope this helps.
public static int[] leftrotation(int[] arr, int d)
{
int[] newarr = new int[arr.Length];
var n = arr.Length;
bool isswapped = false;
for (int i = 0; i < n; i++)
{
int index = Math.Abs((i) -d);
if(index == 0)
{
isswapped = true;
}
if (!isswapped)
{
int finalindex = (n) - index;
newarr[finalindex] = arr[i];
}
else
{
newarr[index] = arr[i];
}
}
return newarr;
}
Take the Item at position 0 and add it at the end. remove the item at position 0. repeat n times.
List<int> iList = new List<int>();
private void shift(int n)
{
for (int i = 0; i < n; i++)
{
iList.Add(iList[0]);
iList.RemoveAt(0);
}
}
An old question, but I thought I'd add another possible solution using just one intermediate array (really, 2 if you include the LINQ Take expression). This code rotates to right rather than left, but may be useful nonetheless.
public static Int32[] ArrayRightRotation(Int32[] A, Int32 k)
{
if (A == null)
{
return A;
}
if (!A.Any())
{
return A;
}
if (k % A.Length == 0)
{
return A;
}
if (A.Length == 1)
{
return A;
}
if (A.Distinct().Count() == 1)
{
return A;
}
for (var i = 0; i < k; i++)
{
var intermediateArray = new List<Int32> {A.Last()};
intermediateArray.AddRange(A.Take(A.Length - 1).ToList());
A = intermediateArray.ToArray();
}
return A;
}
O(1) space, O(n) time solution
I think in theory this is as optimal as it gets, since it makes a.Length in-place swaps and 1 temp variable swap per inner loop.
However I suspect O(d) space solutions would be faster in real life due to less code branching (fewer CPU command pipeline resets) and cache locality (mostly sequential access vs in d element steps).
static int[] RotateInplaceLeft(int[] a, int d)
{
var swapCount = 0;
//get canonical/actual d
d = d % a.Length;
if(d < 0) d += a.Length;
if(d == 0) return a;
for (var i = 0; swapCount < a.Length; i++) //we're done after a.Length swaps
{
var dstIdx = i; //we need this becasue of ~this: https://youtu.be/lJ3CD9M3nEQ?t=251
var first = a[i]; //save first element in this group
for (var j = 0; j < a.Length; j++)
{
var srcIdx = (dstIdx + d) % a.Length;
if(srcIdx == i)// circled around
{
a[dstIdx] = first;
swapCount++;
break; //hence we're done with this group
}
a[dstIdx] = a[srcIdx];
dstIdx = srcIdx;
swapCount++;
}
}
return a;
}
If you take a look at constrains you will see that d <= n (number of rotations <= number of elements in array). Because of that this can be solved in 1 line.
static int[] rotLeft(int[] a, int d)
{
return a.Skip(d).Concat(a.Take(d)).ToArray();
}
// using the same same array, and only one temp variable
// shifting everything several times by one
// works, simple, but slow
public static int[] ArrayRotateLeftCyclical(int[] a, int shift)
{
var length = a.Length;
for (int j = 0; j < shift; j++)
{
int t = a[0];
for (int i = 0; i < length; i++)
{
if (i == length - 1)
a[i] = t;
else
a[i] = a[i + 1];
}
}
return a;
}
Let's say if I have a array of integer 'Arr'. To rotate the array 'n' you can do as follows:
static int[] leftRotation(int[] Arr, int n)
{
int tempVariable = 0;
Queue<int> TempQueue = new Queue<int>(a);
for(int i=1;i<=d;i++)
{
tempVariable = TempQueue.Dequeue();
TempQueue.Enqueue(t);
}
return TempQueue.ToArray();`
}
Let me know if any comments. Thanks!
This is my attempt. It is easy, but for some reason it timed out on big chunks of data:
int arrayLength = arr.Length;
int tmpCell = 0;
for (int rotation = 1; rotation <= d; rotation++)
{
for (int i = 0; i < arrayLength; i++)
{
if (arr[i] < arrayElementMinValue || arr[i] > arrayElementMaxValue)
{
throw new ArgumentException($"Array element needs to be between {arrayElementMinValue} and {arrayElementMaxValue}");
}
if (i == 0)
{
tmpCell = arr[0];
arr[0] = arr[1];
}
else if (i == arrayLength - 1)
{
arr[arrayLength - 1] = tmpCell;
}
else
{
arr[i] = arr[i + 1];
}
}
}
what about this?
public static void RotateArrayAndPrint(int[] n, int rotate)
{
for (int i = 1; i <= n.Length; i++)
{
var arrIndex = (i + rotate) > n.Length ? n.Length - (i + rotate) : (i + rotate);
arrIndex = arrIndex < 0 ? arrIndex * -1 : arrIndex;
var output = n[arrIndex-1];
Console.Write(output + " ");
}
}
It's very straight forward answer.
Main thing is how you choose the start index.
public static List<int> rotateLeft(int d, List<int> arr) {
int n = arr.Count;
List<int> t = new List<int>();
int h = d;
for (int j = 0; j < n; j++)
{
if ((j + d) % n == 0)
{
h = 0;
}
t.Add(arr[h]);
h++;
}
return t;
}
using this code, I have successfully submitted to hacker rank problem,
// fast and beautiful method
// reusing the same array
// using small temp array to store replaced values when unavoidable
// a - array, s - shift
public static int[] ArrayRotateLeftWithSmallTempArray(int[] a, int s)
{
var l = a.Length;
var t = new int[s]; // temp array with size s = shift
for (int i = 0; i < l; i++)
{
// save cells which will be replaced by shift
if (i < s)
t[i] = a[i];
if (i + s < l)
a[i] = a[i + s];
else
a[i] = t[i + s - l];
}
return a;
}
https://github.com/sam-klok/ArraysRotation
public static void Rotate(int[] arr, int steps)
{
for (int i = 0; i < steps; i++)
{
int previousValue = arr[arr.Length - 1];
for (int j = 0; j < arr.Length; j++)
{
int currentValue = arr[j];
arr[j] = previousValue;
previousValue = currentValue;
}
}
}
Here is an in-place Rotate implementation of a trick posted by גלעד ברקן in another question. The trick is:
Example, k = 3:
1234567
First reverse in place each of the two sections delineated by n-k:
4321 765
Now reverse the whole array:
5671234
My implementation, based on the Array.Reverse method:
/// <summary>
/// Rotate left for negative k. Rotate right for positive k.
/// </summary>
public static void Rotate<T>(T[] array, int k)
{
ArgumentNullException.ThrowIfNull(array);
k = k % array.Length;
if (k < 0) k += array.Length;
if (k == 0) return;
Debug.Assert(k > 0);
Debug.Assert(k < array.Length);
Array.Reverse(array, 0, array.Length - k);
Array.Reverse(array, array.Length - k, k);
Array.Reverse(array);
}
Live demo.
Output:
Array: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
Rotate(5)
Array: 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7
Rotate(-2)
Array: 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9

Returning array from function (Syntax Error: Value expected)

Why does the program expect me to return array[c] in the below code when c is the length of array minus 1? I can't seem to follow how my program still manages to execute just well.
P.S I arrived at the last line of code by Trial and Error and it worked as expected. I just don't know how!
public static int arrayReverse(int[] array)
{
int c = array.Length - 1, b;
for (int i = 0; i < (array.Length / 2); i++)
{
b = array[i];
array[i] = array[c];
array[c] = b;
c--;
}
return array[c];
}
My main function looks like this:
static void Main(string[] args)
{
int[] array = new int[] { 1, 5, 3, 4, 2 };
//Reverse an Array
arrayReverse(array);
//Display Array Elements
foreach (int x in array)
Console.WriteLine(x);
Console.ReadLine();
}
Because you are returning an int not an int[]. Here, try this out:
public static int[] arrayReverse(int[] array)
{
int c = array.Length - 1, b;
for (int i = 0; i < (array.Length / 2); i++)
{
b = array[i];
array[i] = array[c];
array[c] = b;
c--;
}
return array;
}
Also, you are not assigning back the returned array in main
array = arrayReverse(array);
Now, you do NOT need to return the array at all, since you are writing elements in place and not allocating new array.
Here, please find the code for In-Place and new array implementations. Debug it - write code on paper try to analyze what is happening.
static void Main(string[] args)
{
try
{
int[] array = new int[] { 1, 5, 3, 4, 2 };
//Reverse copy of Array
var newarr = arrayReverseNewArray(array);
//Display New Array Elements
foreach (int x in newarr)
Console.Write(x + ",");
Console.WriteLine("");
//Reverse original Array
arrayReverseinPlace(array);
//Display original Array Elements
foreach (int x in array)
Console.Write(x + ",");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void arrayReverseinPlace(int[] array)
{
for (int i = 0; i < array.Length / 2; i++)
{
int tempvar = array[i];
array[i] = array[array.Length - i - 1];
array[array.Length - i - 1] = tempvar;
}
}
private static int[] arrayReverseNewArray(int[] array)
{
int[] arr = new int[array.Length];
int j = 0;
for (int i = array.Length - 1; i >=0 ; i--)
{
arr[j] = array[i];
j++;
}
return arr;
}
Here is the Running Sample Code.

Summing a jagged int array in C#

As done here: C # Two-dimensional int array,Sum off all elements, but this time with jagged arrays. Getting:
System.IndexOutOfRangeException.
I am a beginner asking for help. This is my code:
public static int Sum(int[][] arr)
{
int total = 0;
for (int i = 0; i < arr.GetLength(0); i++)
{
for (int j = 0; j < arr.GetLength(1); j++)
{
total += arr[i][j];
}
}
return total;
}
static void Main(string[] args)
{
int[][] arr = new int[][]
{
new int [] {1},
new int [] {1,3,-5},
};
int total = Sum(arr);
Console.WriteLine();
Console.ReadKey();
}
In your inner loop do this instead:
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] != null)
{
for (int j = 0; j < arr[i].Length; j++)
{
total += arr[i][j];
}
}
}
return total;
Because your lists aren't even you get the exception on arr.GetLength(1) for the first dimension - it has no item at that place.
The if (arr[i] != null) line is needed in the case the array would look something like:
int[][] arr = new int[][]
{
new int [] {1},
null,
new int [] {1,3,-5},
};
In this case, when we loop with i==1 and try to do arr[i].Length (meaning arr[1].Length we will recieve a NullReferenceException.
And after you do the basics and get to Linq all your current Sum method can be replaced with:
arr.SelectMany(item => item).Sum()
But it is good to start with the basics :)
Since you're using a jagged array the dimensions of that array aren't necessarily even. Have a look at the initialization code of that jagged array:
int[][] arr = new int[][] {
new int [] {1},
new int [] {1,3,-5},
};
So in the first dimension, there are two elements ({1} and {1, 3, -5}). But the second dimension isn't of the same length. The first element has got only one element ({1}) whereas the second element's got 3 elements ({1, 3, -5}).
That's why you're facing the IndexOutOfRangeException.
To fix that, you'll have to adjust the inner loop to the number of elements for that dimension. You can do that like this:
for (int i = 0; i < arr.Length; i++) {
for (int j = 0; j < arr[i].Length; j++) {
total += arr[i][j];
}
}

Simple Windows Application program in C# confusion

My program is messed up bad, and I need help!
I already tried c++, and c# is new for me. Experts here at the university said that c# is like c++, and so I tried to widen my perspective on other programming languages other that c++. I tried to make a program that computes the sum of the lowest 3 numbers in 5 inputted numbers on windows application.
to view the design of the windows application is here:
Design View
and my messed up code:
namespace Array_excercise
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int[] nums = { 0, 0, 0, 0, 0 };
int[] lownum = { 0, 0, 0,0,0 };
int[] highnum = { 0, 0, 0, 0, 0 };
private void computbtn_Click(object sender, EventArgs e)
{
nums[0] = Int32.Parse(textBox1.Text);
nums[1] = Int32.Parse(textBox2.Text);
nums[2] = Int32.Parse(textBox3.Text);
nums[3] = Int32.Parse(textBox4.Text);
nums[4] = Int32.Parse(textBox5.Text);
int result;
for (int a = 0; a <= 4; a++)
{
if (nums[a] < nums[0])
lownum[a] = nums[a];
else if (nums[a] < nums[1])
lownum[a] = nums[a];
else if (nums[a] < nums[2])
lownum[a] = nums[a];
else if (nums[a] < nums[3])
lownum[a] = nums[a];
else if (nums[a] < nums[4])
lownum[a] = nums[a];
else
highnum[a] = nums[a];
}
}
}
After that, I don't know how to compute the sum.
for now, I'm particularly learning how to use arrays with if and for loop functions.
I'll be very grateful if those functions are used in this program.
I thank you in advance!
Use LINQ
var lowSum = nums.OrderBy(n => n).Take(3).Sum();
A one-dimensional array can be sorted with the static Sort() method.
https://msdn.microsoft.com/en-us/library/system.array.sort(v=vs.110).aspx
So in your example, it would go something like:
// populate the array
nums[0] = Int32.Parse(textBox1.Text);
nums[1] = Int32.Parse(textBox2.Text);
nums[2] = Int32.Parse(textBox3.Text);
nums[3] = Int32.Parse(textBox4.Text);
nums[4] = Int32.Parse(textBox5.Text);
// sort the array from lowest to highest
Array.Sort(nums);
// declare a variable to hold the sum
int sum = 0;
// iterate over the first (smallest) three
for(int i=0;i<3; i++)
{
sum += nums[i];
}
Console.WriteLine("The sum of the three smallest is: " + sum);
Try with some sorting algorithms, for example bubble sort to sort your array:
int c = -1;
for (int i = array.Length; i > 1; i--)
{
for (int j = 0; j < i - 1; j++)
{
c = j;
if (array[j] < array[j + 1])
{
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
After you have the sorted array, you can get the sum of the first 3 lowest number:
int sum = 0;
for(int i=0; i < 3; i++)
{
sum += array[i];
}
After putting all the values into "nums". You can set the values of the two arrays using the following code.
List<int> tempnums = nums.ToList(); //Creates a List from "nums" array.
tempnums.Sort(); //Sorts the List from smallest number to highest
int[] lownums = tempnums.ToArray(); //Creates an array from "tempnums" List.
tempnums.Reverse();//Reverses the values of "tempnums" so that the numbers are highest to lowest.
int[] highnums = tempnums.ToArray();//Creates an array from "tempnums" List.
And then there are two ways to get the result.
int result = 0;
for(int i = 1; i <= 3; i++)
{
result += nums[i];
}
Or
int result = nums[0]+nums[1]+nums[2];

Generic initialization of multidimensional array

I have a multidimensional array, which I want to initialize in a simple and fast way:
double[,,] arr = new double[4,5,6];
// doesn't work by design
foreach(double d in arr)
d = ... ; // my initialization value
This obviously doesn't works. But I would like to have a generic function for setting all array values to a choosen default. With own classes, I could write a special constructor, but with value types I've no real idea. With C++, I could access all items in a linear way with one for loop, but in C# I think I've to use as much for loops as I have dimensions. I've no better solution at the moment ( or I'm using unsafe code and pointer arithmetics, which would probably work.).
Is there a more elegant way for doing this ?
Not quite sure if it's what you want, but the following extension method will allow you to initialise every value in an array, regardless of the number of dimensions.
public static class ArrayExtensions
{
public static void Set<T>(this Array array, T defaultValue)
{
int[] indicies = new int[array.Rank];
SetDimension<T>(array, indicies, 0, defaultValue);
}
private static void SetDimension<T>(Array array, int[] indicies, int dimension, T defaultValue)
{
for (int i = 0; i <= array.GetUpperBound(dimension); i++)
{
indicies[dimension] = i;
if (dimension < array.Rank - 1)
SetDimension<T>(array, indicies, dimension + 1, defaultValue);
else
array.SetValue(defaultValue, indicies);
}
}
}
Use like so:
int[, ,] test1 = new int[3, 4, 5];
test1.Set(1);
int[,] test2 = new int[3, 4];
test2.Set(1);
int[] test3 = new int[3];
test3.Set(1);
I would strongly recommend using a 1D array, and map the values sequentially. You will need to convert from indeces i, j, k, ... into the proper array index, which is done with the Que() function below, part of a generic array class SeqArray<T>.
// Test code first
class Program
{
static void Main(string[] args)
{
/* 3 pages, of a 4x2 matrix
*
* |16 17|
* | 8 9|19|
* | 0 1|11|21|
* | 2 3|13|23|
* | 4 5|15|
* | 6 7|
*
* shown above are the sequential indeces for a rank 3 array
*/
SeqArray<double> arr = new SeqArray<double>(3, 4, 2);
// Initialize values to squential index "num"
int num = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 2; k++)
{
arr[i, j, k] = num++;
}
}
}
// Check that the array values correspond to the index sequence
num = 0;
for (int i = 0; i < 3 * 4 * 2; i++)
{
Trace.Assert(arr.InnerArray[i] == num++);
}
// Initialize with value=π
arr = new SeqArray<double>(Math.PI, 4, 5, 6);
}
}
public class SeqArray<T>
{
T[] values;
int[] lengths;
public SeqArray(params int[] lengths)
{
this.lengths = lengths;
int N = 1;
for (int i = 0; i < lengths.Length; i++)
{
N *= lengths[i];
}
values = new T[N];
}
public SeqArray(T value, params int[] lengths) : this(lengths)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = value;
}
}
public int[] Lengths { get { return lengths; } }
public int Size { get { return values.Length; } }
internal T[] InnerArray { get { return values; } }
public int Que(params int[] indeces)
{
// Check if indeces are omited like arr[4] instead of arr[4,0,0]
if (indeces.Length < lengths.Length)
{
// Make a new index array padded with zeros
int[] temp = new int[lengths.Length];
indeces.CopyTo(temp, 0);
indeces = temp;
}
// Count the elements for indeces
int k = 0;
for (int i = 0; i < indeces.Length; i++)
{
k = lengths[i] * k + indeces[i];
}
return k;
}
public T this[params int[] indeces]
{
get { return values[Que(indeces)]; }
set { values[Que(indeces)] = value; }
}
}
Here is a non-recursive version alternative to that posted by Andy Holt above:
public static void SetAll<T>(this Array array, T value)
{
var sizes = new int[array.Rank];
sizes[array.Rank - 1] = 1;
for (var d = array.Rank - 2; d >= 0; d--)
{
sizes[d] = array.GetLength(d + 1)*sizes[d + 1];
}
for (var i = 0; i < array.Length; i++)
{
var remainder = i;
var index = new int[array.Rank];
for (var d = 0; d < array.Rank && remainder > 0; d++)
{
index[d] = remainder / sizes[d];
remainder -= index[d]*sizes[d];
}
array.SetValue(value, index);
}
}

Categories