(If you can think of a better title, please let me know.)
I’m working on a route optimization program. I'm starting with a list of points which the route needs to include. My first step is to create a list of all possible routes (permutations). I then remove any route I can (for example, if one stop must precede another). Once that's done I calculate the distance and time between each point, in each possible route. Each point is an object (TPoint) and all the distance and time values are stored in a separate class called TData, which is stored in each instance of TPoint. My problem is this: when I try to update the TData in, say, the first stop, in the first possible route it will update the TData for that same TPoint in each possible route. This is because the class is a reference type and is stored on the heap. I’m looking for a solution that allows me to store the TData on each TPoint.
Here's some example code (the following code demonstrates how when I modify one object (TPoint), I'm only actually using the reference to modify the object on the heap):
Main
// Let's create a list of points we need to hit.
List<TPoint> lstInitial = new List<TPoint>();
lstInitial.Add(new TPoint("A", new TData(-1, -1)));
lstInitial.Add(new TPoint("B", new TData(-1, -1)));
lstInitial.Add(new TPoint("C", new TData(-1, -1)));
// Now let's get all possible routes
IList<IList<TPoint>> lstPermutations = Permutations(lstInitial);
// Let's write these values to the first point, in the first possible route.
lstPermutations[0][0].oTData.distance = 10;
lstPermutations[0][0].oTData.minutes = 20;
foreach (IList<TPoint> perm in lstPermutations)
{
foreach (TPoint p in perm)
{
Response.Write(p.id + "|" + p.oTData.distance + "|" + p.oTData.minutes);
Response.Write(" ");
}
Response.Write("<br />");
}
Permutation Function
// Get permutations
private static IList<IList<T>> Permutations<T>(IList<T> list)
{
List<IList<T>> perms = new List<IList<T>>();
// If the list is empty, return an empty list.
if (list.Count == 0)
{
return perms;
}
// This is a loop method to get the factorial of an integer
int factorial = 1;
for (int i = 2; i <= list.Count; i++)
{
// shortcut for: factorial = factorial * i;
factorial *= i;
}
for (int v = 0; v < factorial; v++)
{
//List<T> s = new List<T>(list);
List<T> s = new List<T>(list);
int k = v;
for (int j = 2; j <= list.Count; j++)
{
int other = (k % j);
T temp = s[j - 1];
s[j - 1] = s[other];
s[other] = temp;
k = k / j;
}
perms.Add(s);
}
return perms;
}
Classes
public class TPoint
{
public TPoint(string _id, TData _oTData)
{
id = _id;
oTData = _oTData;
}
public string id { get; set; }
public int someInt { get; set; }
public TData oTData { get; set; }
}
public class TData
{
public TData(int _distance, int _minutes)
{
distance = _distance;
minutes = _minutes;
}
public int distance { get; set; }
public int minutes { get; set; }
}
It kind of seems as if I've managed to paint myself into a corner. I can think of a few solutions, but they seem messy so I figured I'd ask the experts on this one.
Edit
Can anyone think of why this wouldn't be a good idea?
Instead of this, which modifies the object on the heap (and affects every point in each possible route):
lstPermutations[0][0].oTData.distance = 10;
lstPermutations[0][0].oTData.minutes = 20;
Use this, which just creates a new instance of the class:
TPoint oTPoint = new TPoint(lstPermutations[0][0].id, new TData(10, 20));
lstPermutations[0][0] = oTPoint;
If you make TData a struct then it will be copied by value and not by reference. Otherwise you'll have to make a shallow clone which copies values.
Why not make your simple TData type immutable by removing the set accessors, so that it won't matter much if it is copied by value or copied by reference. It could be functionally equivalent to Tuple<int, int>.
Whether the object is stored on the heap or somewhere else is probably unimportant. If you decide to make the object immutable, it will be natural to make it a struct, though, but a class is also fine.
Related
I have a multidimensional array with five countries and some medals. The last column is the total and i need to return the country with most medals. My code is "working" as long as there are no two countries with the same number of medals and those being the max number.
Problably i just don't have enough experience with arrays, but how can i return more than one contry, if i need?
string [,] medals = new string[5, 5];
Random rdn = new Random();
medals[0, 0] = "Brazil";
medals[1, 0] = "USA";
medals[2, 0] = "Russia";
medals[3, 0] = "France";
medals[4, 0] = "Egypt";
for (int i = 0; i < medals.GetLength(0); i++)
for (int j = 1; j < medals.GetLength(1); j++)
{
//This fills the gold, silver and copper medals
if (j < medals.GetLength(1)-1)
medals[i, j] = rdn.Next(1, 6).ToString();
else
//This fills the total medals
medals[i, j] = (int.Parse(medals[i, 1]) + int.Parse(medals[i,2]) + int.Parse(medals[i,3])).ToString();
}
//The first index stores the max number so far and the second stores the name of the country
string [] winner = { "0", "0" };
for (int i = 0; i < medals.GetLength(0); i++)
{
if (int.Parse(medals[i,4]) > int.Parse(winner[0]))
{
winner[0] = medals[i, 4];
winner[1] = medals[i, 0];
}
}
You could use a list to store the winners.
var listWinners = new List<KeyValuePair<string,string>>();
for (int i = 0; i < medals.GetLength(0); i++)
{
if ((listWinners.Count() == 0)||(int.Parse(medals[i,4]) > int.Parse(listWinners.First().Value)))
{
listWinners.Clear();
listWinners.Add(new KeyValuePair<string,string>(medals[i,0],medals[i,4]));
}
else if (int.Parse(medals[i,4]) == int.Parse(listWinners.First().Value))
{
listWinners.Add(new KeyValuePair<string,string>(medals[i,0],medals[i,4]));
}
}
But I would like reiterate what has been said in the comments, it would be much better if you could use a List of Object rather than multi-dimentional array. It would increase your readability of code and make things much simpler.
A dictionary would be a much easier starting place. You could then just sort based on the values in the dict and use a simple loop to check for duplicate values.
There are a lot of things I would do differently than you, but that's besides the point (see note at the end). Your issue is how to deal with the situation where you have multiple countries with equal and max number of medals.
How to return multiple countries?
Well, that's easy: imagine you return the winner from the below function:
string[] GetWinner() {
// your code
return new[] { "20", "USA" };
}
Then there is no change in the data type, simply add another country to the array and the calling code should check how many you have
string[] GetWinner() {
// your code
return new[] { "20", "USA", "CAN" };
}
Now if you have a problem as to how to create an array whose size is unknown while creating it, then the usual solution is to use List<>, which in this case will act as a re-sizable array for you.
The final code would look something like below
static string[] GetWinner(string[,] medals) {
int rows = medals.GetLength(0);
var winners = new List<string>();
int maxMedals = 0;
for (var i = 0; i < rows; i++) {
var n = int.Parse(medals[i, 4]);
maxMedals = n > maxMedals ? n : maxMedals;
}
for (var i = 0; i < rows; i++) {
var n = int.Parse(medals[i, 4]);
if (n == maxMedals)
winners.Add(medals[i, 0]);
}
winners.Insert(0, maxMedals.ToString());
return winners.ToArray();
}
Now, I would advise you to use a better data structure to store your medals. But since I don't know the full situation, I would guess, something like below is reasonable. Instead of using named types, you can use ValueTuple - to make the code concise, if the code related to these objects are restricted to a small area of a the code file. This should avoid allocating big chunk of memory associated with 2D arrays, and also storing of int in string.
public class CountryMedalTally {
public string Country { get; set; }
public string[] Medals { get; set; }
public int MedalCount { get; set; }
}
public class Winner {
public List<string> Country { get; set; }
public int MedalCount { get; set; }
}
List<CountryMedalTally> AllMedals;
I would like to store reference of an ushort variable in an ushort array, so that the value of the variable changes when I change the values inside the ushort array. Here is my sample code which will give a clear picture of what I'm trying to achieve.
public void IndexSetter(List<int> indexVal,Rootobject objectVal)
{
ushort[] refereneArray = new ushort[8]
{
objectVal.index1, objectVal.index2,
objectVal.index3 , objectVal.index4,
objectVal.index5, objectVal.index6,
objectVal.index7, objectVal.index8
};
for(int j = 0; j< indexVal.Count;j++)
{
refereneArray[j] =(ushort) indexVal[j];
}
}
Instead of storing the values like from above code , I need to store the reference so that the changes in indexVal list reflect in the values of index1, index2.. etc
I´d suggest not to have 8 indexes with the exact same name (except a number). Give every member of your class a name describing what it´s ment to be, however index6 isn´t really self-explanatory.
Having said this what you can do is to have one array of indexes within your class itself:
class Rootobject
{
public int[] Indexes { get; set; }
}
Now you can access them as follows:
public void IndexSetter(List<int> indexVal, Rootobject objectVal)
{
for(int i = 0; i < indexVal.Count; i++)
objectVal.Indexes[index] = indexVal[i];
}
Or even shorter:
objectVal.Indexes = indexVal.Cast<ushort>().ToArray();
You can do it with unsafe code, using array of pointers like this:
static unsafe void IndexSetter(IList<ushort> indexVal, Rootobject objectVal) {
fixed (ushort* r1 = &objectVal.index1)
fixed (ushort* r2 = &objectVal.index2) {
ushort*[] refereneArray = {r1, r2};
for (int j = 0; j < indexVal.Count; j++) {
*refereneArray[j] = (ushort) indexVal[j];
}
}
}
Should you really do this in real application is another story. There is very high chance that there is a better way to solve your problem, but you didn't tell us what the actual problem is.
If perfomance is not critical - you can use reflection:
static void IndexSetter2(IList<ushort> indexVal, Rootobject objectVal) {
int i = 0;
foreach (var field in objectVal.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(c => c.Name.StartsWith("index") && c.FieldType == typeof(ushort))
.OrderBy(c => c.Name)) {
field.SetValue(objectVal, indexVal[i]);
i++;
}
}
I have list of structure. I want to modify a particular data from the structure.
And the structure is at the particular index location of the List.
I want to do something like this:
struct sample
{
int a;
string name;
}
List<sample> list = new List<sample>();
for(int i=0; i < list.Count; i++)
{
list[i].a = someotherlist[i].data;
}
The problem is that the list indexer creates a copy of the struct, i.e. it is really:
for(int i=0; i < list.Count; i++)
{
var completelyIsolatedClone = list[i];
completelyIsolatedClone.a = someotherlist[i].data;
}
The compiler is preventing you making an obvious mistake. The code you have uses the get, mutates a separate copy of the data, but never puts it back - so your change doesn't do anything useful. Note that the Mono folks think it would be nice if it worked your way, though: http://tirania.org/blog/archive/2012/Apr-11.html
Note that an array works differently; with an array you are touching the struct in place, so the following would work fine:
for(int i=0; i < list.Count; i++)
{
someArray[i].a = someotherlist[i].data;
}
Another approach is to copy the data out (the get accessor), mutate it, and put it back:
for(int i=0; i < list.Count; i++)
{
var completelyIsolatedClone = list[i];
completelyIsolatedClone.a = someotherlist[i].data;
list[i] = completelyIsolatedClone;
}
or better, acoid mutable structs completely, perhaps with a method that applies the change to a new copy:
for(int i=0; i < list.Count; i++)
{
list[i] = list[i].SetA(someotherlist[i].data);
}
where SetA creates a new struct, like DateTime.AddDays etc, i.e.
public SomeType SetA(int a) {
return new SomeType(this.X, this.Y, a, this.Z);
}
The reason you can't do it is because Sample is a struct, if you change it to a class then you can modify it. Structures are passed by value, that is, when a structure is returned by a method, a copy of the structure is returned, not the orginal structure. So when list[i].a = someotherlist[i].data; is run, you are actually modifying the copy and the orginal structure is not being changed. The compilers prevents you from doing this as it is probably not what you had intended.
You may look at this thread Why couldnot I modify the value of item from Generic Collections) ?
I just modified my code as bellow and it works fine for me
public struct test
{
public int data;
public string name;
public int port_index;
}
static void Main(string[] args)
{
List<test> look_up = new List<test>();
test obj;
obj.data = 1;
obj.port_index = 0;
obj.name = "aaaa";
look_up.Add(obj);
test obj1;
obj1.data=3;
obj1.port_index=1;
obj1.name="sssss";
look_up.Add(obj1);
for(int i=0;i<look_up.Count;i++)
{
if (i == 1)
{
test temp = look_up[i];
temp.data = 5;
look_up[i] = temp;
}
}
}
I am trying to access an object which is a member of an object array, is that possible ?
I have declared a structure named Particle, and initialized an object array of "Particle" about 40 particles,now I need to access each particle, for ex: particle.Gbest
any one can help ??
here is my code:
struct particle
{
double[] position = new double[100];
double Gbest, Lbest;
double Pconst = 0.5;
}
object[] swarm = new object[swarm_size];
for (int i = 0; i < swarm_size; i++)
{
swarm[i] = new particle();
}
This code is invalid to start with:
struct particle
{
double[] position = new double[100];
}
You can't specify variable initializers for instance variables in structs.
However, accessing data within another object or value is easy - if it's accessible. In this case your fields are private and you haven't provided any access methods or properties, so you won't be able to get at them "from the outside" without more code.
Here's some modified code:
public class Particle
{
private readonly double[] positions = new double[100];
// TODO: Rename these to something useful
public double Gbest { get; private set; }
private double Lbest;
private double Pconst = 0.5;
public Particle(int g)
{
Gbest = g; // Or whatever
}
}
List<Particle> swarm = new List<Particle>();
for (int i = 0; i < swarmSize; i++)
{
swarm.Add(new Particle(i));
}
double total = 0;
foreach (Particle particle in swarm)
{
total += particle.Gbest;
}
Now this isn't doing anything particularly useful, because it's not clear what you're trying to do - but I would suggest you get an introductory book on C#. Stack Overflow is great for specific questions, but I think you're early enough on your journey into C# that a good book or tutorial would help you more.
var swarm = new particle[swarm_size];
for (int i = 0; i < swarm_size; i++)
{
swarm[i] = new particle();
}
To access properties of the array you could walk it like this:
for (int i = 0; i < swarm_size; i++)
{
Console.WriteLine(swarm[i].Gbest);
Console.WriteLine(swarm[i].Lbest);
}
EDIT: swarm declaration was incorrect.
If you know the index of the particle, you can simply use:
particle part = (particle)swarm[i];
// do stuff with part
If you don't know the index, you can iterate over them:
foreach( particle part in swam )
{
// do stuff with part
}
Or you can use Linq-to-Objects to do more sophisticated stuff, but I think you need to start with the simple stuff...
By the way, if you can, declare swarm as:
particle[] swarm = new particle[swarm_size];
and get the benefit of type-safety.
struct particle
{
public double[] position = new double[100];
public double Gbest, Lbest;
public double Pconst = 0.5;
}
particle[] swarm = new particle[swarm_size];
for (int i = 0; i < swarm_size; i++)
{
swarm[i] = new particle();
}
foreach(particle p in swarm)
{
// do magic here
}
You can either change your array type to Particle and access it with index like...
particle[] swarm = new particle[swarm_size];
particle firstParticle = swarm[0];
or you can cast the object back to a particle...
particle firstParticle = (particle)swarm[0];
I would recommend the first option thou for performance reasons.
The .Net framework has an Array.Sort overload that allows one to specify the starting and ending indicies for the sort to act upon. However these parameters are only 32 bit. So I don't see a way to sort a part of a large array when the indicies that describe the sort range can only be specified using a 64-bit number. I suppose I could copy and modify the the framework's sort implementation, but that is not ideal.
Update:
I've created two classes to help me around these and other large-array issues. One other such issue was that long before I got to my memory limit, I start getting OutOfMemoryException's. I'm assuming this is because the requested memory may be available but not contiguous. So for that, I created class BigArray, which is a generic, dynamically sizable list of arrays. It has a smaller memory footprint than the framework's generic list class, and does not require that the entire array be contiguous. I haven't tested the performance hit, but I'm sure its there.
public class BigArray<T> : IEnumerable<T>
{
private long capacity;
private int itemsPerBlock;
private int shift;
private List<T[]> blocks = new List<T[]>();
public BigArray(int itemsPerBlock)
{
shift = (int)Math.Ceiling(Math.Log(itemsPerBlock) / Math.Log(2));
this.itemsPerBlock = 1 << shift;
}
public long Capacity
{
get
{
return capacity;
}
set
{
var requiredBlockCount = (value - 1) / itemsPerBlock + 1;
while (blocks.Count > requiredBlockCount)
{
blocks.RemoveAt(blocks.Count - 1);
}
while (blocks.Count < requiredBlockCount)
{
blocks.Add(new T[itemsPerBlock]);
}
capacity = (long)itemsPerBlock * blocks.Count;
}
}
public T this[long index]
{
get
{
Debug.Assert(index < capacity);
var blockNumber = (int)(index >> shift);
var itemNumber = index & (itemsPerBlock - 1);
return blocks[blockNumber][itemNumber];
}
set
{
Debug.Assert(index < capacity);
var blockNumber = (int)(index >> shift);
var itemNumber = index & (itemsPerBlock - 1);
blocks[blockNumber][itemNumber] = value;
}
}
public IEnumerator<T> GetEnumerator()
{
for (long i = 0; i < capacity; i++)
{
yield return this[i];
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
And getting back to the original issue of sorting... What I really needed was a way to act on each element of an array, in order. But with such large arrays, it is prohibitive to copy the data, sort it, act on it and then discard the sorted copy (the original order must be maintained). So I created static class OrderedOperation, which allows you to perform an arbitrary operation on each element of an unsorted array, in a sorted order. And do so with a low memory footprint (trading memory for execution time here).
public static class OrderedOperation
{
public delegate void WorkerDelegate(int index, float progress);
public static void Process(WorkerDelegate worker, IEnumerable<int> items, int count, int maxItem, int maxChunkSize)
{
// create a histogram such that a single bin is never bigger than a chunk
int binCount = 1000;
int[] bins;
double binScale;
bool ok;
do
{
ok = true;
bins = new int[binCount];
binScale = (double)(binCount - 1) / maxItem;
int i = 0;
foreach (int item in items)
{
bins[(int)(binScale * item)]++;
if (++i == count)
{
break;
}
}
for (int b = 0; b < binCount; b++)
{
if (bins[b] > maxChunkSize)
{
ok = false;
binCount *= 2;
break;
}
}
} while (!ok);
var chunkData = new int[maxChunkSize];
var chunkIndex = new int[maxChunkSize];
var done = new System.Collections.BitArray(count);
var processed = 0;
var binsCompleted = 0;
while (binsCompleted < binCount)
{
var chunkMax = 0;
var sum = 0;
do
{
sum += bins[binsCompleted];
binsCompleted++;
} while (binsCompleted < binCount - 1 && sum + bins[binsCompleted] <= maxChunkSize);
Debug.Assert(sum <= maxChunkSize);
chunkMax = (int)Math.Ceiling((double)binsCompleted / binScale);
var chunkCount = 0;
int i = 0;
foreach (int item in items)
{
if (item < chunkMax && !done[i])
{
chunkData[chunkCount] = item;
chunkIndex[chunkCount] = i;
chunkCount++;
done[i] = true;
}
if (++i == count)
{
break;
}
}
Debug.Assert(sum == chunkCount);
Array.Sort(chunkData, chunkIndex, 0, chunkCount);
for (i = 0; i < chunkCount; i++)
{
worker(chunkIndex[i], (float)processed / count);
processed++;
}
}
Debug.Assert(processed == count);
}
}
The two classes can work together (that's how I use them), but they don't have to. I hope someone else finds them useful. But I'll admit, they are fringe case classes. Questions welcome. And if my code sucks, I'd like to hear tips, too.
One final thought: As you can see in OrderedOperation, I'm using ints and not longs. Currently that is sufficient for me despite the original question I had (the application is in flux, in case you can't tell). But the class should be able to handle longs as well, should the need arise.
You'll find that even on the 64-bit framework, the maximum number of elements in an array is int.MaxValue.
The existing methods that take or return Int64 just cast the long values to Int32 internally and, in the case of parameters, will throw an ArgumentOutOfRangeException if a long parameter isn't between int.MinValue and int.MaxValue.
For example the LongLength property, which returns an Int64, just casts and returns the value of the Length property:
public long LongLength
{
get { return (long)this.Length; } // Length is an Int32
}
So my suggestion would be to cast your Int64 indicies to Int32 and then call one of the existing Sort overloads.
Since Array.Copy takes Int64 params, you could pull out the section you need to sort, sort it, then put it back. Assuming you're sorting less than 2^32 elements, of course.
Seems like if you are sorting more than 2^32 elements then it would be best to write your own, more efficient, sort algorithm anyway.