are all while loops convertible to for loops? - loops

earlier, I thought that we can't use for loops when working with linked lists... but then
for(current = head; current != NULL; current = current->next)
this line made me think. is all while loops are convertible to for loops especially when there is more than one condition?

Yes anything which can be written in a while loop can be represented with a for loop. Both of them are entry controlled loops which means first they check the condition and then the body is executed.
For a loop to run properly, we need at least one thing, i.e. condition and at most 3 things:
Initialization of the looping variable (If necessary)
Condition (Necessary)
Modification to the looping variable (If looping variable is initialized)
Now I will present a simple code block with both while and for loops:
-> To print all naturals numbers from 1 to 100.
Using While loop
int i=1; //Initialization of looping variable
while(i<=100) //Condition check
{
cout<<i;
i++; //Increment (Modification of looping variable)
}
Using For loop
Method 1:
for(int i=1;i<=100;i++)
//Here the first part to the for is initialization of looping variable.
// Second part is the Condition
// Third part is the increment
{
cout<<i;
}
Method 2:
int i=1;//Initializing the loop variable
for(;i<=100;)//Condition
{
cout<<i;
i++;//Increment
}
I gave this 2 methods to write the For loop, to show that both while and for loop can run only with the condition. If we are capable enough to rewrite the code in the format we need, both will run exactly in the same way.

You can use for loops in this instance because you are iterating a specific number of times (once per item in the list). It's not super intuitive but most purely programming related you could manage to change from a purely true/false run condition to a bounded countable run condition.
This line of thinking breaks down very quickly if you involve any amount of hardware. Let's say you have a program that turns on an LED so long as you hold down a button.
while(button is down)
{
LED = ON;
}
Something like this you wouldn't want to do with a for loop because there is no way of counting something to know when you stop, the amount of time is decided by the person holding down the button and can't be known by the computer until it actually happens.
TL;DR: You can use for loops for a lot of things that aren't intuitive. But you can't use them to replace EVERY possible while loop.

Some code example from my code, using while in a way that I wouldn't replace it with a for.
public function generateUniqueTokenForEntity(){
while (true) {
$token = substr(md5(uniqid()), 0, 10);
$entry = $databaseTable->findEntryByToken($token);
if ($entry === null) {
return $token;
}
}
}

Related

I am getting the wrong answer when I use .size() in my for loop but when I assign it to a variable before, it works. Why?

while(!q.empty())
{
depth++;
//int size = q.size();
for(int i = 0; i<q.size;i++)
{
cout << q.size();
auto currNode = q.front();
q.pop();
for(auto n: currNode->children)
{
if(n)
q.push(n);
}
}
I using BFS to solve a leetcode problem but when I have q.size() in the for loop, I miss test cases. However when I assign it to an integer before going into the loop (the commented out section), then it works. Could anyone explain why? I would have assumed that the code would work the same written either way. thanks!
The size of the queue is always changing inside the for loop.
Let's say initially the size of the queue is 5.
When you store this value in a variable before the for loop, the loop is guaranteed to run for 5 times according to the loop's condition.
But if we use q.size() in the loop's condition, it will not be guaranteed to run for 5 times. Because inside the loop, the queue's size is always changing. Either it's decreasing because the current node has no child, or it's increasing because the current node has 2 or more child.
Let's say, among the 5 nodes, the first 4 does not have any child. In that case, the for loop will iterate for 3 times and then terminate. But if we use the size variable, it will iterate for 5 times.

How would you write the equivalent of this C++ loop in Rust

Rust's for loops are a bit different than those in C-style languages. I am trying to figure out if I can achieve the same result below in a similar fashion in Rust. Note the condition where the i^2 < n.
for (int i = 2; i * i < n; i++)
{
// code goes here ...
}
You can always do a literal translation to a while loop.
let mut i = 2;
while i * i < n {
// code goes here
i += 1;
}
You can also always write a for loop over an infinite range and break out on an arbitrary condition:
for i in 2.. {
if i * i >= n { break }
// code goes here
}
For this specific problem, you could also use take_while, but I don't know if that is actually more readable than breaking out of the for loop. It would make more sense as part of a longer chain of "combinators".
for i in (2..).take_while(|i| i * i < n) {
// code goes here
}
The take_while suggestion from zwol's answer is the most idiomatic, and therefore usually the best choice. All of the information about the loop is kept together in a single expression instead of getting mixed into the body of the loop.
However, the fastest implementation is to precompute the square root of n (actually a weird sort of rounded-down square root). This lets you avoid doing a comparison every iteration, since you know this is always the final value of i.
let m = (n as f64 - 0.5).sqrt() as _;
for i in 2 ..= m {
// code goes here
}
As a side note, I tried to benchmark these different loops. The take_while was the slowest. The version I just suggested always reported 0 ns/iter, and I'm not sure if that's just due to some code being optimised to the point of not running at all, or if it really is too fast to measure. For most uses, the difference shouldn't be important though.
Update: I have learned more Rust since I wrote this answer. This structure is still useful for some rare situations (like when the logic inside the loop needs to conditionally mutate the counter variable), but usually you'll want to use a Range Expression like zwol said.
I like this form, since it keeps the increment at the top of the loop instead of the bottom:
let mut i = 2 - 1; // You need to subtract 1 from the initial value.
loop {
i+=1; if i*i >= n { break }
// code goes here...
}

In between loop iteration syntax

In most languages, if you want to perform an action only between loop iterations you have to write something like the following:
for item in items:
*DO SOMETHING HERE*
if item is last in list:
DON'T DO/UNDO THE IN-BETWEEN ACTION
That last if statement if quite messy and not always obvious how to achieve, especially in for-each loops.
I'm wondering if there's a syntax in a particular language that allows you to execute statements only if execution is in between loop iterations.
Instead of running the "in-between task" at the end of the loop, you could do it at the beginning.
It becomes easier since you only have to check if the iteration is the first or not, which you can easily achieve with a boolean flag or an integer, like in the example below.
let i = 0;
for (let x of [1,2,3,4]) {
if (i++ > 0) {
console.log('*');
}
console.log(x);
}

Syntax/concept of a non-iterated loop?

I'm trying to iterate through a loop (any programming language, really, but for this exercise I happen to be using c#) and I was just wondering... what happens when you try to use a loop that doesn't iterate at all (i.e. ...."null"?)
For example:
int x = choose(0,1,2);
for(int i=0;i<x;i++) {
//some stuff
}
Like, what would happen if x gets chosen to be 0? Does it just become a useless for loop on that case? Will my program crash? Is that bad programming practice? etc. etc.
I'm mainly asking because I'm trying to format a concatenated string but only if some array has enough elements. thanks
Well simply put, nothing will happen. A for loop is like an if statement where it checks the condition and repeats while that condition is true.
for(int i=0;i<x;i++)
This is saying:
Initialize i to 0
Check if i is less than the value of x
Increment i at the end of the loop
If x is 0, then the loop will simply not run; it becomes useless.

End condition of an IF loop that depends on a 3D array

I'm writing a program which will move a particle about a cube, either left,right,up,down, back or forward depending on the value randomly generator by the program. The particle is able to move with cube of dimensions LxLxL. I wish the program to stop when the particle has been to all possible sites and the number of jumps taken output.
Currently I am doing this using an array[i][j][k] and when the particle has been to a position, changing the value of the array at that corresponding point to 0. However, in my IF loop I have to type out every possible combination of i,j and k in order to say if they are all equal to 0 the program should end. Would there be a better way to do this?
Thanks,
Beth
Yes. I'm assuming the if in question is the one contained within the triple nested loop who's body sets finish=1;. The better way of doing this is to set a your flag before the loop, beginning with a true value then setting it to false and breaking if you encounter a value other then zero. Your if statement becomes much simpler, like this;
int finish =1; // start with a true value
//loops are untouched so still got the for i and for j above this
for(k = 0; k < 15; k++)
{
if (list[i][j][k] != 0)
{
finish = 0;
break;
}
}
// outside all the loops
return finish;
I think this is what you're asking for but if not please edit your question to clarify. I'm not sure if there is some technical name for this concept but the idea is to choose your initial truth value based on what's most efficient. Given you have a 15x15x15 array and a single non-zero value means false, it's much better to begin with true and break as soon as you encounter a value that makes your statement false. Trying to go in the other direction is far more complicated and far less efficient.
Maybe you can add your list[i][j][k] to a collection every time list[i][j][k]=0. Then at the end of your program, check for the collection's length. If it's of the right length, then terminate..

Resources