Loop stops all code after one iteration - c#

I have a loop which in theory should loop 40000 times but exits and doesn't continue with code after the loop, just after one iteration. I figured that I wasnt being a silly willy about the for-loops since it didn't continue after the loops at all, so that might be something with restrictions for Lists? Or mayby something about the VS-debugger that isn't working preperly? (probably not tho...)
Edit: Thanks for pointing out that the last layer was pointless. I edited the code, but the problem persists.
Edit2: To clarify, the code does not result in an exception, or breaks. It just stops without any notifications, and shows the form(since I do a windows forms application). Just... it just don't want to continue and skips the rest of the code.
for (int i = 0; i < hiddenLayerDepth - 1; i++)
{
Connectors.Add(new List<List<List<List<Connector>>>>());
for (int j = 0; j < playfieldSize; j++)
{
Connectors[i].Add(new List<List<List<Connector>>>());
for (int k = 0; k < playfieldSize; k++)
{
Connectors[i][j].Add(new List<List<Connector>>());
for (int l = 0; l < playfieldSize; l++)
{
Connectors[i][j][k][l].Add(new Connector());
}
}
}
}
hiddenLayerDepth is set to 5 when entering the loop, and playfieldSize is set to 10. It enters the innermost loop and executes the code inside, then it just stops without increasing m.

Missing
Connectors[i][j][k].Add(new List<List<Connector>>());
If you know the sizes you should just create and array up front

Well, I tried to add a 'Connector' where there were no list. The List that contained the lists that would countain the Connectors was not added.

Related

Pre-decrement of value in a for loop is not correctly decreasing value on first loop

I have the following for loop in my code (using C#)
for (int i = 150; i >= 75; --i)
{
print("I holds " + i);
images[i].gameObject.SetActive(false);
}
trying to run through each item in a list, and disable the object. The list holds 150 objects (but since it starts at value zero, the final reference position is 149)
So, I figured a for loop was a good way to iterate through them all. Yet, I try to decrease the value of i to 149 for the first run of the loop, but it still passes a value of 150 into the loop in the first run, which throws the expected ("Argument is out of range") error.
Can anyone work out why the decreased value isn't correctly being passed to the loop?
I tried both decreasing it before and after the first run of the loop, but both times it passes a value of 150 into the loop.
I feel this should be a relatively simple issue to solve, yet it's not working as I expected it to do!
for (int i = 10; i >= 0; --i)
is the same as
for (int i = 10; i >= 0; i--)
i does not decrease/increase on the first loop. This is for many languages. Just start with 149 and it works.
Answer for "Can anyone work out why the decreased value isn't correctly being passed to the loop?"
Another way to loop through all items of an array without caring of actual indices is to make use of a foreach statement:
foreach(var image in images)
{
image.gameObject.SetActive(false);
}
If you want to use a for statement. I would suggest you write it as below:
for(var i=0; i<images.Length; i++)
{
image[i].gameObject.SetActive(false);
}
Doing so, you are pretty confident that you are not going to be out of the array's size. You start at the element at the position with index of 0 and you read the last item stored in the array, in the position of images.Length-1.
Update
If you want to update only the first 75 items (where 75 is half the total items in the array) in your array you could try this:
for(var i=0; i<images.Length/2; i++)
{
image[i].gameObject.SetActive(false);
}

For Loop isnt being fully completed

I have a For Loop which handles taking cards from the master deck, and putting them in a random order into the players deck. The code is:
for(int a = 0; a < deckManager.DeckAllCardsPlayer.Count; a++){
int b = Random.Range(0, deckManager.DeckAllCardsPlayer.Count);
if(!PlayerDeck.Contains(deckManager.DeckAllCardsPlayer[b])){
PlayerDeck.Add(deckManager.DeckAllCardsPlayer[b]);
deckManager.DeckAllCardsPlayer.RemoveAt(b);
}
}
There are 16 cards in the master deck, but this for loop only does 8. Can someone figure out why? Originally, it was adding some cards multiple times, which is why I added the '!PlayerDeck.Contains' statement. I have no idea why it's only doing 8 of 16.
The issue is that deckManager.DeckAllCardsPlayer.Count is getting smaller at each iteration. Try this instead:
while (deckManager.DeckAllCardsPlayer.Count > 0) {
int b = Random.Range(0, deckManager.DeckAllCardsPlayer.Count);
PlayerDeck.Add(deckManager.DeckAllCardsPlayer[b]);
deckManager.DeckAllCardsPlayer.RemoveAt(b);
}
I removed the conditional, because it shouldn't be necessary. (Unless the starting deck has duplicates? If so, just put it back in.)
You start off with 16 cards, but remove one each time.
As a result, although a decrease by one each iteration, the value of deckManager.DeckAllCardsPlayer.Count goes down.
After 8 iterations, a is 7, but the size of DeckAllCardsPlayer has been reduced to 8. Hence the loop terminates on the next turn.
One way to work around would be to take the count up front and store in an integer:
int totalCards = deckManager.DeckAllCardsPlayer.Count;
for(int a = 0; a < totalCards; a++){
... etc.
Although there are many other ways, depending on the logic that you want to expose.
This question may be enlightening : Is the condition in a for loop evaluated each iteration?
The upperbound or limit of the loop is changing as you remove cards from deck.
To fix it with just 2 line code change,
Try this
int count = deckManager.DeckAllCardsPlayer.Count;
for(int a = 0; a < count; a++){
int b = Random.Range(0, deckManager.DeckAllCardsPlayer.Count);
if(!PlayerDeck.Contains(deckManager.DeckAllCardsPlayer[b])){
PlayerDeck.Add(deckManager.DeckAllCardsPlayer[b]);
deckManager.DeckAllCardsPlayer.RemoveAt(b);
}
}
Assuming PlayerDeck & deckManager.DeckAllCardsPlayer are both lists then just do this:
PlayerDeck.AddRange(deckManager.DeckAllCardsPlayer.OrderBy(x => Random.value));
deckManager.DeckAllCardsPlayer.Clear();
Then you don't have to worry about removing elements while you iterate (which you should never do).
int count = deckManager.DeckAllCardsPlayer.Count;
for(int a = 0; a < count; a++){
int b = Random.Range(0, deckManager.DeckAllCardsPlayer.Count);
if(!PlayerDeck.Contains(deckManager.DeckAllCardsPlayer[b])){
PlayerDeck.Add(deckManager.DeckAllCardsPlayer[b]);
deckManager.DeckAllCardsPlayer.RemoveAt(b);
}
}
You must use count variable. Because deckManager.DeckAllCardsPlayer.Count will be changed after run deckManager.DeckAllCardsPlayer.RemoveAt(b). I hope it will work for you.

C# When using foreach on a list of arrays, the foreach only iterates 5 times even though the list has length 86

I'm writing a chess engine in C#, and I'm trying to debug move generation. I've been using breakpoints so far to check variables, but I need a better way to debug. Despite the fact that a breakpoint shows that this list has a length of 86, the loop only runs 5 times. The only thing I can think of is that the arrays in the list have a length of 5, but I have no idea what would be causing this.
foreach (int[] debugBoard in futures)
{
for (int i = 0; i < 5; i++)
{
Debug.Write(debugBoard[i].ToString().PadLeft(3, ' '));
}
Debug.Write("\n");
int[,] debugOutBoard = new int[8, 8];
Array.Copy(chessBoard.Pieces(), debugOutBoard, 64);
if (debugBoard[0] < 0 || debugBoard[1] < 0 || debugBoard[2] < 0 || debugBoard[3] < 0 || debugBoard[0] > 7 || debugBoard[1] > 7 || debugBoard[2] > 7 || debugBoard[3] > 7)
break;
debugOutBoard[debugBoard[2], debugBoard[3]] = debugOutBoard[debugBoard[0], debugBoard[1]];
debugOutBoard[debugBoard[0], debugBoard[1]] = 0;
int rowLength = debugOutBoard.GetLength(0);
int colLength = debugOutBoard.GetLength(1);
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
Debug.Write(debugOutBoard[i, j].ToString().PadLeft(3, ' '));
}
Debug.Write(Environment.NewLine + Environment.NewLine);
}
}
Also, I tried using a concurrentbag to store moves in (I was going to multithread the move processing later on) but as soon as the foreach loop touched the concurrent bag, all the memory values of the bag changed to one value. I've been stuck on this roadblock for days, and I really need help.
Your if statement breaks out of the for loop when its condition is met, I presume this happens for the first time on the 5th/6th iteration.
What I meant to do is iterate to the next element. What command would I use to do that? –
You need to use continue instead of break
If 'futures' contains 86 items the only way it could stop iterating is if an exception occurs. Visual studio (In default settings) should break when this occurs unless you handle the exception somewhere.
Wrap the whole thing in a try{} catch{} and set a breakpoint in catch and see if it hits.

Bidirectional Bubble sort c#

I have a homework assignment of coding a bidirectional bubble sort. Can someone please see if my logic is correct with respect to it. I Don't want code as I want to figure it out myself. I just want a logic check of how i understand it.
As i understand the Bidirectional Bubble sort you implement 2 for loops one starting at position 1 in the list and performing a normal bubble sort. As the first for loop reaches the end a second one is implemented working in reverse. I just don't completely understand what the terminating conditions for each loop would be.
Would the for loop conditions be something as follows?
loop 1 - for(i = 0; i < Count -i; i++)
loop 2 - for(j = Count - i; j > i; j--)
in each loop the swap conditions would be specified.
Thanks
The "classic" bubble sort goes through the entire array on each iteration, so the loops should be
for(i = 0; i < Count - 1; i++)
and
for(j = Count - 1; j > 0; j--)
Both loops skip one index: the first loop skips the last index, while the second loop skips the initial one. This is so that your code could safely compare data[i] to data[i+1], and data[j] to data[j-1].
EDIT The "optimized" bubble sort skips the initial k elements on k-th iteration. Since your bubble sort is bidirectional, you will be able to skip the initial k and the tail k elements, like this:
int k = 0;
do { // The outer loop
...
for(int i = k; i < Count - k - 1; i++)
...
for(int j = Count - k - 1; j > k ; j--)
...
k++;
} while (<there were swaps>);
bidirectional bubble sort works like this:
instead of passing the list from bottom to top every time (bubble sort) you start one time at the bottom and every second time from the top of the list.
the wikipedia article does a way better job at explaining it:
http://en.wikipedia.org/wiki/Cocktail_sort
- rich

Optimize looping through large datatable

I'm loping datatable with 100 to 10000 rows, comparing each row to each other through doyble loop.
for (int i = 0; i < DT1.Rows.Count; i++)
{
for (int j = 0; j < DT1.Rows.Count; j++)
{
//some code to compare data
}
}
For 100-200 rows it's done in few minutes, which is OK, but comparing few thousands rows to few thousands, takes hours and isn't finished.
What can I do to speed it up? Best I thought up is to use lists of objects, instead of datatables.
Any other sugestions?
Can thread be used to do this?
Thanks.
I recently came across a similar scenario that I had to work through. Though in my case, I was comparing a pair of excel files. For my trial run, after getting it working, I had 530 rows on one side and 459000 on the other inside nested loop. This is roughly 234 million iterations. My program was able to work through it in roughly 30 seconds. I used a foreach in this scenario:
foreach (DataRow r1 in DT1.Rows) //Loop the First Source data
{
foreach (DataRow r2 in DT2.Rows) //Loop the Second Source data
{
//Comparison code here...
}
}
Edit: In your loop, as a point of reference, you are causing 3 variables to be tracked at each iteration of the loops, first and second are your counters. The third is the major performance hit, DT1.Rows.Count. By using the Direct row count as a part of the loops, it must be re-evaluated at each iteration. This adds unneeded time to the program. If you absolutely require that there be the counters, then assign the Row count out first:
int DT1Count = DT1.Rows.Count;
for (int i = 0; i < DT1Count; i++)
{
for (int j = 0; j < DT1Count; j++)
{
//some code to compare data
}
}
This way, the row count is static and shall remove the extra processing needed to evaluate the row count at each iteration.
Although you can certainly optimize your search by using hash tables, the best optimization is to let the database engine to the search for you. RDBMS engines are optimized for this kind of task - no client-side optimization should be able to beat it. Your biggest disadvantage is having to pull the data from the database into your program. This is very slow. The database engine has all the data right there - this is a huge advantage.
For example, if you are looking for rows representing users with identical first and last name, a simple query with a self-join will get you results in seconds, not minutes, because the data never leaves the engine.
select u1.userId, u2.userId
from User u1
join User u2 on u1.FirstName=u2.FirstName and u1.LastName=u2.LastName
Assuming that FirstName and LastName columns are indexed, this query will find you duplicates very quickly.
If the results are sorted in some sort of order you can put the results into an array and loop through using a Binary Search
for (int i = 0; i < DT1.Rows.Count; i++)
{
for (int j = i+1; j < DT1.Rows.Count; j++) //<-- starts from next row
{
//some code to compare data
}
}
you could also count on .NET internals to do better job than manual looping using:
DataTable.Select(filterExpression, sortExpression)
The biggest optimization to be made here is the following:
Currently, you are comparing each value twice. For example, in the first iteration of the loop, you are comparing the first row with itself, because both loops start at index 0.
The simplest fix to this would be to change the inner loop to this:
for (int j = i + 1; j < DT1.Rows.Count; j++)
This will dramatically reduce the number of comparisons. Your algorithm currently needs n^2 comparisons. The proposed fix reduces this number to less than the half. With the fix you only need (n^2 - n) / 2 comparisons.

Categories