I'm doing a basic 2D array in C# and I've got a bit of confusion.
I'm a lot more used to working with 1-based arrays, so 0-based arrays kind of mess up my head if you know what I mean.
blocks = new Block[15, 999];
for (int x = 0; x <= 15; x++)
{
for (int y = 0; y <= 999; y++)
{
blocks[x, y] = new Dirt(terrainTexture, new Vector2(x * 16, y * 16));
}
}
So it's telling me I'm out of bounds of the array?
If the array is from
0-15, 0-999
Shouldn't a loop from 0-15, 0-999 work?
It's not. 999 is the length of the array. Thusly, it's from 0-998, and when you loop over it, you should be in the habit of using "less than" rather than "less than or equal" -- then it will tend to come out right.
You have 15 and 999 elements, but since arrays are 0-indexed, that means they run from 0-14 and 0-998, respectively.
Related
I'm working on a multidimensional array in C# and I was wondering whether I can fill two dimensions of a 3 dimensional array using another 2d array. I have two arrays:
byte[,,] thArray = new byte[1000, 1000, 1000];
byte[,] twArray = new byte[1000, 1000];
Now I need to do something like this:
thArray[,,0] = twArray;
Filling any kind of array requires copying. So the trivial answer would be to write a double loop copying each value from twArray to the thArray. Other answers show how to do this already.
However, I might share some experiences using large multidimensional arrays.
For 2D arrays I prefer using a wrapper around a 1D array rather then the built in multidimensional array. This makes some operations faster, and allows for things like using Buffer.BlockCopy for copying large sections, and is usually easier to use when inter operating with other systems. Indexing a value can be done like y*width + x.
Using a custom type also removes the risk of calling .GetLength() in a loop check, since this method is several times slower than checking a regular property. An easy mistake to make, but one that can make loops much slower.
For 3D arrays you could use the same approach, and just add another dimension. But in my experience this tend to be slower than using a jagged array. So I would recommend using something like a byte[][] myArray for a 3D array and index it using myArray[z][y * width + x], preferably with some custom class that can do all this indexing.
You can use 2 for loops to copy the values of the 2-dimensional array to the 3-dimensional array, but leave the 3-dimensional arrays z-value 0:
int height = twArray.GetLength(0);
int width = twArray.GetLength(1);
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
thArray[i, j, 0] = twArray[i, j];
}
}
Yes, you can do it in a good old for loop:
for (int x = 0; x < thArray.GetLength(0); ++x)
for (int y = 0; y < thArray.GetLength(1); ++y)
thArray[x, y, 0] = twArray[x, y];
If you wan to assign in one go you can use byte[][,] thArray - array of 2D arrays:
byte[][,] thArray = new byte[1000][,];
thArray[0] = twArray;
I've created a backtracking algorithm for solving Sudoku puzzles which basicly walks through all the empty fields from left to right, top down respectively. Now I need to make an extended version in which the order in which the algorithm walks through the fields is defined by the amount of possibilities (calculated once, at initialization) for each of the fields. E.g. empty fields which initially have the fewest amount of possible values should be visited first, and only the initially possible values should be checked (both to reduce the amount of iterations needed). Now I'm not sure how to go on implementing this without increasing the amount of iterations needed to actually define these values for each field and then obtain the next field with the fewest possibilities.
For my backtracking algorithm I have a nextPosition method which determines the next empty field in the sudoku to visit. Right now it looks like this:
protected virtual int[] nextPosition(int[] position)
{
int[] nextPosition = new int[2];
if (position[1] == (n * n) - 1)
{
nextPosition[0] = position[0]+1;
nextPosition[1] = 0;
}
else
{
nextPosition[0] = position[0];
nextPosition[1] = position[1]+1;
}
return nextPosition;
}
So it basicly walks through the sudoku left-right, top-down respectively. Now I need to alter this for my new version to walk through the fields ordered by the fewest amount of possible values for the fields (and only trying the possible values for each field in my backtracking algorithm). I figured I'd try to keep a list of invalid values for each field:
public void getInvalidValues(int x, int y)
{
for (int i = 0; i < n * n; i++)
if (grid[y, i] != 0)
this.invalidValues[y, i].Add(grid[y, i]);
for (int i = 0; i < n * n; i++)
if (grid[i, x] == 0)
this.invalidValues[i, x].Add(grid[i, x]);
int nX = (int)Math.Floor((double)x / n);
int nY = (int)Math.Floor((double)y / n);
for (int x = 0; x < n; x++)
for (int y = 0; y < n; y++)
if (grid[nY * n + y, nX * n + x] != 0)
this.invalidValues[y, x].Add(grid[y, x]);
}
Calling this method for every empty field in the sudoku (represented in this.grid as 2D array [nn,nn]). However this causes even more iterations since in order to determine the amount of different invalid values for each field it'll have to walk through each list again.
So my question is whether someone knows a way to efficiently walk through the fields of the sudoku ordered by the amount of possible values for each field (at the same time keeping track of these possible values for each field since they are needed for the backtracking algorithm). If anyone could help me out on this it'd be much appreciated.
Thanks in advance!
I have a need to convert a multi-dimensional double array to a jagged float array. The sizes will var from [2][5] up to around [6][1024].
I was curious how just looping and casting the double to the float would perform and it's not TOO bad, about 225µs for a [2][5] array - here's the code:
const int count = 5;
const int numCh = 2;
double[,] dbl = new double[numCh, count];
float[][] flt = new float[numCh][];
for (int i = 0; i < numCh; i++)
{
flt[i] = new float[count];
for (int j = 0; j < count; j++)
{
flt[i][j] = (float)dbl[i, j];
}
}
However if there are more efficient techniques I'd like to use them. I should mention that I ONLY timed the two nested loops, not the allocations before it.
After experimenting a little more I think 99% of the time is burned on the loops, even without the assignment!
This will run faster, for small data it's not worth doing Parallel.For(0, count, (j) => it actually runs considerably slower for very small data, which is why that I have commented that section out.
double* dp0;
float* fp0;
fixed (double* dp1 = dbl)
{
dp0 = dp1;
float[] newFlt = new float[count];
fixed (float* fp1 = newFlt)
{
fp0 = fp1;
for (int i = 0; i < numCh; i++)
{
//Parallel.For(0, count, (j) =>
for (int j = 0; j < count; j++)
{
fp0[j] = (float)dp0[i * count + j];
}
//});
flt[i] = newFlt.Clone() as float[];
}
}
}
This runs faster because double accessing double arrays [,] is really taxing in .NET due to the array bounds checking. the newFlt.Clone() just means we're not fixing and unfixing new pointers all the time (as there is a slight overhead in doing so)
You will need to run it with the unsafe code tag and compile with /UNSAFE
But really you should be running with data closer to 5000 x 5000 not 5 x 2, if something takes less than 1000 ms you need to either add in more loops or increase the data because at that level a minor spike in cpu activity can add a lot of noise to your profiling.
In your example - I think you dont measure the double/float comparison so much (which should be a processor internal instruction) as the array accesses (which have a lot of redirects plus obviousl.... aray delimiter checks (for the array index of bounds exception).
I would suggest timining a test without arrays.
I don't really think that you can optimize your code much more, one option would be to make your code parallel but for your input data size ([2][5] up to around [6][1024]) I don't thing that you would profit so much if you would even have any profit. In fact, I wouldn't even bother optimizing that piece of code at all...
Anyway, to optimize that, the only thing that I would do (if that fits in what you want to do) would be to just used fixed-width arrays instead of the jagged ones, even if you would waste memory with that.
If you could use also Lists in your case you could use the LINQ approach:
List<List<double>> t = new List<List<double>>();
//adding test data
t.Add(new List<double>() { 12343, 345, 3, 23, 2, 1 });
t.Add(new List<double>() { 43, 123, 3, 54, 233, 1 });
//creating target
List<List<float>> q;
//conversion
q = t.ConvertAll<List<float>>(
(List<double> inList) =>
{
return inList.ConvertAll<float>((double inValue) => { return (float)inValue; });
}
);
if its faster you have to measure yourself. (doubtful)
but you could parallelize it which could fasten it up (PLINQ)
Making game of life I need to a have a grid that is 30x20 (X * Y). The problem is (I had another question regarding to that) that the c# arrays are rows, columns. So when I use CursorPosition() to drawing I need to swap it because it wants column at first.
Is there any way how I can reverse it so I can use like this?
int [,] Array = new int[30,20];
Console.SetCursorPosition(29,19) // now its vice versa, I would need to use 19,29.
I believe that this is purely conceptual (c# arrays are neither row/col or col/row that is up to the developer) and comes down to iterating your array in either a depth-first or breadth-first manner e.g.
//Breadth-first
for(int x = 0; x < col.Length; x++)
{
for(int y = 0; y < row.Length; y++)
{
}
}
//Depth-first
for(int y = 0; y < row.Length; y++)
{
for(int x = 0; x < col.Length; x++)
{
}
}
At first I was inclined to answer no as the parameters to Console.SetCursorPosition is Positional parameters. But when I remember that C# have Named parameters too so something like this works.
int a = 10;
int b = 20;
Console.SetCursorPosition(top: a, left: b);
This is the closest you can get, if you want to know why, search for the terms above
What you need is a data structure to store date in relation with an x,y coordinate.
You do not have to use a multi-dimensional array for this. You could very easily create a class that hides the specific implementation from the other classes.
In fact this will make your design more robust.
You can store the data in a database, bitarray, single dimension array, etc.
I'm trying to write a model containing digital organisms. Within the model i'd liek the environment to be a fixed 2-d array, but each cell needs to contain a list of the organisms in it. I tried using a jagged array, but as the number of occupied elements varies quite a bit throughout the programm run, i need to use something more flexible than an array. I've tried making a 2-D array of the type list, but im getting errors with it.
List<Creature>[,] theWorld;
public Environment()
{
List<Creature>[,] theWorld = new List<Creature>[100,100];
}
public void addCreature(Creature c)
{
for (int x = 0; x < 100; x++)
{
for (int y = 0; y < 100; y++)
{
theWorld[x, y].Add (c);
} } }
this is the segment where i'm trying to declare the array at the beginning, as a type that holds lists (of the organisms), and later i try to add a creature (c) to each of the lists in each element of the array.
when i run it i get the following error message-
"An unhandled exception of type 'System.NullReferenceException' occurred in HGT_sim_2.exe
Additional information: Object reference not set to an instance of an object."
and the line "World[x, y].Add (c);" is highlighted.
If anyone can tell me what i'm doing wrong, and even better, a way around the problem, it'd be amazing.
thank you ain advance!
All your array contains initially is a lot of nulls. You need to actually create the lists...
for(int x = 0 ; x < 100 ; x++)
for(int y = 0 ; y < 100 ; y++)
theWorld[x,y] = new List<Creature>();
Personally, though, I expect this will be a costly way to do things...
It depends in part on whether the data is "sparse" - i.e. are most of the cells usually taken? A simple (but possibly more efficient) approach, for example, would be to use something like multi-map; i.e.
Point pt = new Point(x,y);
theWorld.Add(pt, someCreature);
where theWorld could be something like EditableLookup<Point, Creature> (using EditableLookup<,> from "MiscUtil"). That way, you can still query it by co-ordinate, and have multiple creatures on a coordinate, but you don't have to allocate space for every cell. And because it functions as a dictionary it is still fast. Not as fast as a flat array, but it will scale to bigger (sparse) grids... of course, if the grid has creatures on every cell it could be more expensive! Hence the need to understand your data.
You need to initialize each member of your array, e.g.
for (int x = 0; x < 100; x++)
{
for (int y = 0; y < 100; y++)
{
theWorld[x, y] = new List<Creature>();
} }
Here's the fix:
List<Creature>[,] theWorld;
public Environment()
{
theWorld = new List<Creature>[100,100]; // Remove the type, you were creating a new list and throwing it away...
for(int x = 0 ; x < 100 ; x++)
for(int y = 0 ; y < 100 ; y++)
theWorld[x,y] = new List<Creature>();
}
public void addCreature(Creature c)
{
for (int x = 0; x < 100; x++)
{
for (int y = 0; y < 100; y++)
{
theWorld[x, y].Add (c);
} } }
When you do this:
List<Creature>[,] theWorld = new List<Creature>[100,100];
You're creating an array of List<Creature> references, but they are all empty (pointing to null, not a valid List). You need to initialize each individual element:
for (int x = 0; x < 100; x++) {
for (int y = 0; y < 100; y++) {
theWorld[i,j] = new List<Creature>();
}
}
Once you've done that, you'll be able to call .Add on the individual members.
You're doing it almost correct. Your variable is a 2D array of List<Creature>. Now, List<Creature> is a reference type, so the array is initialized to contain null's in all its members. Thus you get the NullReferenceException. The line
theWorld[x, y].Add (c);
is basically equivalent to
null.Add (c);
All you need to do is to initialize all the members to contain instances of List<Creature>. The best way to do this would be in the constructor. Just rewrite it like this:
public Environment()
{
theWorld = new List<Creature>[100,100];
for(int x = 0 ; x < 100 ; x++)
for(int y = 0 ; y < 100 ; y++)
theWorld[x,y] = new List<Creature>();
}
Now all the operations will work as expected.
Also note, that in your example you are creating a local variable with the same name as the class member. This way you don't initialize the class member at all - it stays null.
You have created the array object to hold your lists, but you haven't created the list itself. You will need to do the following in your constructor:
for (int x = 0; x < 100; x++)
for (int y = 0; y < 100; y++)
theWorld[x,y] = new List<Creature>();
Another problem: you were also defining theWorld as a local variable in your constructor, which means your theWorld field on Environment was never initialized, either.
However, 10,000 Lists may be overkill for what you really need. If your Environment really needs a Creature at every point, and some Creatures may move to other points (where there is more than one at a point, then it may make more sense to use a Dictionary<Point, IList<Creature>> as your model versus 10,000 lists.
public void Add(Creature c, Point at)
{
IList<Creature> list;
if (!theWorld.TryGetValue(at)) {
list = theWorld[at] = new List<Creature>();
}
list.Add(c);
}
You can then implement Move and Remove methods similarly. Also, note that you are adding the same Creature to every point, which (may) mean that there's one Creature at all points in your Environment. You will probably want to create a new Creature() for every point, if that's what you are actually modeling.