I am making game of life in 2D array. I need to determine when all adjacent cells are empty so I just test all of them. It works well unless the cell being checked is the boundary. Then of course testing X+1 throws an exception as the index is out of the array boundaries. Can I handle this somehow instead of handling the exception?
Thanks
use GetLength(0) and GetLength(1) to get the width and height of the array.
There is also a neat performance trick the runtime uses for its own bounds checks: casting to unsigned int to reduce the two checks into one. But since this costs readability you use it if the check is really performance critical.
(i >= 0) && (i < length)
becomes
(uint)i < length
If you want speed you'll have to treat the edge-cells differently and process the rest with a
for(int x = 1; x < Size-1; x++) // these all have x-1 and x+1 neighbours
I created an extension method for a 2D array to check if in bounds:
public static class ExtensionMethods
{
public static bool In2DArrayBounds(this object[,] array, int x, int y)
{
if (x < array.GetLowerBound(0) ||
x > array.GetUpperBound(0) ||
y < array.GetLowerBound(1) ||
y > array.GetUpperBound(1)) return false;
return true;
}
}
Yes, before accessing the element at index i + 1, check whether i + 1 is strictly inferior to array.Length.
Related
I am doing this problem and struggling so I find this answer:
public class Solution {
public int[][] FloodFill(int[][] image, int sr, int sc, int color) {
if(image[sr][sc] == color) return image;
Fill(image,sr,sc,color,image[sr][sc]);
return image;
}
private void Fill(int[][] image,int x, int y, int color, int oldColor) {
if(x < 0 || y < 0 || x > image.Length - 1 || y > image[x].Length - 1 || image[x][y] == color || image[x][y] != oldColor) return;
image[x][y] = color;
Fill(image,x + 1,y,color,oldColor);
Fill(image,x - 1,y,color,oldColor);
Fill(image,x,y + 1,color,oldColor);
Fill(image,x,y - 1,color,oldColor);
}
}
I understand everything now, except for this part:
y > image[x].Length - 1
What exactly does that mean? I get the boundaries of x > image.Length - 1, but this one confuses me.
I am assuming that it means the boundaries of the xth column, but I would love clarification on this.
Your image seems to be stored as an array of arrays. It's an array of "rows" actually. Note that to access a pixel in the array you have to access image[row][column]. First you access the array at image[row], which is, itself, an array of all the pixels in that row, one for each column. Then you access the pixel at index column in that array. i.e.: (image[row])[column].
My first complaint: You've used the variable names x and y unconventionally. :(
Typically we assign rows the coordinate y and columns the coordinate x so we would expect to have to access image[y][x] But you've done the opposite.
The code provides sr and sc which I assume the letters r=row and c=column. This is corroborated by the quick-escape check: if(image[sr][sc] == color) return image; That sr is intended to be used in the major dimension (first index) and sc is intended to be used in the minor dimension (second index).
You have:
Fill(image,sr,sc,color,image[sr][sc]);
But you then have:
private void Fill(int[][] image,int x, int y, int color, int oldColor) {
So you're passing x = sr and y = sc. That's very confusing / atypical / unconventional / backwards. We usually use y for rows and x for columns.
However, it doesn't matter because you're actually using these variables consistently again by accessing image[x][y]. Which is also backwards, but in this case two wrongs have made a right -- you've bucked convention by swapping labelling and order. Most of us have come to terms with the fact that, with an image that is an array of arrays, we have to write image[y][x]. But you've just swapped the variable names. It means you can write image[x][y], which is appealing, but it's technically confusing for those of us that know better and stick to conventions.
The actual explanation
Setting aside your unconventional/backwards use of x and y,
it's checking y against "the length of the array representing the xth row" or "the number of columns in row x", which is image[x].length.
If y is in range, then y < length. So we test the opposite to conclude that y is out of range. Instead of checking !(y < length) it is logically equivalent to check y >= length or y > length - 1. The last of these is the check you are using. y > image[x].length - 1
The order of these tests is important: if x < 0 or x > image.length - 1 Then the x index is out of bounds and it would be unsafe to even look at the xth row array to see what its length is (the xth row doesn't even exist in that case.) So beware the order of the lazy || checks there. We can be certain that image[x] exists because we've already checked x is in range in the left part of that expression.
Due to lazy evaluation of ||, spelling it out explicitly,
x < 0 || y < 0 || x > image.Length - 1 // it's important this check comes first
|| y > image[x].Length - 1 // it's important this check comes after
is there any better (less complex) way to paste the smaller array[,] to the bigger array[,] than looping through them? My code:
private void PasteRoomIntoTheMap(GameObject[,] room, (int, int) positionOnTheMap)
{
(int, int) roomSize = (room.GetLength(0), room.GetLength(1));
int roomsXAxesDimention = 0;
int roomsYAxesDimention = 0;
for (int i = positionOnTheMap.Item1; i <= positionOnTheMap.Item1 + roomSize.Item1; i++)
{
for (int j = positionOnTheMap.Item2; j <= positionOnTheMap.Item2 + roomSize.Item2; j++)
{
Map[i, j] = room[roomsXAxesDimention, roomsYAxesDimention];
roomsYAxesDimention++;
}
roomsXAxesDimention++;
}
}
(I didn't run it yet. There might be some errors but I hope that you will understand this method)
The code that I would love to have:
Map [5...15, 2...5] = room[0...room.GetLength(0), 0...room.GetLength(1)]
Short answer: No
Longer answer:
Multidimensional arrays are really a wrapper around a 1D array, with some special code to handle indices etc. It does however lack some useful features.
You could perhaps improve your example code a bit by copying entire columns or rows using Array.Copy or blockCopy instead of processing item by item. This might help performance if you have very many items that need copying, but is unlikely to make any difference if the sizes are small.
You could probably provide the syntax you desire by creating something like a ArraySlice2D class that reference the original 2D array as well as the region you want to copy. But you probably need to either create your own wrapper to provide index operators, or create extension methods to do it. Perhaps something like
public class My2DArray<T>{
private T[,] array;
public ArraySlice2D<T> this[Range x, Range y]{
get => new ArraySlice2D<T>(array, x, y);
set {
// Copy values from value.RangeX/Y to x/y ranges
}
}
You might also consider writing your own 2D array class that wraps a 1D array. I find that this often makes interoperability easier since most systems can handle 1D arrays, but few handle multidimensional arrays without conversion.
I am not aware of any shortcut for that and there might be to many slightly distinct usecase so that the most apropriate solution would be to implement your own functionality.
It is advisable however to add a size check to your method so you dont end up indexing nonexisting areas of the big array:
private bool ReplaceWithSubArray(int[,] array, int[,] subarray, (int x,int y) indices)
{
if (array.GetLength(0) < subarray.GetLength(0) + indices.x ||
array.GetLength(1) < subarray.GetLength(1) + indices.y)
{
// 'array' to small
return false;
}
for (int x = 0; x <= subarray.GetLength(0); x++)
{
for (int y = 0; y <= subarray.GetLength(1); y++)
{
array[x + indices.x, y + indices.y] = subarray[x, y];
}
}
return true;
}
I have a 2 dimensional array and what I want to do is search for a specific value around that index(so I want to check array[x-1,y], array[x,y-1] and so on).
My problem is when it will check index which is out of range. Is there someway to check them (I don't want to a lot of IF's checking if x-1 or y-1 is in range of course). I haven't used try/catch a lot yet, and I'm not sure how that works either, but can I ignore the out of range Exception with that? Or is there a better solution for this problem?
If you can't have if you can pre-compute lists of indexes for each cell and iterate over them. I.e. have separate array of the same dimensions that contains lists of index pairs for iteration. Inner elements would have 8 pairs each, corner and border elements would have less (3 and 5 correspondingly).
Alternatively you can use ? : instead of if condition in case restriction is only on syntax and not on condition itself.
I suggest using an extension method for hiding the logic in it (weather with if's or with Math.Max and Math.Min):
public static partial class Array2DExtensions {
public static IEnumerable<T> Vicinity<T>(this T[,] data, int line, int col) {
if (null == data)
throw new ArgumentNullException("data");
//TODO: you may want to add range check here
for (int i = Math.Max(data.GetLowerBound(0), line - 1);
i <= Math.Min(data.GetUpperBound(0), line + 1);
++i)
for (int j = Math.Max(data.GetLowerBound(1), col - 1);
j <= Math.Min(data.GetUpperBound(1), col + 1);
++j)
yield return data[i, j];
}
}
And so you can put something like this:
int[,] sample = ...
...
// Are there any value less than 100 in vicinity of 5, 7 item?
bool found = sample
.Vicinity(5, 7)
.Any(item => item < 100);
You can calculate the safe lower and upper limits for both dimensions and then iterate over the matrix:
// Calculate x range to check
var xl = Math.Max(x-1, 0);
var xu = Math.Min(x+1, array.GetUpperBound(1));
// Calculate y range to check
var yl = Math.Max(y-1, 0);
var yu = Math.Min(y+1, array.GetUpperBound(0));
// Iterate using ranges
for (var j=yl; j <= yu; j++)
for (var i=xl; i <= xu; i++)
// Do the checking
// array[j, i]
I think you'll have to check for each index if it around the array edges.
with the necessary "if's"
if you want to use try and catch it will work,
but you'll have to surround each array access with it's own Try And Catch
(if all will be in same try, once exception was caught the following commands will be skipped)
like this:
try
{
array[x-1,y]
}
catch (ArgumentOutOfRangeException ex)
{
}
try
{
array[x,y-1]
}
catch (ArgumentOutOfRangeException ex)
{
}
etc..
I have an extremely sparse static array with 4 dimensions of 8192 each that I want to do lookups from (C#). Only 68796 of these 4.5 * 10^15 values are non-zero. What is the fastest way to do this, with speed and low memory usage being vital?
Thanks
First, I would argue that plain arrays are quite clearly the wrong kind of data structure for your problem.
How about using a dictionary where you use a 4-tuple as index?
var lookup = new Dictionary<Tuple<int,int,int,int>, int>();
I've never done that myself, but it should work fine. If you don't have Tuple ready because you're working with a version of the .NET Framework preceding .NET 4, you could provide your own index type:
struct LookupKey
{
public readonly int First;
public readonly int Second;
public readonly int Third;
public readonly int Fourth;
…
}
var lookup = new Dictionary<LookupKey, int>();
You could use a plain Dictionary or create a similar map suited for your needs (it will be an array in which you place elements according to an hashvalue you calculate on your 4 values) but you'll need to care about collisions.
Also a binary seach tree can make the trick if you accept a logarithmic complexity for lookup..
Use hashtable (generic Dictionary is already implemented as Hashtable). As key use vector of 4 dimension index. As value store what you want.
What I'd do is use hash lists instead of "normal" arrays for this, then (pseudo-code):
// first, check bounds:
if(x < 0 || y < 0 || z < 0 || w < 0
|| x > xsize || y > ysize || z > zsize || w > wsize)
throw new Whatever(...);
// now return value if != 0
if(x in arr && y in arr[x] && z in arr[x][y] && w in arr[x][y][z])
return arr[x][y][z][w];
else
return 0;
I think the best way is to use a hash-table (Dictionary<T, int>), indexed with a custom struct containing the 4 indexes. Don't forgot to override object.Equals() and object.GetHashCode() on that struct.
Note: I'm optimizing because of past experience and due to profiler software's advice. I realize an alternative optimization would be to call GetNeighbors less often, but that is a secondary issue at the moment.
I have a very simple function described below. In general, I call it within a foreach loop. I call that function a lot (about 100,000 times per second). A while back, I coded a variation of this program in Java and was so disgusted by the speed that I ended up replacing several of the for loops which used it with 4 if statements. Loop unrolling seems ugly, but it did make a noticeable difference in application speed. So, I've come up with a few potential optimizations and thought I would ask for opinions on their merit and for suggestions:
Use four if statements and totally ignore the DRY principle. I am confident this will improve performance based on past experience, but it makes me sad. To clarify, the 4 if statements would be pasted anywhere I called getNeighbors() too frequently and would then have the inside of the foreach block pasted within them.
Memoize the results in some mysterious manner.
Add a "neighbors" property to all squares. Generate its contents at initialization.
Use a code generation utility to turn calls to GetNeighbors into if statements as part of compilation.
public static IEnumerable<Square> GetNeighbors(Model m, Square s)
{
int x = s.X;
int y = s.Y;
if (x > 0) yield return m[x - 1, y];
if (y > 0) yield return m[x, y - 1];
if (x < m.Width - 1) yield return m[x + 1, y];
if (y < m.Height - 1) yield return m[x, y + 1];
yield break;
}
//The property of Model used to get elements.
private Square[,] grid;
//...
public Square this[int x, int y]
{
get
{
return grid[x, y];
}
}
Note: 20% of the time spent by the GetNeighbors function is spent on the call to m.get_Item, the other 80% is spent in the method itself.
Brian,
I've run into similar things in my code.
The two things I've found with C# that helped me the most:
First, don't be afraid necessarily of allocations. C# memory allocations are very, very fast, so allocating an array on the fly can often be faster than making an enumerator. However, whether this will help depends a lot on how you're using the results. The only pitfall I see is that, if you return a fixed size array (4), you're going to have to check for edge cases in the routine that's using your results.
Depending on how large your matrix of Squares is in your model, you may be better off doing 1 check up front to see if you're on the edge, and if not, precomputing the full array and returning it. If you're on an edge, you can handle those special cases separately (make a 1 or 2 element array as appropriate). This would put one larger statement in there, but that is often faster in my experience. If the model is large, I would avoid precomputing all of the neighbors. The overhead in the Squares may outweigh the benefits.
In my experience, as well, preallocating and returning vs. using yield makes the JIT more likely to inline your function, which can make a big difference in speed. If you can take advantage of the IEnumerable results and you are not always using every returned element, that is better, but otherwise, precomputing may be faster.
The other thing to consider - I don't know what information is saved in Square in your case, but if hte object is relatively small, and being used in a large matrix and iterated over many, many times, consider making it a struct. I had a routine similar to this (called hundreds of thousands or millions of times in a loop), and changing the class to a struct, in my case, sped up the routine by over 40%. This is assuming you're using .net 3.5sp1, though, as the JIT does many more optimizations on structs in the latest release.
There are other potential pitfalls to switching to struct vs. class, of course, but it can have huge performance impacts.
I'd suggest making an array of Squares (capacity four) and returning that instead. I would be very suspicious about using iterators in a performance-sensitive context. For example:
// could return IEnumerable<Square> still instead if you preferred.
public static Square[] GetNeighbors(Model m, Square s)
{
int x = s.X, y = s.Y, i = 0;
var result = new Square[4];
if (x > 0) result[i++] = m[x - 1, y];
if (y > 0) result[i++] = m[x, y - 1];
if (x < m.Width - 1) result[i++] = m[x + 1, y];
if (y < m.Height - 1) result[i++] = m[x, y + 1];
return result;
}
I wouldn't be surprised if that's much faster.
I'm on a slippery slope, so insert disclaimer here.
I'd go with option 3. Fill in the neighbor references lazily and you've got a kind of memoization.
ANother kind of memoization would be to return an array instead of a lazy IEnumerable, and GetNeighbors becomes a pure function that is trivial to memoize. This amounts roughly to option 3 though.
In any case, but you know this, profile and re-evaluate every step of the way. I am for example unsure about the tradeoff between the lazy IEnumerable or returning an array of results directly. (you avoid some indirections but need an allocation).
Why not make the Square class responsible of returning it's neighbours? Then you have an excellent place to do lazy initialisation without the extra overhead of memoization.
public class Square {
private Model _model;
private int _x;
private int _y;
private Square[] _neightbours;
public Square(Model model, int x, int y) {
_model = model;
_x = x;
_y = y;
_neightbours = null;
}
public Square[] Neighbours {
get {
if (_neightbours == null) {
_neighbours = GetNeighbours();
}
return _neighbours;
}
}
private Square[] GetNeightbours() {
int len = 4;
if (_x == 0) len--;
if (_x == _model.Width - 1) len--;
if (_y == 0) len--;
if (-y == _model.Height -1) len--;
Square [] result = new Square(len);
int i = 0;
if (_x > 0) {
result[i++] = _model[_x - 1,_y];
}
if (_x < _model.Width - 1) {
result[i++] = _model[_x + 1,_y];
}
if (_y > 0) {
result[i++] = _model[_x,_y - 1];
}
if (_y < _model.Height - 1) {
result[i++] = _model[_x,_y + 1];
}
return result;
}
}
Depending on the use of GetNeighbors, maybe some inversion of control could help:
public static void DoOnNeighbors(Model m, Square s, Action<s> action) {
int x = s.X;
int y = s.Y;
if (x > 0) action(m[x - 1, y]);
if (y > 0) action(m[x, y - 1]);
if (x < m.Width - 1) action(m[x + 1, y]);
if (y < m.Height - 1) action(m[x, y + 1]);
}
But I'm not sure, if this has better performance.