I have this for loop. TicketList starts with 109 tickets. nColumns = 100. I calculate the number of rows I will need depending on the number of tickets. So in this case I need 2 rows. Row one will be full and row two will only have 9 entries. I have the loop below. It only runs one time for the NumOfRows and fills the first 100 and never loops.
What am I missing?
for (int j = 0; j < NumOfRows; j++)
{
for (int i = 0; i < nColumns; i++)
{
if (TicketList.Count() > 0)
{
t = rand.Next(0, TicketList.Count() - 1);
numbers[i, j] = TicketList[t];
TicketList.Remove(TicketList[t]);
}
}
}
Try changing your code to use a more LINQ-like, functional approach. If might make the logic easier. Something like this:
TicketList
.OrderBy(x => rand.Next())
.Select((ticket, n) => new
{
ticket,
j = n / NumOfRows,
i = n % NumOfRows
})
.ToList()
.ForEach(x =>
{
numbers[x.i, x.j] = x.ticket;
});
You may need to flip around x.i & x.j or use nColumns instead of NumOfRows - I wasn't sure what your logic was looking for - but this code might work better.
Other than a few poor choices, your loops appear to be fine. I would venture that NumOfRows is not being calculated correctly.
The expression NumOfRows = (TotalTickets + (Columns - 1)) / Columns; should calculate the correct number of rows.
Also, you should use the property version of Count rather than the Linq extension method and use IList<T>.RemoveAt() or List<T>.RemoveAt rather than Remove(TicketList[T]).
Using Remove() requires that the list be enumerated to locate the element to remove, which may not be the same index that you are targeting. Not to mention that you will scan 50% (on average) of the list for each Remove call, when you already know the correct index to remove.
The functional approach listed earlier seems like overkill.
I've attempted to replicate your issue, assuming certain facts about the various variables in use. The loop repeats the expected number of times.
static void TestMe ()
{
List<object> TicketList = new List<object>();
for (int index = 0; index < 109; index++)
TicketList.Add(new object());
var rand = new Random();
int nColumns = 100;
int NumOfRows = (TicketList.Count + (nColumns - 1)) / nColumns;
object[,] numbers;
int t;
numbers = new object[nColumns, NumOfRows];
for (int j = 0; j < NumOfRows; j++)
{
Console.WriteLine("OuterLoop");
for (int i = 0; i < nColumns; i++)
{
if (TicketList.Count > 0)
{
t = rand.Next(0, TicketList.Count - 1);
numbers[i, j] = TicketList[t];
TicketList.RemoveAt(t);
}
}
}
}
The problem that you are seeing must be the result of something that you have not included in your sample.
Related
I have 2 checked list boxes, where you select the main idea in the first one, and select a narrower focus in the 2nd box. After much work, I finally made it work, but it still seems horribly inefficient. Is there a way to optimize this?
List<int> k= new List<int>();
int f = 0;
for(int j = 0; j < SubRaces.Items.Count; j++) {
if(SubRaces.GetItemCheckState(j) == CheckState.Checked) {
f = j;
}
}
for(int i = 0; i < DNDSubRace.allSubRaces.Count; i++){
if(DNDSubRace.allSubRaces[i].MainRace.Name == Races.SelectedItem) {
k.Add(i);
}
}
DNDSubRace.allSubRaces [k [f]].DNDSubRaceDescription();
SubRaceBenefits.Text = DNDSubRace.allSubRaces [k [f]].Details;
You can optimize the code a little bit, for example you can add a break statement in the first for loop (this requires you to reverse the loop to get the exact same behaviour, provided SubRaces.GetItemCheckState() does not need to be called for every element)
List<int> k = new List<int>();
int f = 0;
for(int j = SubRaces.Items.Count - 1; j >= 0; j--) {
if(SubRaces.GetItemCheckState(j) == CheckState.Checked) {
f = j;
break;
}
}
for(int i = 0; i < DNDSubRace.allSubRaces.Count; i++){
if(DNDSubRace.allSubRaces[i].MainRace.Name == Races.SelectedItem) {
k.Add(i);
}
}
DNDSubRace.allSubRaces [k [f]].DNDSubRaceDescription();
SubRaceBenefits.Text = DNDSubRace.allSubRaces [k [f]].Details;
Another possibility is using Linq which will be slower, but is shorter to write. When using Linq to shorten the above solution, the result is:
List<int> k = DNDSubRace.allSubRaces.Where(r=>r.MainRace.Name == Races.SelectedItem).ToList();
int f = 0;
for(int j = SubRaces.Items.Count - 1; j >= 0; j--) {
if(SubRaces.GetItemCheckState(j) == CheckState.Checked) {
f = j;
break;
}
}
DNDSubRace.allSubRaces [k [f]].DNDSubRaceDescription();
SubRaceBenefits.Text = DNDSubRace.allSubRaces [k [f]].Details;
The first way of optimizing the code is reducing the number of cycles the upper for loop will be run for. When there are two matching elements in SubRaces then the variable f will be set to the index two times and the last match will stay (in the unoptimized version). If you reverse the for loop and exit it as soon as you get a match you will end up with the same behaviour, but it will be quicker.
The second rewrite wraps the second for loop into a Linq statement, which is slower but is shorter to write. Essentially it applies a filter and then copies the matching elements over to a new List.
I hope this helps!
Your answer would be to use events. When the item in the first list gets selected you can populate the second list with only its related options.
I have a float array containing 1M floats
I want to do sampling: for each 4 floats I want to take only 1. So i am doing this :
for(int i = 0; i< floatArray.Length; i++) {
if(i % 4 == 0) {
resultFloat.Add(floatArray[i])
}
}
This works fine, but it takes much time to run through all the elements , is there any other methods to make it with better results (if there are any)
I can see two factors that might be slowing down performance.
As you have already been offered, you should set the step to 4:
for (int i = 0; i < floatArray.Length; i += 4)
{
resultFloat.Add(floatArray[i]);
}
Looks like resultFloat is a list of float. I suggest to use array instead of list, like this:
int m = (floatArray.Length + 3) / 4;
float[] resultFloat = new float[m];
for (int i = 0, k = 0; i < floatArray.Length; i += 4, k++)
{
resultFloat[k] = floatArray[i];
}
Just increment your loop by 4 each iteration instead of by 1:
for(int i = 0; i< floatArray.Length; i+=4)
{
resultFloat.Add(floatArray[i]);
}
If you really have an issue with performance, then you'd be even better off not using a dynamic container for the results, but a statically sized array.
float[] resultFloat = new float[(floatArray.Length + 3) >> 2];
for(int i = 0; i < resultFloat.Length; i++)
resultFloat[i] = floatArray[i << 2];
Usually performance isn't an issue thow, and you shouldn't optimize until a profiler gave you proof that you should. In all other cases the more readable code is preferrable.
Just to add another option, if you want this to be the fastest, use Parallel.For instead of a normal for loop.
int resultLength = (floatArray.Length + 3) / 4;
var resultFloat = new float[resultLength];
Parallel.For(0, resultLength, i =>
{
resultFloat[i] = floatArray[i * 4];
});
List<decimal> list = new List<decimal>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
list.Add(6);
list.Add(7);
list.Add(8);
list.Add(9);
list.Add(10);
list.Add(11);
list.Add(12);
list.Add(13);
list.Add(14);
list.Add(15);
list.Add(16);
var sampleData = list.Where((x, i) => (i + 1) % (4) == 0).ToList();
I'm new here and sorry If my question is stupid, but I really need you help.
I need to sort that two dimensional string array by id (the first column):
string [,] a = new string [,]
{
{"2","Pena","pena"},
{"1","Kon","kon"},
{"5","Sopol","sopol"},
{"4","Pastet","pastet"},
{"7","Kuche","kuche"}
};
The problem is that I'm sorting only the number and I want after them to sort the words. That's what I did so far
static void Main(string[] args)
{
string [,] a = new string [,]
{
{"2","Pena","pena"},
{"1","Kon","kon"},
{"5","Sopol","sopol"},
{"4","Pastet","pastet"},
{"7","Kuche","kuche"}
};
int b = a.GetLength(0);
Console.WriteLine(b);
Console.WriteLine(a[0,0]);
Console.WriteLine(a[0,1]);
Console.WriteLine(a[1,0]);
InsertionSort(a, b);
Console.WriteLine();
Console.Write("Sorted Array: ");
printArray(a);
Console.WriteLine();
Console.Write("Press any key to close");
Console.ReadKey();
}
public static void InsertionSort(string[,] iNumbers, int iArraySize)
{
int i, j, index;
for (i = 1; i < iArraySize; i++)
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
index = Convert.ToInt32(iNumbers[i, 0]);
j = i;
while ((j > 0) && (Convert.ToInt32(iNumbers[j - 1, 0]) > index))
{
iNumbers[j, k] = iNumbers[j - 1, k];
j = j - 1;
}
iNumbers[j, 0] = Convert.ToString(index);
}
}
}
static void printArray(string[,] iNumbers)
{
for (int i = 0; i < iNumbers.GetLength(0); i++)
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
Console.Write(iNumbers[i, k] + " ");
}
}
Console.WriteLine();
}
Unfortunatelly as output I get
1 Pena pena 2 Kon kon 4 Sopol sopol 5 Pastet pastet 7 Kuche kuche
I would be really grateful if you could help me.
Based on the nature of the example and the question, I am guessing that this is a homework assignment and so must be implemented in a fashion that is a) not far from your current example, and b) actually demonstrates an insertion sort.
With that in mind, the following is a corrected version of your example that works:
public static void InsertionSort(string[,] iNumbers, int iArraySize)
{
int i, j, index;
for (i = 1; i < iArraySize; i++)
{
index = Convert.ToInt32(iNumbers[i, 0]);
j = i;
while ((j > 0) && (Convert.ToInt32(iNumbers[j - 1, 0]) > index))
{
for (int k = 0; k < iNumbers.GetLength(1); k++)
{
string temp = iNumbers[j, k];
iNumbers[j, k] = iNumbers[j - 1, k];
iNumbers[j - 1, k] = temp;
}
j = j - 1;
}
}
}
I made two key changes to your original code:
I rearranged the k and j loops so that the k loop is the inner-most loop, rather than the j loop. Your j loop is the one performing the actual sort, while the k loop is what should be actually moving a row for an insertion operation.
In your original example, you had this reversed, with the result that by the time you went to sort anything except the index element of a row, everything looked sorted to the code (because it's only comparing the index element) and so nothing else got moved.
With the above example, the insertion point is determined first, and then the k loop is used simply to do the actual insertion.
I added logic to actually swap the elements. In your original code, there wasn't really a swap there. You had hard-coded the second part of a swap, simply copying the index element to the target, so the swap did work for the index element. But it wouldn't have achieved the swap for any other element; instead, you'd just have overwritten data.
With the above, a proper, traditional swap is used: one of the values to be swapped is copied to a temp local variable, the other value to be swapped is copied to the location of the first value, and then finally the saved value is copied to the location of the second.
The above should be good enough to get you back on track with your assignment. However, I will mention that you can get rid of the k loop altogether if your teacher will allow you to implement this using jagged arrays (i.e. a single-dimensional array containing several other single-dimensional arrays), or by using a second "index array" (i.e. where you swap the indexes relative to the original array, but leave the original array untouched).
I heard about Counting Sort and wrote my version of it based on what I understood.
public void my_counting_sort(int[] arr)
{
int range = 100;
int[] count = new int[range];
for (int i = 0; i < arr.Length; i++) count[arr[i]]++;
int index = 0;
for (int i = 0; i < count.Length; i++)
{
while (count[i] != 0)
{
arr[index++] = i;
count[i]--;
}
}
}
The above code works perfectly.
However, the algorithm given in CLRS is different. Below is my implementation
public int[] counting_sort(int[] arr)
{
int k = 100;
int[] count = new int[k + 1];
for (int i = 0; i < arr.Length; i++)
count[arr[i]]++;
for (int i = 1; i <= k; i++)
count[i] = count[i] + count[i - 1];
int[] b = new int[arr.Length];
for (int i = arr.Length - 1; i >= 0; i--)
{
b[count[arr[i]]] = arr[i];
count[arr[i]]--;
}
return b;
}
I've directly translated this from pseudocode to C#. The code doesn't work and I get an IndexOutOfRange Exception.
So my questions are:
What's wrong with the second piece of code ?
What's the difference algorithm wise between my naive implementation and the one given in the book ?
The problem with your version is that it won't work if the elements have satellite data.
CLRS version would work and it's stable.
EDIT:
Here's an implementation of the CLRS version in Python, which sorts pairs (key, value) by key:
def sort(a):
B = 101
count = [0] * B
for (k, v) in a:
count[k] += 1
for i in range(1, B):
count[i] += count[i-1]
b = [None] * len(a)
for i in range(len(a) - 1, -1, -1):
(k, v) = a[i]
count[k] -= 1
b[count[k]] = a[i]
return b
>>> print sort([(3,'b'),(2,'a'),(3,'l'),(1,'s'),(1,'t'),(3,'e')])
[(1, 's'), (1, 't'), (2, 'a'), (3, 'b'), (3, 'l'), (3, 'e')]
It should be
b[count[arr[i]]-1] = arr[i];
I'll leave it to you to track down why ;-).
I don't think they perform any differently. The second just pushes the correlation of counts out of the loop so that it's simplified a bit within the final loop. That's not necessary as far as I'm concerned. Your way is just as straightforward and probably more readable. In fact (I don't know about C# since I'm a Java guy) I would expect that you could replace that inner while-loop with a library array fill; something like this:
for (int i = 0; i < count.Length; i++)
{
arrayFill(arr, index, count[i], i);
index += count[i];
}
In Java the method is java.util.Arrays.fill(...).
The problem is that you have hard-coded the length of the array that you are using to 100. The length of the array should be m + 1 where m is the maximum element on the original array. This is the first reason that you would think using counting-sort, if you have information about the elements of the array are all minor that some constant and it would work great.
I am looping through an array of strings, such as (1/12/1992 apple truck 12/10/10 orange bicycle). The array's length will always be divisible by 3. I need to loop through the array and grab the first 3 items (I'm going to insert them into a DB) and then grab the next 3 and so on and so forth until all of them have been gone through.
//iterate the array
for (int i = 0; i < theData.Length; i++)
{
//grab 3 items at a time and do db insert, continue until all items are gone. 'theData' will always be divisible by 3.
}
Just increment i by 3 in each step:
Debug.Assert((theData.Length % 3) == 0); // 'theData' will always be divisible by 3
for (int i = 0; i < theData.Length; i += 3)
{
//grab 3 items at a time and do db insert,
// continue until all items are gone..
string item1 = theData[i+0];
string item2 = theData[i+1];
string item3 = theData[i+2];
// use the items
}
To answer some comments, it is a given that theData.Length is a multiple of 3 so there is no need to check for theData.Length-2 as an upperbound. That would only mask errors in the preconditions.
i++ is the standard use of a loop, but not the only way. Try incrementing by 3 each time:
for (int i = 0; i < theData.Length - 2; i+=3)
{
// use theData[i], theData[i+1], theData[i+2]
}
Not too difficult. Just increment the counter of the for loop by 3 each iteration and then offset the indexer to get the batch of 3 at a time:
for(int i=0; i < theData.Length; i+=3)
{
var item1 = theData[i];
var item2 = theData[i+1];
var item3 = theData[i+2];
}
If the length of the array wasn't garuanteed to be a multiple of three, you would need to check the upper bound with theData.Length - 2 instead.
Your for loop doesn't need to just add one. You can loop by three.
for(int i = 0; i < theData.Length; i+=3)
{
string value1 = theData[i];
string value2 = theData[i+1];
string value3 = theData[i+2];
}
Basically, you are just using indexes to grab the values in your array. One point to note here, I am not checking to see if you go past the end of your array. Make sure you are doing bounds checking!
This should work:
//iterate the array
for (int i = 0; i < theData.Length; i+=3)
{
//grab 3 items at a time and do db insert, continue until all items are gone. 'theData' will always be divisible by 3.
var a = theData[i];
var b = theData[i + 1];
var c = theData[i + 2];
}
I've been downvoted for this answer once. I'm pretty sure it is related to the use of theData.Length for the upperbound. The code as is works fine because array is guaranteed to be a multiple of three as the question states. If this guarantee wasn't in place, you would need to check the upper bound with theData.Length - 2 instead.
Here is a more general solution:
int increment = 3;
for(int i = 0; i < theData.Length; i += increment)
{
for(int j = 0; j < increment; j++)
{
if(i+j < theData.Length) {
//theData[i + j] for the current index
}
}
}
string[] friends = new string[4];
friends[0]= "ali";
friends[1]= "Mike";
friends[2]= "jan";
friends[3]= "hamid";
for (int i = 0; i < friends.Length; i++)
{
Console.WriteLine(friends[i]);
}Console.ReadLine();