I am trying to use a while loop to determine when a process is completed, but in order to establish completion, I must compare the previous run with the current run, so I was setting the comparison array to the original... this apparently is creating some sort of reference because when I change a value in the original "Distinct" array, the value also changes in the "InDistinct" comparison array. How can I prevent/work around this? Otherwise my "while(Distinct!=InDistinct)" is useless.
int[,] Distinct = new int[100, 100]; //Establish Distinct Table
int[,] InDistinct= new int[100,100]; //Comparison Array
//Initialize Distinct table to all 0's (not shown)
while (InDistinct != Distinct)
{
InDistinct = Distinct;
for (int j=0; j < DoIt.Sstates.Length; j++)
{
for (; k < DoIt.Sstates.Length; k++)
{
if (DoIt.Sstates[k] == null)
break;
int w = 0;
for (w = 0; w < DoIt.alphabet.Length;w++)
{
if (DoIt.alphabet[w] == '\0')
break;
if (Distinct[j, k] == 0 && Distinct[jim.tLookup(DoIt, j, DoIt.alphabet[w]), jim.tLookup(DoIt, k, DoIt.alphabet[w])] == 1)
Distinct[j, k] = 1;
else if (Distinct[j, k] == 0 && Distinct[jim.tLookup(DoIt, k, DoIt.alphabet[w]), jim.tLookup(DoIt, j, DoIt.alphabet[w])] == 1)
Distinct[j, k] = 1;`
I ended up initiating the InDistinct array above the While loop and copying the Distinct array to it via nested for loops:
int[,] InDistincta= new int[100,100];
while (InDistincta != Distinct)
{
for (int a = 0; a < 100; a++)
{
for (int b = 0; b < 100; b++)
{
InDistincta[a, b] = Distinct[a, b];
}
Isn't this statement at the beginning of your while loop doing this?
while (InDistinct != Distinct)
{
InDistinct = Distinct;
The condition of your loop is checking if the InDistinct array value is not equal to the Distinct value but then makes the two equal by assigning the InDistinct value to that of the Distinct one immediately after.
Arrays are mechanisms that allow you to treat several items as a
single collection. The Microsoft® .NET Common Language Runtime (CLR)
supports single-dimensional arrays, multidimensional arrays, and
jagged arrays (arrays of arrays). All array types are implicitly
derived from System.Array, which itself is derived from System.Object.
This means that all arrays are always reference types which are
allocated on the managed heap, and your app's variable contains a
reference to the array and not the array itself.
https://msdn.microsoft.com/en-us/library/bb985948.aspx
So you need to change
InDistinct = Distinct;
just because after that line, the two names refers the same object.
try to copy target array into to the InDistinct object
targetArray = new string[sourceArray.Length];
sourceArray.CopyTo( targetArray, 0 );
for multi-dimensional arrays
Array.Copy(sourceArray,targetArray, sourceArray.Length);
Related
I need an array of the same dimensions (to hold values 0 or 1) as an argument to a function which may be of any rank and any type. The result array will contain 0 for failure and 1 for success (I could use Boolean) arising from a process. How can I create the result array?
Use Array.CreateInstance:
private static Array CreateArray(Array array)
{
List<int> dimensions = new List<int>();
for (int i = 0; i < array.Rank; i++)
{
dimensions.Add(array.GetLength(i));
}
return Array.CreateInstance(typeof(bool), dimensions.ToArray());
}
I have following code:
for (int c = 0; c < date_old.Length; c++)
{
for (int d = 0; d < date_new.Length; d++)
{
newList[c] = data_old[c];
if (date_old[c] == date_new[d])
{
newList[c] = data_new[d];
}
}
}
What I'm trying to do is the following:
I have four arrays: date_new, date_old, data_new, data_old and a List called newList.
date_old and data_old have the same length and date_new and data_new too.
I want to loop through the date arrays check if there are equal date values. While I'm doing this, I want to copy every value from the data_old array to newList. When a value is equal, I want to copy the value at this point from the data_new position into the List.
Here I get a OutOfBoundException after the second for loop. What is wrong?
Make sure your newList is instantiated as
var newList = new DateTime[Math.Max(date_old.Length, date_new.Length)];
Also make sure the length of date_old equals the length of data_old, same thing for date_new and data_new.
Move newList[c] = data_old[c]; to the outer for loop if you can (i.e. to line 3), it's gonna overwrite your new data assigned to newList.
This exception is thrown when you try to read/write to an array with an index greater than array.Length -1.
Double-check the size of newList.
for (int c = 0; c < date_old.Length; c++)
{
for (int d = 0; d < date_new.Length; d++)
{
newList.Add((date_old[c] == date_new[d] ? data_new[d] : data_old[c]));
}
}
with your list solution and this logic you provided
I like to create an int[] with length X and value it with [0,1,2....X]
e.g.
public int[] CreateAA(int X){}
int[] AA = CreateAA(9) => [0,1,2,3,4,5,6,7,8,9]
is there any easy method? Or have to loop and init value
You can avail the functionality of IEnumerable.
int[] arr = Enumerable.Range(0, X+1).ToArray();
This will create a IEnumerable List for you and .ToArray() will satisfy your int array need.
So for X=9 in your case it would generate the array for [0,1,2,3,4,5,6,7,8,9] (as you need)
Using Enumerable.Range(0, 10).ToArray() is very concise but if you want to create a very large array the ToArray extension method will have to collect the numbers into a buffer that will have to be reallocated multiple times. On each reallocation the contents of the buffer is copied to the new larger buffer. .NET uses a strategy where the size of the buffer is doubled on each reallocation (and the initial buffer has four items).
So if you want to avoid multiple reallocations of the buffer you need to create the array in advance:
int[] aa = new int[10];
for (var i = 0; i < aa.Length; i += 1)
aa[i] = i;
This is the most efficient way of initializing the array.
However, if you need an array of say 100,000,000 consecutive numbers then you should look at a design where you don't have to keep all the numbers in an array to avoid the impact of the memory requirement. IEnumerable<int> is very useful for this purpose because you don't have to allocate the entire sequence but can produce it while you iterate and that is exactly what Enumerable.Range does. So avoiding the array of consecutive numbers in the first place may be even better than thinking about how to create it.
Why make a function when it is already there.
For this specific example, use
int[] AA = Enumerable.Range(0, 10).ToArray();
where 0 is the starting value and 10 (X + 1) is the length of array
So a general one applicable to all
int[] AA = Enumerable.Range(0, X + 1).ToArray();
with function and loop:
static int[] f(int X)
{
int[] a = new int[X+1];
for(int i = 0; i < a.Length; i++)
a[i] = i;
return a;
}
To initialize try this
int x = 10;
Enumerable.Range(0, x)
.Select((v, i) => v + i).ToArray();
For completeness, here is a function that creates an array.
I made it a bit more versatile by having parameters for the min and max value, i.e. CreateArray(0, 9) returns {0,1,2,3,4,5,6,7,8,9}.
static int[] CreateArray(int min, int max) {
int[] a = new int[max - min + 1];
for (int i = 0; i < a.Length; i++) {
a[i] = min + i;
}
return a;
}
I was having this discussion with my friend who had this question asked to him in the Interview. The Question goes like this. Write a Function which takes in a byte array(2 dimensional) as input along with an Integer n, The initial assumption is all the elements of M*N byte array is zero and the problem is to fill 'n' Byte array elements with value 1, For instance if M=5 and N=5 and the n value is 10 the Byte array should've 10/25 elements to be 1 and rest of the 15 values to be 0. The values filled should be random and one cell in byte array should be filled only once. I was fascinated to try solving this on my own. I've attached the code I've come up with so far.
public Boolean ByteArrayFiller(int a,int b, int n)
{
int count = n;
int iLocalCount = 0;
byte[,] bArray= new byte[a,b];
for (int i = 0; i <a; i++)
for (int j = 1; j <b; j++)
bArray[i, j] = 0;
Random randa= new Random();
int iRandA = randa.Next(a);
int iRandB = randa.Next(b);
while (iLocalCount < n)
{
if (bArray[iRandA, iRandB] == 0)
{
bArray[iRandA, iRandB] = 1;
iLocalCount++;
}
iRandA = randa.Next(a);
iRandB = randa.Next(b);
continue;
}
//do
//{
// //iRandA = randa.Next(a);
// //iRandB = randa.Next(b);
// bArray[iRandA,iRandB]=1;
// iLocalCount++;
//} while (iLocalCount<=count && bArray[iRandA,iRandB]==0);
return true;
}
The code i wrote is in C# but it's straight forward to understand. It's able to do the purpose of the question( I did some trials runs and results came out correctly) perfectly but I have used Random object in C#(Equivalent to Math.Rand in Java) to fill up the byte array and I keep thinking if Rand returns the same values for a and b. There is a good chance for this to go indefinitely. Is that the purpose of the question? or Does the solution that i came up for this question is good enough!
I am curious to see how experts here solve this problem? I am just looking for new ideas to expand my horizon. Any pointers would be greatly appreciated. Thanks for taking the time to read this post!
A while loop trying random locations until it finds a good one is generally a very bad approach. If n = M*N, then the last one will have a probability of 1/(M*N) of finding a match. If M*N are sufficiently large, this can be extremely inefficient.
If M*N is not too large, I would create a temporary array of M*N size, fill it with the numbers 0 through (M*N)-1, and then permutate it - i.e. you walk through it and swap the current value with that of a random other value.
Then you go to the first n elements in your array and set the appropriate cell. (row = value / columns, col = value % columns).
I would treat the array, logically, as a one-dimensional array. Fill the first n positions with the prescribed value, and then shuffle the array.
Given a byte array, and the number of rows and columns in the array, and assuming that the array is already filled with 0:
int NumElements = NumRows * NumCols;
for (int i = 0; i < NumElementsToFill; ++i)
{
int row = i / NumRows;
int col = i % NumCols;
array[row, col] = 1;
}
// Now shuffle the array
Random rnd = new Random();
for (int i = 0; i < NumElements; ++i)
{
int irow = i / NumRows;
int icol = i % NumCols;
int swapWith = rnd.Next(i+1);
int swapRow = swapWith / NumRows;
int swapCol = swapWith % NumCols;
byte temp = array[irow, icol];
array[irow, icol] = array[swapRow, swapCol];
array[swapRow, swapCol] = temp;
}
The key here is converting the one-dimensional index into row/col values. I used / and %. You could also use Math.DivRem. Or create Action methods that do the get and set for you.
Choose a number, which is larger than both N and M and is prime (or co-prime to both N and M). Let's call this number p.
Loop until you've set x numbers:
Generate a random number less than N*M. Call this number `l`.
Then the next place to put the number will be `p*l%(N*M)`, if that position hasn't been set.
A downside to this approach is that if the array is filling up, you'll have more collisions.
Bascially, you need to choose n unique random numbers from range [0, p) (where p = M * N), and map them to positions of 2-dimensional array.
Naive approaches are 1) generate non-unique numbers with retry 2) fill an array with numbers from 0 to p-1, shuffle it and take first n numbers (takes O(p) time, O(p) memory).
Another approach is to choose them with the following algorithm (O(n2) time, O(n) memory, code in Java):
public Set<Integer> chooseUniqueRandomNumbers(int n, int p) {
Set<Integer> choosen = new TreeSet<Integer>();
Random rnd = new Random();
for (int i = 0; i < n; i++) {
// Generate random number from range [0, p - i)
int c = rnd.nextInt(p - i);
// Adjust it as it was choosen from range [0, p) excluding already choosen numbers
Iterator<Integer> it = choosen.iterator();
while (it.hasNext() && it.next() <= c) c++;
choosen.add(c);
}
return choosen;
}
Mapping of generated numbers to positions of 2-dimensional array is trivial.
I need to iterate over an array of arbitrary rank. This is for both reading and writing, so GetEnumerator will not work.
Array.SetValue(object, int) doesn't work on multidimensional arrays.
Array.SetValue(object, params int[]) would require excessive arithmetic for iterating through the multidimensional space. It would also require dynamic invocation to get around the params part of the signature.
I'm tempted to pin the array and iterate over it with a pointer, but I can't find any documentation that says that multidimensional arrays are guaranteed to be contiguous. If they have padding at the end of a dimension then that won't work. I'd also prefer to avoid unsafe code.
Is there an easy way to sequentially address a multidimensional array using only a single index?
Multidimensional arrays are guaranteed to be contiguous. From ECMA-335:
Array elements shall be laid out within the array object in row-major order (i.e., the elements associated with the rightmost array dimension shall be laid out contiguously from lowest to highest index).
So this works:
int[,,,] array = new int[10, 10, 10, 10];
fixed (int* ptr = array)
{
ptr[10] = 42;
}
int result = array[0, 0, 1, 0]; // == 42
You can use the Rank and GetUpperBound property/method to create an indices array that you can pass to the array's SetValue and GetValue methods:
int[] Indices(Array a, int idx)
{
var indices = new int[a.Rank];
for (var i = 0; i < a.Rank; i++)
{
var div = 1;
for (var j = i + 1; j < a.Rank; j++)
{
div *= a.GetLength(j);
}
indices[i] = a.GetLowerBound(i) + idx / div % a.GetLength(i);
}
return indices;
}
..and use it like so:
for (var i = 0; i < array.Length; i++)
{
var indices = Indices(array, i);
array.SetValue(i, indices);
var val = array.GetValue(indices);
}
Perhaps you could join them all into the a single temporary collection, and just iterate over that.