Why are loops executed one more time than the loop body? - algorithm

A quote from an Algorithms textbook:
"When a for or while loop exits in the usual way (i.e., due to the test in the loop header), the test is executed one time more than the loop body."
So, for example, a for loop that begins with for j=1 to 3 will be executed not 3 times, but 4 times!
Question: Why would such a loop be executed 4 times and not 3 times?
By my reasoning:
When j = 1, the loop is executed.
When j = 2, the loop is executed.
When j = 3, the loop is executed.
When j = 4, the loop is NOT executed.
I count 3, not 4.

I think you are confused about what the statement in the book states
When a for or while loop exits in the usual way (i.e., due to the test in the loop header), the test is executed one time more than the loop body.
This means that the loop condition will be tested one more time than the loop body therefore by your example:
for j = 1:3
j = 1, pass and looped
j = 2, pass and looped
j = 3, pass and looped
j = 4, failed and code executes as written

Here's the pseudo machine code for a for...loop
// int result = 0;
// for(int x = 0; x < 10; x++) {
// result += x;
// }
MOV edx, 0 // result = 0
MOV eax, 0 // x = 0
.ForLoopLabel:
CMP eax, 10 // FillFlags(x - 10)
JGE .ForLoopFinishedLabel // IF x >= 10 THEN GoTo ForLoopFinishedLabel
// for loop's body
ADD edx, eax // result += x
// end of body
ADD eax, 1 // x++
JMP .ForLoopLabel // GoTo ForLoopLabel
.ForLoopFinishedLabel:

Related

how to iterate one value twice in for loop (Python)

I am having a problem in really simple program. My problem is that i lose value (y = 50 or 100 or 150) because at that time first condition is not valid. so how can i repeat loop for let say y = 50. (i don't want to use '=' e.g y< = (50+increment) because this is just a dummy program.
thanks
increment = 0
b = 1
var = 0
for y in range(1,1000):
if y>= increment and y< (50+increment):
print(f'{y} in List {b}')
else:
var = y
increment += 50
b+=1

Erroneous dynamic programming algorithm

Transferred from Code Review. If this question is not suitable for SO either, please let me know. I will remove it.
I am working on an algorithm puzzle here at: https://www.hackerrank.com/challenges/hackerland-radio-transmitters/forum
It cannot pass all of the test cases. Some test cases have such large arrays that it gets so hard to debug. Simple cases from my end seem all work fine. Can anyone look into this and share what is wrong with this algorithm? Basically it just loops through the array and find every furthest covered station (as origin). A counter-like variable result record the origins (radio stations).
def solution(k, arr, origin=0):
arr = sorted(list(set(arr)))
result = 1
cur = 0
origin = 0
for i in range(1, len(arr)):
if arr[i] - arr[origin] <= k:
pass
else:
origin = i - 1
j = 1
while origin + j < len(arr):
if arr[origin + j] - arr[origin] <= k:
pass
else:
origin = origin + j
i = origin + j + 1
result += 1
continue
j += 1
return result
Most of your code is correct. Only problem is with the usage of For range outer loop and continue in the inner loop.
For range loop doesn't change the i value # runtime (it is more like a ForEach loop).
The continue will not terminate the inner loop - you may want to use break.
The following code passed all the test cases
def solution(k, arr, origin=0):
arr = sorted(list(set(arr)))
print arr
result = 1
cur = 0
origin = 0
i = 0
while (i < len(arr)):
if arr[i] - arr[origin] <= k:
i = i + 1
pass
else:
origin = i - 1
j = 1
while origin + j < len(arr):
if arr[origin + j] - arr[origin] <= k:
pass
else:
# Start for next station position from this point
i = origin + j
origin = i
# need another radio station
result += 1
break
j += 1
return result
hope it helps!
You're placing the first object on the first index. The first object in the optimal solution can be placed later too.
solution(1,[1,2,3,4,5,6]) prints 3, when it should be 2 (by placing the two objects on 2 and 5). You place your first object on 1, then 3 and then 5. It should ideally be placed on 2, then 5.

Bignum too big to convert into 'long' (RangeError)

Trying to teach myself ruby - I'm working on Project Euler problem 14 in ruby.
n = 1000000
array = Array.new(n,0)
#array[x] will store the number of steps to get to one if a solution has been found and 0 otherwise. x will equal the starting number. array[0] will be nonsensical for these purposes
i = n-1#We will start at array[n-1] and work down to 1
while i > 1
if array[i] == 0
numstep = 0 #numstep will hold the number of loops that j makes until it gets to 1 or a number that has already been solved
j = i
while j > 1 && (array[j] == 0 || array[j] == nil)
case j%2
when 1 # j is odd
j = 3*j + 1
when 0 # j is even
j = j/2
end
numstep += 1
end
stop = array[j] #if j has been solved, array[j] is the number of steps to j = 1. If j = 1, array[j] = 0
j = i
counter = 0
while j > 1 && (array[j] == 0 || array[j] == nil)
if j < n
array[j] = numstep + stop - counter #numstep + stop should equal the solution to the ith number, to get the jth number we subtract counter
end
case j%2
when 1 #j is odd
j = 3*j+1
when 0 #j is even
j = j/2
end
counter += 1
end
end
i = i-1
end
puts("The longest Collatz sequence starting below #{n} starts at #{array.each_with_index.max[1]} and is #{array.max} numbers long")
This code works fine for n = 100000 and below, but when I go up to n = 1000000, it runs for a short while (until j = 999167 *3 + 1 = 2997502). When it tries access the 2997502th index of array, it throws the error
in '[]': bignum too big to convert into 'long' (RangeError)
on line 27 (which is the while statement:
while j > 1 && (array[j] == 0 || array[j] == nil)
How can I get this to not throw an error? Checking if the array is zero saves code efficiency because it allows you to not recalculate something that's already been done, but if I remove the and statement, it runs and gives the correct answer. I'm pretty sure that the problem is that the index of an array can't be a bignum, but maybe there's a way to declare my array such that it can be? I don't much care about the answer itself; I've actually already solved this in C# - just trying to learn ruby, so I'd like to know why my code is doing this (if I'm wrong about why) and how to fix it.
The code above runs happily for me for any input that produces output in acceptable time. I believe this is because you might experience problems being on 32bit arch, or like. Anyway, the solution of the problem stated would be simple (unless you might run out of memory, which is another possible glitch.)
Array indices are limited, as is follows from the error you got. Cool, let’s use hash instead!
n = 1000000
array = Hash.new(0)
#array[x] will store the number of steps to get to one if a solution has been found and 0 otherwise. x will equal the starting number. arr
i = n-1#We will start at array[n-1] and work down to 1
while i > 1
if array[i].zero?
numstep = 0 #numstep will hold the number of loops that j makes until it gets to 1 or a number that has already been solved
j = i
while j > 1 && array[j].zero?
case j%2
when 1 # j is odd
j = 3*j + 1
when 0 # j is even
j = j/2
end
numstep += 1
end
stop = array[j] #if j has been solved, array[j] is the number of steps to j = 1. If j = 1, array[j] = 0
j = i
counter = 0
while j > 1 && array[j].zero?
if j < n
array[j] = numstep + stop - counter #numstep + stop should equal the solution to the ith number, to get the jth number we
end
case j%2
when 1 #j is odd
j = 3*j+1
when 0 #j is even
j = j/2
end
counter += 1
end
end
i = i-1
end
puts("Longest Collatz below #{n} ##{array.sort_by(&:first).map(&:last).each_with_index.max[1]} is #{arr
Please note, that since I used the hash with initializer, array[i] can’t become nil, that’s why the check is done for zero values only.

Tracing this algorithm, is my trace right?

For a classwork problem I am doing, I am supposed to trace (check for bugs) the following algorithm (in pseudocode):
num <- 2
count <- 1
while count < 5
{
count <- count * num
if count / 2 < 2
print "Hello"
else
while count < 7
{
count <- count + 1
}
print "The count is " + count + "."
}
When i traced this code, I got
num count output
2 1 Hello The count is 1.
My question is, was my trace right? It looks like there is something else I have to add.
When you are tracing the problem, you need to note down all value changes in the program.
In your program, we have 2 variables to trace: count and num. From the program, we can figure out 2 facts:
There is no assignment of num;
All output statements are related to count.
Therefore, we should focus on tracing the changes on count.
Notice that this block:
while count < 7
{
count <- count + 1
}
can be replaced with
if count < 7
{
count = 7
}
The workflow of the program can be depicted in English like below:
Check if count is smaller than 5, YES go to 2, NO program ends;
Double count;
If count / 2 is smaller than 2, YES go to 4, NO go to 5;
Print "Hello", go to 6;
If count is smaller than 7, set count to 7;
Print "The count is +count+.`", go to 1;
Now the task is to use 1 as initial value of count and walk through the work flow until the program terminates.
Let's do it together:
count equals to 1, so go to 2;
Now count equals to 2;
count / 2 equals to 1, which is smaller than 2, so go to 4;
Hello is printed, go to 6;
"The count is 2." is printed, go to 1;
count equals to 2, so go to 2;
Now count equals to 4;
count / 2 equals to 2, which is NOT smaller than 2, so go to 5;
count is set to 7;
"The count is 7." is printed, go to 1;
count equals to 7, so program terminates.
Therefore the output will be:
HelloThe count is 2.The count is 7.
Here is how you should walk through this.
num = 2
count = 1
while 1 < 5
{
2 = 1 * 2
if 2 /2 < 2 //since 1 < 2 print Hello
print "Hello"
else //This is skipped because the if was true
while count < 7
{
count <- count + 1
}
print "The count is " + count + "." //This prints "The Count is 2
}
Then you continue through the while loop with count = 2.
Start of second iteration.
while 2 < 5
{
4 = 2 * 2
count changes each time through the loop.

scanning binary sequences of length n with k 1's and n-k 0's

I want to write a loop that scans all binary sequences of length n with k 1's and n-k 0's.
Actually, in each iteration an action is performed on the sequence and if a criterion is met the loop will break, otherwise it goes to next sequence. (I am not looking for nchoosek or perms since for large values of n it takes so much time to give the output).
What MATLAB code do you suggest?
You could implement something like an iterator/generator pattern:
classdef Iterator < handle
properties (SetAccess = private)
n % sequence length
counter % keeps track of current iteration
end
methods
function obj = Iterator(n)
% constructor
obj.n = n;
obj.counter = 0;
end
function seq = next(obj)
% get next bit sequence
if (obj.counter > 2^(obj.n) - 1)
error('Iterator:StopIteration', 'Stop iteration')
end
seq = dec2bin(obj.counter, obj.n) - '0';
obj.counter = obj.counter + 1;
end
function tf = hasNext(obj)
% check if sequence still not ended
tf = (obj.counter <= 2^(obj.n) - 1);
end
function reset(obj)
% reset the iterator
obj.counter = 0;
end
end
end
Now you can use it as:
k = 2;
iter = Iterator(4);
while iter.hasNext()
seq = iter.next();
if sum(seq)~=k, continue, end
disp(seq)
end
In the example above, this will iterate through all 0/1 sequences of length 4 with exactly k=2 ones:
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 0
1 1 0 0

Resources