Decrementing a loop counter as loop is executing - for-loop

I'm trying to decrement the counter of a for loop as the loop is running. Unfortunately, Lua doesn't seem to allow that. This piece of code should run forever:
for i = 1, 100 do
print (i)
i = i - 1
end
but it does, in fact, simply print the series 1-100. Is that by design? If so, how do I decrement the counter of a running loop (for example because the current cycle was disqualified and should run again)?

It's by design. From Lua reference manual:
3.3.5 – For Statement
All three control expressions are evaluated only once, before the loop starts. They must all result in numbers.
So modifying the value of i inside the loop won't change how the loop runs.

for i = 10, 1, -1 do
print(i)
end
If you want to step backwards through a table then do:
for i = #SomeTable, 1, -1 do
print(SomeTable[i].someproperty)
end

Yu Hao above linked to the correct manual page, but quoted the wrong part of it.
Here is the correct quote
for v = e1, e2, e3 do block end
is equivalent to the code:
do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and limit and step) then error() end
while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
local v = var
block
var = var + step
end
end
[..]
var, limit, and step are invisible variables. The names shown here are for explanatory purposes only.
In other words, the variable that's being looped over (called "var" above) and the variable exposed to the developer (called "v" above) are different. There is no way to access the former.

Related

Understanding this Ruby program concerned with prime numbers

This is a program that came from a textbook:
# Initialize our counter
i = 1
# i: [0, 100]
while (i <= 100)
# Initialize prime flag
prime_flag = true
j = 2
# Test divisibility of i from [0, i/2]
while (j <= i / 2)
# puts " i ==> " to i.to_s + " j ==> " + j.to_s
if (i % j == 0)
prime_flag = false
# break
end
j = j + 1
end
# We found a prime!
if prime_flag
puts "Prime ==> " + i.to_s
end
# Increment the counter
i += 1
end
The while (j <= i / 2) introduces a new loop. What if we are trying to find prime numbers. Why is this written? Prime numbers don't have square roots. What is the purpose of j being <= i / 2? I do not understand why j is introduced.
You are correct that you should be only checking numbers <= floor(sqrt(i)). The above code is unnecessarily checking numbers from ceil(sqrt(i)) through i/2. It would give the correct answer, however.
In addition, this is not very Ruby-like code. It's terrible and the author should feel terrible (unless they intended to show you something bad in order for you to be amazed when you see how you can write it better!).
Here's the same code done in a more Ruby-like manner. Note that prime? can definitely be a one-liner, but I split things on to more lines readability in the context of the question:
def prime?(i) # Define a function that takes 1 parameter `i`
MAX_NUM_TO_CHECK = Math.sqrt(i) # No need to check numbers greater than sqrt(i)
(2..MAX_NUM_TO_CHECK).all? do |j| # Return `true` if the following line is true for
# all numbers [2,MAX_NUM_TO_CHECK]
i % j != 0 # true if `i` is evenly not divisible by `j`. Any
# input that evaluates to false here is not prime.
end
end
# Test primality of numbers [1,100]
(1..100).each {|n| puts "Prime ==> #{n}" if prime? n}
I think the biggest differences between your book and this code are:
The algorithm is different in that we do not check all values, but rather limit the checks to <= sqrt(i). We also stop checking once we know a number is not prime.
We iterate over Ranges rather than keeping counters. This is slightly higher level and easier to read once you get the syntax.
I split the code into two parts, a function that calculates whether a parameter is prime or not, and then we iterate over a Range of inputs (1..100). This seems like a good division of functionality to me, helping readability.
Some language features used here not in your example:
If statements can go after expressions, and the expression is only evaluated if the predicate (the thing after the if) evaluates to true. This can make some statements more readable.
A range is written (x..y) and allows you to quickly describe a series of values that you can iterate over without keeping counters.
Code inside
do |param1, ..., paramN| <CODE>; end
or
{|param1, ..., paramN| <CODE>}
is called a block. It's an anonymous function (a function passed in as a parameter to another function/method). We use this with all? and each here.
each is used to run a block of code on each element of a collection, ignoring the return value
all? can be used to determine whether a block returns true for every item in a collection.
If you're not familiar with passing code into functions, this is probably a little confusing. It allows you to execute different code based on your needs. For example, each runs the yielded block for every item in the collection.You could do anything in that block without changing the definition of each... you just yield it a block and it runs that block with the proper parameters. Here is a good blog post to get you started on how this works and what else you can use it for.

How to remove several columns from a matrix

Integer :: NBE,ierr,RN,i,j
Real(kind=8), allocatable :: AA1(:,:),AA2(:,:)
NBE=40
RN=3*NBE-2
Allocate(AA1(3*NBE,3*NBE),AA2(3*NBE,RN),stat=ierr)
If (ierr .ne. 0) Then
print *, 'allocate steps failed 1'
pause
End If
Do i=1,3*NBE
Do j=1,3*NBE
AA1(i,j)=1
End Do
End Do
I want to remove columns 97 and 113 from the matrix AA1 and then this matrix becomes AA2. I just want to know if any command of Fortran can realize this operation?
Alexander Vogt's answer gives the concept of using a vector subscript to select the elements of the array for inclusion. That answer constructs the vector subscript array using
[(i,i=1,96),(i=98,112),(i=114,3*NBE)]
Some may consider
AA2 = AA1(:,[(i,i=1,96),(i=98,112),(i=114,3*NBE)])
to be less than clear in reading. One could use a "temporary" index vector
integer selected_columns(RN)
selected_columns = [(i,i=1,96),(i=98,112),(i=114,3*NBE)]
AA2 = AA1(:,selected_columns)
but that doesn't address the array constructor being not nice, especially in more complicated cases. Instead, we can create a mask and use our common techniques:
logical column_wanted(3*NBE)
integer, allocatable :: selected_columns(:)
! Create a mask of whether a column is wanted
column_wanted = .TRUE.
column_wanted([97,113]) = .FALSE.
! Create a list of indexes of wanted columns
selected_columns = PACK([(i,i=1,3*NBE)],column_wanted)
AA2 = AA1(:,selected_columns)
Here's a simple one liner:
AA2 = AA1(:,[(i,i=1,96),(i=98,112),(i=114,3*NBE)])
Explanation:
(Inner part) Construct a temporary array for the indices [1,...,96,98,...,112,114,...,3*NBE]
(Outer part) Copy the matrix and only consider the columns in the index array
OK, I yield to #IanBush... Even simpler would be to do three dedicated assignments:
AA2(:,1:96) = AA1(:,1:96)
AA2(:,97:111) = AA1(:,98:112)
AA2(:,112:) = AA1(:,114:)
I don't have a fortran compiler here at home, so I cant test it. But I'd do something line this:
i = 0
DO j = 1, 3*NBE
IF (j == 97 .OR. j == 113) CYCLE
i = i + 1
AA2(:, i) = AA1(:, j)
END DO
The CYCLE command means that the rest of the loop should not be executed any more and the next iteration should start. Thereby, i will not get incremented, so when j=96, then i=96, when j=98 then i=97, and when j=114 then i=112.
A few more words: Due to Fortran's memory layout, you want to cycle over the first index the fastest, and so forth. So your code would run faster if you changed it to:
Do j=1,3*NBE ! Outer loop over second index
Do i=1,3*NBE ! Inner loop over first index
AA1(i,j)=1
End Do
End Do
(Of course, such an easy initialisation can be done even easier with just AA1(:,:) = 1 of just AA1 = 1.

About the inject method: How does it work?

This part of code calculates the value of each arithmetic series up to and including the number that the user put in:
print "enter a number: "
num = gets.to_i
(1..num).inject(0) do |res, e|
res += e
p res
end
I think that (1..num) is the range, with num being the user input. I know that inject combines all elements of enum by applying a binary operation specified by a block or a symbol that names a method or operator.
I don't understand what each element in this line does:
(1..num).inject(0) do |res, e|
What does |res, e| mean? It must be the block that defines what inject does, but what does for instance res and e stand for? (e is probably element?)
What does (0) stand for?
What does the command do do?
what is its connection in regard to (1..num) and inject(0)?
Am I right to assume that p at the end just stands for puts or print?
inject takes an optional start value, and a block taking an intermediate value and element and returning a new intermediate value.
So:
What does (0) stand for?
The start value parameter to inject.
What does the command "do" do?
It is not a command; it marks the start of the block (terminated by end). .inject(0) do ... end is almost (except for some syntactic issues) the same as .inject(0) { ... }. Usually, do ... end is used for multi-line blocks and { ... } for single-line blocks, but it is not a rule.
What does |res, e| mean?
Those are the block parameters (intermediate value and current element), here probably called after "result" and "element", respectively.
Let's see on a simplified example: (1..3).inject(0) do |res, e| res + e end will set the intermediate result to 0. Then it will pass this intermediate result and the first element of the enumerable being injected: res is 0 and e is 1. The value of the block is the value of its last expression, which is 1 (result of 0 + 1). This 1 now becomes the new intermediate value, and 2 becomes the next current element. The value of the block is 3 (result of 1 + 2). In the next iteration, intermediate value is 3, and the current element also 3, resulting in 6 (3 + 3). The range will stop yielding elements now that we reached its upper boundary, and inject returns with the last intermediate result calculated, 6.
Also, the last question am I right to assume that "p" at the end just stands for puts or print?
Almost. p is its own beast. p x is roughly synonymous with puts x.inspect; x - i.e. it prints the value in a bit different format, and unlike puts which always returns nil, p returns the value unchanged. Thus, p res at the end of your block will not destroy the code by making it return nil, but transparently return res.
inject is a method that boils a collection (eg an array or range) down to a single value. It does this by executing the block once for each element in the collection. The block takes two arguments: the current value being worked on, and the single value that will eventually be returned. inject itself takes one argument (aside from the block), which is its initial starting value.
Take this example.
x = [1, 2, 3, 4, 5].inject(0) do |result, current|
result + current
end
We have a list of numbers, [1, 2, 3, 4, 5]. We're going to boil them down into one single number.
We start with 0, because that's inject's argument. That means that the first time the block runs, result will be 0.
So the block runs for the first time. result is 0, current is 1, the first element. We say result + current (which is 1). It's the last expression inside the block, so it's what that block 'returns'.
At the end of the block, inject says "Okay, do we have more elements in the collection?" Yeah. So the block runs again. This time, result is whatever the last block returned, which was 1, and current is the second element, 2.
The block runs, and finishes with result + current, or 1 + 2, which is 3. There are still elements left, so we run again. This time, result is 3, and current is 3. result + current, 6. Still more values to go, on the next run result is 6 and current is 4. 6 + 4 = 10. Still more values to go, on the next run result is 10 and current is 5. 10 + 5 = 15.
Then the block finishes, and there are no more elements left. So inject itself returns with the final value, 15. So in the end, x = 15. We boiled down our list into one number by adding things up.
res in your example stands for result, and e for element. You can call them anything you want. You might call them sum while adding, or product if multiplying. But they don't have to be numbers. You could use inject to boil an array of strings, a range of characters, an array of arrays, whatever collection you want. The block just tells it how.
Excited to see that you're learning Ruby, welcome!
At your level of expertise best learn from a book.
Get yourself a copy of the "Pickaxe Book" — this is by far the best book.
The first edition fir Ruby 1.9 is available online, http://ruby-doc.com/docs/ProgrammingRuby
And here is a popular online tutorial, http://poignant.guide
Some quick answers
1..num is a range object
.inject(0) do ... end is a method call with TWO parameters, the value 0 and a code block
do |a, b| ... end is a code block with two parameters
res and e are VERY bad variable names, maybe better use sum and each?
p is a global method that prints debug information, similar to puts but not the same
Hope that helps to unblock you.

'For' loop pre and post empty statements

What does it mean in Go that the pre and post statements of a for loop are empty, like in the following example?
sum := 1
for ; sum < 10; {
sum += sum
}
fmt.Println(sum)
Remember that a for loop is the same as a while loop.
Your code can be rewritten in other languages as
sum := 1
while(sum < 10) {
sum += sum
}
fmt.Println(sum)
In a for loop, there are 3 parts.
for(initial statement ; condition ; end statement usually iterate)
This is equivalent to
initial statement
while(condition) {
Stuff here
End iteration statement
}
The reason your loop can be written withiut the pre and post statements is because you've specified them in other parts of the code.
It behaves like a while in other languages. You don't need the two semicolons:
sum := 1
for sum < 10 {
sum += sum
}
fmt.Println(sum)
A for loop has three elements: initialization statement, condition check, and variable change.
for <initialization statement>; <condition check>; <variable change>{
<actual body>
}
The initialization statement is executed only once when the loop starts. Based on the name, it initializes something (in a lot of cases a variable you iterate through). If it is omitted, then it does nothing
The condition check verifies whether the condition evaluates to true. If it is not, the loop stops. If it is omitted, then it is always true.
The variable change is modifying variables during each iteration of the loop. Most of the time, the iterated variable is increased/decreased, but you can do whatever you want. If it is omitted, it does nothing
After this explanation, you can see that this loop does nothing during your initialization and post condition phase.
You also do not need to use semicolons here. This will be enough.
sum := 1
for sum < 10 {
sum += sum
}
You can even write a loop like this: for {} which will never stop executing, or do something like a while loop:
t := 10
for t > 0{
t--
}
Note that inside your initialization, condition, and change phase you can use many expressions (not just one). So with a simple while loop you can do something like:
for f1, f2, n := 1, 1, 10; n > 0; f1, f2, n = f2, f1 + f2, n - 1{
fmt.Println(f1)
}
which creates Fibonacci numbers—see Go Playground. Showing this not because this is the best way to write it, but rather because it is possible.

For Loop: can the end value come from the value of a variable?

I have a forvalues loop:
forvalues x = 1(1)50 {
/* Code goes here */
}
Instead of 50, ideally, I would like that value to come as follows. I have a variable name. Let length = length(name). Whatever the largest value is for length, I would like that to be in place of the 50. I could not figure how to write a forvalues loop in which the end point was not directly stated numerically.
I am thinking that I could deduce the maximum length of the variable as follows:
gen id = 1
gen length = length(name)
by id, sort: egen maxlength = max(length)
From there though I do not know how to store this value into the for loop.
Alternatively, would this be better coded by a while loop?
Something like:
gen x = 1
while (x <= maxlength) {
/* Same Code Here */
replace x = x + 1
}
Based on the documentation I've read, it is possible to use macros but with the caveat that changing the end of the range within the forvalues loop has no effect on the number of times the loop will occur. For instance, if length(name) is 50 when the forvalues loop starts, and you change the length of name within the loop, it will still only loop 50 times.
Technically, you'd be better off using a while loop since forvalues was intended to be used when the end of the range is a literal value. You can use a forvalues loop, but you should use a while loop.
Here's my source to back this up:
http://www.stata.com/manuals13/pforvalues.pdf
Specifically:
Technical note
It is not legal syntax to type
. scalar x = 3
. forvalues i = 1(1)x' {
2. local x =x' + 1
3. display `i'
4. }
forvalues requires literal numbers. Using macros, as shown in the following technical note, is
allowed.
And:
Using macros, as shown in the following technical note, is
allowed.
Technical note
The values of the loop bounds are determined once and for all the first time the loop is executed.
Changing the loop bounds will have no effect. For instance,
will not create an infinite loop. With `n' originally equal to 3, the loop will be performed three
times.
local n 3
forvalues i = 1(1)`n' {
local n = `n' + 1
display `i'
}
Output:
1
2
3
Here is the trick with Stata which I think may work for you. I am using the data auto from Stata datasets.
sysuse auto
Suppose the variable name here be price. Now you want the length of variable price.
sum price
gen length=r(N)
To see what is r(N) type return list after running the sum price.
In your loop it goes like follows: (Updated as per #Nick)
forvalues x = 1/`r(N)'{
/* Code goes here */
}
OR:
local length=r(N)
forvalue i=1/`length'{
dis "`i'"
}
Note: It is not clear why you want for loop.So my answer is restricted to what you only asked for.
#Metrics' first code won't quite work. Here is a better way, cutting out what I call the middle macro.
Start with something more like
. su price, meanonly
. forval j = 1/`r(N)' {
An equivalent approach to the one proposed by #Nick and #Metrics is the following:
sysuse auto, clear
count if !missing(price)
forvalues x = 1 / `r(N)' {
/* Code goes here */
}

Resources