I have this array here:
float[, ,] vectors;
int pos = 0;
void Start() {
vectors = new float[,,] { {
{ 0, 1, 1 },
{ 0, 2, 2 } }
};
}
This works. I fill the array with numbers.
Now I want to add some values again to a given position. But how?
This are not working:
vectors[pos] = new float[,,] { { { 33, 44, 55 } } };
or
vectors[pos] = { { { 33, 44, 55 } } };
I searched, but not found the right answer.
EDIT:
I want something like this:
[0]+
[0] {1, 2, 3},
[1] {4, 5, 6}
[1]+
[0] {11, 22, 33},
[1] {44, 55, 66},
[2] {77, 88, 99}
...
etc.
Now, e.g. I want add values {10,10,10} to pos = 0. But how?
If you want to add values I suggest using generic lists instead of arrays. And you should create your own Vector class or find one that is suitable to your needs like this.
public class Vector
{
public float X { get; private set; }
public float Y { get; private set; }
public float Z { get; private set; }
public Vector(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
}
Then you can do the following
var vectors = new List<List<Vector>>
{
new List<Vector>{
new Vector(0, 1, 1),
new Vector(0, 2, 2)
}
};
vectors[0].Add(new Vector(33,44,55));
And your vectors will contain
[0]
[0] {0, 1, 1}
[1] {0, 2, 2}
[2] {33, 44, 55}
Note that if you need to add to the first dimention you have to do this.
vectors.Add(new List<Vector>());
vectors[1].Add(new Vector(1, 2, 3));
And now you have
[0]
[0] {0, 1, 1}
[1] {0, 2, 2}
[2] {33, 44, 55}
[1]
[0] {1, 2, 3}
You should determine the other positions within the array, you are just specifying one. If your problem cannot be solved within lists
you can try array of arrays as follows
float [][][] x = new float [n][m][];
// initialize the third dimension until m is reached
x[0] = new float {1,2,3,4,5}; // specify whatever value you want
x[1] = new float {3,2,4};
x[2] = new float [3];
// etc until m is reached
// do the same for the n dimension
This will work for you, the array is assigned, you cannot change it you must expand the array as is.
float[, ,] vectors;
int pos = 0;
vectors = new float[,,]
{
{
{ 0, 1, 2 }, { 0, 3, 4 }
}
};
vectors = new float[,,]
{
{
{vectors[0,0,0], vectors[0,0,1], vectors[0,0,2]}, { vectors[0,1,0], vectors[0,1,1], vectors[0,1,2] }, { 33,44,55}
}
};
Related
I am trying to implement VRPTW of Google OR-Tools. But I am facing an issue. When I pass the dynamic Time matrix then the solution object is null but when I pass the Time matrix which is given in example then it worked.
Here is my code
public class DataModel
{
public long[,] DistanceMatrix { get; set; }
public long[,] TimeMatrix = {
//commented matrix is dynamic generated
// {0,5,20,10,0,5},
//{5,0,25,10,5,5},
//{20,25,0,30,20,20},
//{10,10,30,0,10,15},
//{0,5,20,10,0,5},
//{5,5,20,15,5,0},
{0, 6, 9, 8, 7, 3},
{6, 0, 8, 3, 2, 6},
{9, 8, 0, 11, 10, 6},
{8, 3, 11, 0, 1, 7},
{7, 2, 10, 1, 0, 6},
{3, 6, 6, 7, 6, 0},
};
public long[,] TimeWindows = {
{0, 5}, // depot
{7, 12}, // 1
{10, 15}, // 2
{16, 18}, // 3
{10, 13}, // 4
{0, 5}, // 5
};
public int VehicleNumber = 3;
public int Depot = 0;
};
Here is the main function code
DataModel data = new DataModel();
// data.TimeMatrix = TimeMatrix;
// Create Routing Index Manager
RoutingIndexManager manager = new RoutingIndexManager(
data.TimeMatrix.GetLength(0),
data.VehicleNumber,
data.Depot);
// Create a Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create and register a transit callback.
int transitCallbackIndex = routing.RegisterTransitCallback(
(long fromIndex, long toIndex) =>
{
// Convert from routing variable Index to distance matrix NodeIndex.
var fromNode = manager.IndexToNode(fromIndex);
var toNode = manager.IndexToNode(toIndex);
return data.TimeMatrix[fromNode, toNode];
}
);
// Define the cost of each arc.
routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Add Distance constraint.
routing.AddDimension(
transitCallbackIndex, // transit callback
30, // allow waiting time
30, // vehicle maximum capacities
false, // start cumul to zero
"Time");
RoutingDimension timeDimension = routing.GetMutableDimension("Time");
// Add time window constraints for each location except depot.
for (int i = 1; i < data.TimeWindows.GetLength(0); ++i)
{
long index = manager.NodeToIndex(i);
timeDimension.CumulVar(index).SetRange(
data.TimeWindows[i, 0],
data.TimeWindows[i, 1]);
}
// Add time window constraints for each vehicle start node.
for (int i = 0; i < data.VehicleNumber; ++i)
{
long index = routing.Start(i);
timeDimension.CumulVar(index).SetRange(
data.TimeWindows[0, 0],
data.TimeWindows[0, 1]);
}
// Instantiate route start and end times to produce feasible times.
for (int i = 0; i < data.VehicleNumber; ++i)
{
routing.AddVariableMinimizedByFinalizer(
timeDimension.CumulVar(routing.Start(i)));
routing.AddVariableMinimizedByFinalizer(
timeDimension.CumulVar(routing.End(i)));
}
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
operations_research_constraint_solver.DefaultRoutingSearchParameters();
searchParameters.FirstSolutionStrategy =
FirstSolutionStrategy.Types.Value.PathCheapestArc;
// Solve the problem.
Assignment solution = routing.SolveWithParameters(searchParameters); //it is null when dynamic time matrix is used, but it is not null when time matrix mentioned in example is used.
The problem seems to be in AddDimension Method. I am struck in this but could not find any solution. Please suggest any solution.
Solution is null indicates that the solver was not able to find any feasible solution. Most likely your time windows are too tight.
Either try relaxing your time windows
or make sure nodes are optional (using addDisjunction).
Given 2 dimensional:
int[,] arr2d = new int[3,3]
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
Objective: Print the 2d array in the given triangle pattern so it appears as below:
I thought this is print along its main diagonal.
.
In the example case, we list the indices of arr2d:
(0, 2)
(0, 1), (1, 2)
(0, 0), (1, 1), (2, 2)
(1, 0), (2, 1)
(2, 0)
See the regular pattern?
In the first 3 lines, the x of first element on each line remains 0, and the y decreases.
In the last 3 lines, the y of first element on each line remains 0, and the x increases.
In each line, next element relative to previous is (x++, y++), until either x or y ≥3.
For more general way, a n dimensional matrix has 2n-1 line of trangle.
In the first n lines, the x of first element remains to 0, the y decreases.
In the last n lines, the y of first element remains to 0, the x increases.
For each line, print (x++, y++) until either x or y ≥3.
Here's the code:
static void Main(string[] args) {
int[,] arr2d = new int[3,3]
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int dimension = 3;
int x = 0, y = dimension - 1
while(y >= 0) {
WriteDiagalNumbers(arr2d, x, y, dimension);
y--;
// or shorten as
// WriteDiagalNumbers(arr2d, x, y--, dimension);
}
x = 1;
y = 0;
while(x < dimension) {
WriteDiagalNumbers(arr2d, x, y, dimension);
x++;
// or shorten as
// WriteDiagalNumbers(arr2d, x++, y, dimension);
}
}
static void WriteDiagalNumbers(int[,] arr, int x, int y, int dimension) {
List<int> nums = new List<int>();
while(x < dimension && y < dimension) {
nums.Add(arr[x, y]);
x++;
y++;
// or shorten as
// nums.Add(arr[x++, y++]);
}
Console.WriteLine(string.Join(", ", nums));
}
Gives the output:
3
2, 6
1, 5, 9
4, 8
7
I like Sheey's answer, though it bothers me that the array dimensions are hard-coded in that solution. So here's a generic approach using GetUpperBound() to determine the number of rows/columns.
Calling GetUpperBound(0) would tell you how many ROWS, while GetUpperBound(1) would give the number of COLUMNS.
We can get the coordinates of all the diagonal starting positions by starting in the upper right corner of the array and moving left. Once we hit the left side we travel down the array. From each of those starting positions we get the diagonal values by incrementing both of the starting x/y positions while they are within the bounds of the array. This is one of those rare occasions where a for loop with multiple variables can be used.
The code also pads the output based on the largest value so that the triangle can handle any size integers.
Note that when accessing a 2D array, the x and y parameters are reversed:
arr[y, x]
You list the y value as the first parameter, and the x value as the second parameter.
So with this array:
int[,] arr2d = new int[,]
{
{85, 86, 87, 88},
{89, 90, 91, 92},
{93, 94, 95, 96},
{97, 98, 99, 100}
}
The 88 value, using zero based notation, would be normally thought of as at coordinates (2, 0), but would be accessed with arr2d[0, 2].
Similarly, the 97 value would be normally thought of as at coordinates (0, 2), but would be accessed with arr2d[2, 0].
I felt this approach was different enough to warrant an additional answer to the question:
static void Main(string[] args)
{
int[,] arr2d = new int[,]
{
{85, 86, 87, 88},
{89, 90, 91, 92},
{93, 94, 95, 96},
{97, 98, 99, 100}
};
printTriangle(arr2d);
Console.Write("Press Enter to quit...");
Console.ReadLine();
}
static void printTriangle(int[,] arr)
{
// Get all the starting positions for "diagonals":
// Start in the top right of the array,
// then move all the way left,
// followed by all the way down.
int y = 0;
int x = arr.GetUpperBound(1);
bool travelLeft = true;
bool triangleComplete = false;
List<string> diagonalValues = new List<string>();
int pad = arr.Cast<int>().Max().ToString().Length;
while (!triangleComplete)
{
diagonalValues.Clear();
for(int yTemp = y, xTemp = x;
xTemp <= arr.GetUpperBound(1) && yTemp <= arr.GetUpperBound(0);
xTemp++, yTemp++)
{
diagonalValues.Add(arr[yTemp, xTemp].ToString().PadLeft(pad));
}
Console.WriteLine(String.Join(", ", diagonalValues));
if (travelLeft)
{
x--; // move left
travelLeft = (x > 0);
}
else
{
y++; // move down
triangleComplete = (y > arr.GetUpperBound(1));
}
}
}
Output:
88
87, 92
86, 91, 96
85, 90, 95, 100
89, 94, 99
93, 98
97
Press Enter to quit...
this is my first post.
I'm taking a programming course right now and my current assignment is to create an integer (we will call it the ant) which will move around to all integers in a 2d array (randomized path). Here is my code thus far:
namespace Ant
{
class Program
{
static void Main(string[] args)
{
int ant;
int i = 0;
int[,] numberGrid =
{
{1, 2},
{3, 4},
{5, 6},
{7, 8},
{9, 10},
{10, 11},
{11, 12},
{13, 14},
{15, 16},
{17, 18},
{19, 20},
};
do
{
Random rand = new Random();
ant= rand.Next(numberGrid[10, 1]);
Console.WriteLine(ant);
i++;
} while (i !=110);
Console.WriteLine("It took {0} steps for the ant to cover all spaces!", i);
}
}
}
I have the 2d array and I have temporarily set the ant up for a randomized path which will go on for 110 times before it stops. I'm supposed to integrate struct into this so that the ant will only go until it has visited all the integers of the 2d array instead of a set amount of times, but I'm absolutely clueless as to how I'm supposed to do this. If anyone could help me understand that would be great, thank you!
Without more detail of how your expected to do this it sounds like you need to make the Ant a struct and record where the Ant has been (or not been). Here's a way you could do it, though I'm sure performance-wise there's a better way:
static void Main(string[] args)
{
var unvisitedSpaces = new List<Coordinates>
{
//I've used your numbers but should this be a full matrix i.e. [1,1], [1,2], [1,3] etc.?
new Coordinates(1, 2),
new Coordinates(3, 4),
new Coordinates(5, 6),
new Coordinates(7, 8),
new Coordinates(9, 10),
new Coordinates(11, 12),
new Coordinates(13, 14),
new Coordinates(15, 16),
new Coordinates(17, 18),
new Coordinates(19, 20)
};
var ant = new Ant();
int counter = 0;
var r = new Random();
var min = Math.Min(unvisitedSpaces.Min(x => x.X), unvisitedSpaces.Min(y => y.Y));
var max = Math.Max(unvisitedSpaces.Max(x => x.X), unvisitedSpaces.Max(y => y.Y)) + 1;
do
{
ant.X = r.Next(min, max);
ant.Y = r.Next(min, max);
counter++;
//check if the ant hasn't visited this space by checking the unvisitedSpaces list.
if (unvisitedSpaces.Any(c => c.X == ant.X && c.Y == ant.Y))
{
//if it hasn't visited (the list contains that set of coordinates) then remove it from the list as it's now visited it.
var coord = unvisitedSpaces.FirstOrDefault(c => c.X == ant.X && c.Y == ant.Y);
unvisitedSpaces.Remove(coord);
}
} while (unvisitedSpaces.Count() > 0);
Console.WriteLine("It took {0} steps for the ant to cover all spaces!", counter);
Console.ReadLine();
}
public struct Coordinates
{
public int X { get; }
public int Y { get; }
public Coordinates(int x, int y)
{
X = x;
Y = y;
}
}
public struct Ant
{
public int X { get; set; }
public int Y { get; set; }
}
Result:
UPDATE
Added in the ability for it to automatically adjust the max and min values to be used by the 'random' by getting them from the coordinates matrix. Any adjustments to the matrix should therefore be included in the spaces the 'Ant' visits.
I wonder if it is possible to implement a general Julia\Matlab alike View function in C# that would work for arrays of any dimensions (eg [,,] and [,,,]) as they do it in array slicer\mover view. So I wonder if there is a library that provides similar functionality for CSharp multidimentional arrays or how to implement it in C#?
The solution is twofold:
Use a wrapper class that holds a reference to the master array
Use the Array base class to make it polymorphic
Wrapper
class View<T>
{
private readonly Array array;
private readonly int dim;
private readonly int slice;
public View(Array array, int dim, int slice)
{
this.array = array;
this.dim = dim;
this.slice = slice;
}
public T this[params int[] indexes]
{
get { return (T)array.GetValue(BaseIndexesFor(indexes)); }
set { array.SetValue(value, BaseIndexesFor(indexes)); }
}
private int[] BaseIndexesFor(int[] indexes)
{
if (indexes.Length != array.Rank - 1) throw new ArgumentException("indexes");
int i_index = 0;
int[] baseIndexes = new int[array.Rank];
for (int i = 0; i < baseIndexes.Length; i++)
{
baseIndexes[i] = (i == dim) ? slice : indexes[i_index++];
}
return baseIndexes;
}
}
2D example
var A = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
/* View(Array array, int dim, int slice)
*
* For 2 dimensional array:
* dim=0 -> rows
* dim=1 -> columns
*/
// From second dimension slice index 1
// Or simply, take column with index 1
var B = new View<int>(A, 1, 1);
B[2] = 0;
Console.WriteLine(A[2, 1]); // 0
3D examples
var C = new int[,,]
{
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
},
{
{ 11, 12, 13 },
{ 14, 15, 16 },
{ 17, 18, 19 }
},
{
{ 21, 22, 23 },
{ 24, 25, 26 },
{ 27, 28, 29 }
}
};
/* From first dimension slice index 2
* { 21, 22, 23 },
* { 24, 25, 26 },
* { 27, 28, 29 }
*/
var D = new View<int>(C, 0, 2);
D[1, 1] = 0;
Console.WriteLine(C[2, 1, 1]); // 0
/* From third dimension slice index 0
* { 1, 4, 7 },
* { 11, 14, 17 },
* { 21, 24, 27 }
*/
var E = new View<int>(C, 2, 0);
E[2, 0] = 0;
Console.WriteLine(C[2, 0, 0]); // 0
I am not C# expert, and total LINQ beginner, having searched a bit in SO and Google without discovering how to do the following:
If I have, say, int[10,10] array, how can I get a 2D slice from it?
For example, if the values in the said array were dependent on their position (a[2,3] = 23, a[4,8] = 48, etc.), I'd like to perform the following pseudocode:
int[3,3] a_slice = slicer_method(a, 3, 6, 2, 5) // or anything equivalent to this
> [[ 32, 33, 34],
[ 42, 43, 44],
[ 52, 53, 54]]
It doesn't have specifically to use LINQ, but I've seen LINQ used in every similar operation I've come across lately.
#JaredPar is correct, there is no intrinsic way to do slices - that said, you can craft up an extension method to do so:
public static class Ext
{
public static T[] Slice<T>(this T[] source, int fromIdx, int toIdx)
{
T[] ret = new T[toIdx - fromIdx + 1];
for(int srcIdx=fromIdx, dstIdx = 0; srcIdx <= toIdx; srcIdx++)
{
ret[dstIdx++] = source[srcIdx];
}
return ret;
}
public static T[,] Slice<T>(this T[,] source, int fromIdxRank0, int toIdxRank0, int fromIdxRank1, int toIdxRank1)
{
T[,] ret = new T[toIdxRank0 - fromIdxRank0 + 1, toIdxRank1 - fromIdxRank1 + 1];
for(int srcIdxRank0=fromIdxRank0, dstIdxRank0 = 0; srcIdxRank0 <= toIdxRank0; srcIdxRank0++, dstIdxRank0++)
{
for(int srcIdxRank1=fromIdxRank1, dstIdxRank1 = 0; srcIdxRank1 <= toIdxRank1; srcIdxRank1++, dstIdxRank1++)
{
ret[dstIdxRank0, dstIdxRank1] = source[srcIdxRank0, srcIdxRank1];
}
}
return ret;
}
}
And a test:
void Main()
{
var singleArr = new int[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
singleArr.Slice(2, 4).Dump();
var doubleArr = new int[,]
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
};
doubleArr.Slice(2, 4, 2, 4).Dump();
}
There is no way to do this on the CLR because it doesn't support the notion of array slices. They best you can do is create a wrapper type over arrays that simulates slices
You can try something like this:
public T[,] Slice<T>(T[,] a, int x1, int y1, int x2, int y2)
{
var result = new T[x2 - x1, y2 - y1];
for (var i = x1; i < x2; i++)
{
for (var j = y1; j < y2; j++)
{
result[i - x1, j - y1] = a[i,j];
}
}
return result;
}
sample
public class MyArraySlice<T> where T:struct {
public MyArraySlice(T[,] array, int xMin, int xMax, int yMin, int yMax) {
Array = array;
XMin = xMin; XMax = xMax;
YMin = yMin; YMax = yMax;
}
public T this[int i, int j] { get {
if (XMin <= i && i < XMax && YMin <= j && j < YMax)
return Array[i+XMin, j+YMin];
throw new ArgumentOutOfRangeException();
}
}
T[,] Array;
int XMin;
int XMax;
int YMin;
int YMax;
}