Skip to content

TypeICall/LoopsWithinLoops

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 

Repository files navigation

LoopsWithinLoops

Notes on creating loops within loops

for loops

Syntactical Structure
for(int i = 0; i < limit; i++)
for(variable type initialized at an amount;
comparision operation that tells the loop when it is time to break the loop and go on to the lines of code after;
incrementer)

typical loops:

Ascending
for(int i = 0; i < limit; i++) { }
Descending
for(int i = limit; i > 0; i--) { }

Could also change increment as in simple polynomials
Evens = 2n
for(int i = 0; i < limit; i +=2) { }
Odds = 2n + 1
for(int i = 1; i < limit; i +=2) { }

Could have an increment that is not regularly spaced
int increment = 2;
for(int i = 0; i < limit; i += increment) { increment *=2; }

Could change the type of the variable from int to float.
This goes around a circle sector by sector-
Vector2[] CircumRadii;
int pointCount = 0;
float Sector = (2*Mathf.PI)/ nGon;
float Round = 2 * Mathf.Pi; for(float i = 0; i <= Round; i += Sector) { CircumRadii[pointCount] = new Vector2(Mathf.sin(i), Mathf.cos(i)); pointCount++; }

This could also be done with a while loop
Vector2[] CircumRadii;
int i = 0;
int nGon;
float Sector = (2*Mathf.PI)/ nGon;
float slices = 0;
while(i <= nGon)
{
CircumRadii[i] = new Vector2(Mathf.sin(slices), Mathf.cos(slices)); }
slices += Sector;
i++;
}

Could also have multiple evaluations in the middle
for(int i = 0; i < 60 && b > 0; i++)

Then we get to having multiple for loops within one another.

Square = where there are n^2 total loops
for(int x = 0; x < n; x++)
for(int y = 0;y < n; y++)

Rectangular = This is how computer monitor's refresh. where there are x * y loops
Color32[] colors32 = new Color32[ScreenHeightInPixels * ScreenWidthInPixels];
for(int x = 0; x < ScreenHeightInPixels; x++)
for(int y = 0;y < ScreenWidthInPixels; y++)
colors32[y,x] = new Color32(R,G,B,A); // where RGBA are in the range between (0-255) and then 256 goes to 0, 257 goes to 1, and 258 goes to 2, etc.
OR
colors[y,x] = new Color(R,G,B,A); (where R,G,B,A are in the range between (0-255)

Cubic
for(int x = 0; x < n; x++)
for(int y = 0; y < n; y++)
for(int z = 0; z < n; z++)

Cuboidal
for(int x = 0; x < height; x++)
for(int y = 0; y < width; y++)
for(int z = 0; z < depth; z++)

In an instance where checking x againt y is the same as checking y against x, such as finding the distances between points,
we can simplify the equation
We find the triangular numbers described by the equation
(n * (n - 1)) * 0.5f = (n ^ 2 - n) * 0.5f

// DO NOT COPY PASTE THE FOLLOWING SECTION. IT IS NOT OPTIMIZED.
for(int x = 0; x < n; x++)
for(int y = x + 1; y < n; y++)
Distances[x * n + y] = Mathf.Sqrt(vertices[x].x - vertices[y].x + vertices[x].y - vertices[y].y + vertices[x].z - vertices[y].z);

We should remain vigilant where we state "Distances[x * n + y]", as we go from this quadratic polynomial on to cubic or quartic polynomials,
and we start looking at even more for loops being in for loops, being in for loops, etc. and we start to see that
2 nested for loops would need [x * n + y]
3 nested for loops would need [x * n * n + y * n + z]
4 nested for loops would need [x * n * n * n + y * n * n + z * n + w]... You get the point.

Imagine that that polynomial would have to be calculated every single time the innermost for loop executed... that would add up to MANY, MANY multiplications
having to be performed.

Another error that some programmers might make is-

// DO NOT COPY PASTE THE FOLLOWING SECTION. IT IS NOT OPTIMIZED.
Vector3[] vertices;
Vector3[] Distances = new float[(n * (n - 1)) * 0.5f]
int a = 0, b = 0; for(int x = 0; x < n; x++)
a = x * n * n; for(int y = 0; y < n; y++)
b = a + y * n; for(int z = 0; y < n; y++)
Distances[a + b + z] = (Calculations);

This is often seen when programmers are taught mathematics in the form of ax^3 + bx^2 + cx + d = 0. They might think that they could do the indexer by doing these operations in piecemeal, but they could be simplified initializing an INDEXER... (There are also cases where programmers define a and b after the inner for loops are performed, which could also be identified. One would hope the compiler would automatically correct it to prevent flare ups, but that is not guaranteed by any programming language so far as I am aware...)

The INDEXER is simply a variable that also goes in to the for loops and gets incremented by 1 to set the location in memory where bits will be stored.

int index = 0;
for(int x = 0; x < n; x++)
{
for(int y = x + 1; y < n; y++)
{
Distances[index] = Mathf.Sqrt(vertices[x].x - vertices[y].x + vertices[x].y - vertices[y].y + vertices[x].z - vertices[y].z);
index++;
}
}
As simple as it gets I do believe, saves on electricity, allows the program to execute more quickly, nice.
Lesson: Even though it seems impressive to have polynomials with multiple terms in your code, sometimes all you need to do is just keep adding 1 and that is optimal.

Another common optimization error is when the coder decides to define things in the innermost for loop that could be defined in an outer for loop. for(int x = 0; x < n; x++)
for(int y = 0; y < n; y++)
for(int z = 0; y < n; y++)
Differences[a + b + z] = (Mathf.Abs(y -z), Mathf.Abs(x - z), Mathf.Abs(x - y))

Here the Mathf.Abs(x - y) term could be brought out in order to save some calculations.

int xy; for(int x = 0; x < n; x++)
for(int y = 0; y < n; y++)
xy = Mathf.Abs(x - y); for(int z = 0; y < n; y++)
Differences[a + b + z] = (Mathf.Abs(y -z), Mathf.Abs(x - z), xy)

Scanning over your code to see if some calculations could be brought up out of the inner for loops and defined fewer times is good practice.

What happens if we continue this pattern?
Well, it does seem that we start moving along Pa....'s Triangle.
From the row of (1,1,1,1...), to the natural numbers (1,2,3,4...) to the triangular numbers (1,3,6,10...) to the tetrahedral numbers(1,4,10,20,...)

I found the tetrahedral numbers while writing a program that find the angles between any three points in space... or at least this is one way of doing it...
This method ensures that there are instances where the same triangles are being checked with reorderings of the vertices.
Vector3[] verts;
Vector3[] Angles = new float[(n * (n + 1) * (n + 2))/ 6];
int index = 0;
for(int x = 0; x < verts.Length; x++)
{
for(int y = x + 1; y < verts.Length; y++)
{
for(int z = y + 1; z < verts.Length; z++)
{
Angles[index] = ???;
index++;
}
}
}

What about for loops with a Jagged Array?
They do need to have each ([] = square bracket) size defined so that a number of bits can ba allocated in memory.
This is a simple multiplication of (2 ^(number of bits of data type) * number of slots allocated in memory)
int[][] numbers = new int[n][]
for(int i = 0; i < n; i++)
{
numbers[i] = new int[n];
for(int j = 0; j < n; j++)
{
numbers[i][j] = i+j;
}
}

Multi-Dimensional Arrays?
int[,] numbers = new int[n,n]
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
numbers[i,j] = i+j;
}
}

What happens if you declare too few spaces in memory for the array to fit?
The program will stop running once it reaches the # address in memory that is equal to the number of spots that were designated to be in memory when the array was intialized.
This would look like-
int[] points = new int[4];
for(int x = 0; x < 8; x++)
{
points[x] = x;
}

When x is incremented up to 4, then the error will be recognized because there were only memory locations (0,1,2,3) created

What happens if you declare too many spaces in memory for the array to fit?
It might seem like a quick fix to just make the number of spaces in memory to be a higher number than you would need, instead of taking the time to find the exact polynomial, but
some problems can arise from that choice.
The program is stored in memory mostly continuously, linearly, as you define each data type, line by line.
There are some breaks where certain keywords will cause the Read to go to other locations in memory, which does cost some time and electricity, but if you are writing a program then it will be mostly contained within a neighborhood and that neighborhood of transistors switched on or off with current flowing through or not flowing through- those neighborhoods will have to be navigated through by the reader. It will take longer in navigating through memory if you have extra, empty memory that needs to be passed by.

Why not use a list?
Lists have to resize their selves. Because the size of the list is unknown, they get allocated a small number of bits in memory initially,
but then once they reach a ((2 ^ n)- 1) threshold and another term is added, then they will have to change their size.
There are performance gains when we use arrays and tell exactly how much memory there is going to be used for the array before we start adding terms to it.
It is not always the case that we know how big an array will be, so there are many cases where it makes sense to use Lists.

Why use a list?
Lists allow for easier ways of adding and subtracting one or more terms in a single line of code.
When a piece of data is removed from a list, then it will automatically cause the item that was stored after to move in to the now empty spot in memory and then every term thereafter will have their # in memory reduced by how many items were deleted.
This can cause some confusion when looping through the list and trying to sequentially remove items while the list is restructuring it's self.
If one is using the list as a minimum or maximum value in a loop, the size of that list could be changed inside of that loop and therefore seem to move about it's # address in memory.

When to use Lists?
Lists are really helpful when one is not certain how many addresses in memory seem reasonable to designate.
Technically, Lists are not needed if the data is static and unchanging throughout the course of the program's duration.
Lists are more associated with the idea of mutability and Lists allow data to flow in and out with ease.

About

Notes on creating loops within loops

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published