While loop not exiting after condition met (Ruby) - ruby

I'm not a skillful programmer by any means, but everyone's got to start somewhere.
I've been trying to make a (very) basic maze-type in ruby, but I'm having difficulty with the while loop not exiting.
Room layout is an upside down t:
5
2
103
4
Going north twice from the center should change #loc to 5, say "End", and exit the loop:
elsif #loc == 2
#loc = 5
puts "End"
But it returns to the beginning of the while loop, stranding the player.
EDIT: there's some confusion about the code, so I'm removing the block and pointing you to
http://pastebin.com/EFWVBAhn

The line
while #loc != 5
is accessing a variable which is not being changed. The changes are happening to cmd.loc, which is not the same variable. That line needs to be
while cmd.loc != 5
in order to access the variable.
Also you need to quote your strings (e.g. if command == west should be if command == "west"); otherwise you're telling Ruby to compare to a variable called west, which doesn't exist, rather than the string "west".

Related

Expressing "equals" in pseudocode

I was just wondering if there is a special way of saying when something equals something. For example in python, if you declare something equals 2, you say something = 2, whereas when you check if something equals something else, you would say:
if something == somethingelse:
So my question is in pseudocode for algorithms if I'm checking to see if a entered password equals a stored password in an IF THEN ELSE ENDIF loop, would I use one or two equal signs:
WHILE attempts < 3
Get EnteredPassword
**IF EnteredPassword = StoredPassword THEN**
Validated = TRUE
ELSE
attempts = attempts + 1
ENDIF
ENDWHILE
Usually, pseudocode is very broad and every author has their own way of expressing it. As
Aziz has noted, usually x <- 1 is used for an assignment and x := x + 1 for an update. Read ':=' as 'becomes' instead of 'equals', however, they are interchangeably used. As for your question, both = and == are accepted answers, as long as it is clear to your reader what your intention is.
To express equals you use the equal mark symbol once, unlike in python where you use the symbol twice to compare two values (eg if variable == 'one'). An example syntax is:
variable = 'one'
WHILE variable = 'one' DO
SEND "hi" TO DISPLAY

Python 2, raw_input in define function. Returning value

I decided to have a little bit fun with coding python 2 in a long while and decided to try make somewhat playable game of Go.
I quickly tumbled on this issue while trying to make function for the game, it seems like I'm not understanding how raw_input or functions work fundamentally. I cut the part of the code that is giving me the trouble here. When I try to run this, I can get to give inputs, but after that I get NameError: name 'crd_x' is not defined, in the stoneplacement line. The code does work without using the function, but when I try to clean it up like this, I get the said error.
What exactly does return crd give out and how I'm actually supposed to give out variables from def functions?
def checkplayerinput():
if player_on_turn == 0:
crd = raw_input("Place Black stone (X-Y): ").split("-")
elif player_on_turn == 1:
crd = raw_input("Place White stone (X-Y): ").split("-")
crd_x = int(crd[1])
crd_y = int(crd[0])
return crd_x, crd_y
def stoneplacement(crd_x, crd_y, player_on_turn):
if board[crd_x][crd_y] == "+" and player_on_turn == 0:
board[crd_x][crd_y] = "B"
elif board[crd_x][crd_y] == "+" and player_on_turn == 1:
board[crd_x][crd_y] = "W"
stop = 0
while stop == 0:
#User input and derive coordinates
checkplayerinput()
# Stone placement
stoneplacement(crd_x, crd_y, player_on_turn)
edit. just switched the place of crd_x and crd_y like they are in the actual code. It produces exact same NameError however.
So crd is going to give you an array of strings based on whatever the user types in, separated by the ‘-‘ symbols. For example if player_on_turn == 0, and you entered for example “X-Y” (whatever your game calls for), checkplayerinput() would return crd as [“X”, “Y”].
Also, remember that an array is indexed starting at 0. So in this example, crd[0] == “X”.
Running through your code, does that explain why your stoneplacement() function throws a NameError? I.e. are you inputting the right raw_input to yield crd[1]?
Also, did you define crd before def checkplayerinput() in the code? According to python scope rules, if you define the variable crd inside of the function, it will not have a global value outside of it (and will throw an error if you reference it in another function). This is likely why you are able to run your code without the function definitions. Try adding a line “global crd” or “crd = [ ]” somewhere outside of the function and it will allow you to access crd in the stoneplacement(( function.

How to escape from a recursive method in ruby

I created a recursive function that tries to parse the information from the parsed list. It's kind of hard to explain, but it's something like
In a parse function that parses either a wikipedia Movie page or an Actor page, starts by parsing a filmography list from a wikipedia actor page -> call the same function on the parsed list -> repeat
I set a global variable that counts the number of iterations, but when I try to break out from the function and move on to the next step by doing,
if $counter > 10
return nil
end
but it does not immediately ends since there are still functions to be called left (since it's recursive). I tried to use "abort" but this one just terminated the program instead of moving on to the next one.
Is there a way to immedately stop the recursive run and move on to the next step without aborting the program?
A bit hard to answer without more code. But i guess you looking for next or break to jump out of recursiveness.
next
Jumps to the next iteration of the most internal loop. Terminates execution of a block if called within a block (with yield or call returning nil).
for i in 0..5
if i < 2 then
next
end
puts "Value of local variable is #{i}"
end
Result:
Value of local variable is 2
Value of local variable is 3
Value of local variable is 4
Value of local variable is 5
break
Terminates the most internal loop. Terminates a method with an associated block if called within the block (with the method returning nil).
for i in 0..5
if i > 2 then
break
end
puts "Value of local variable is #{i}"
end
Result:
Value of local variable is 0
Value of local variable is 1
Value of local variable is 2

Calculating year dummy variables using a for loop (foreach) in Stata

I am attempting to generate a dummy variable for each year from 1996 to 2012 (inclusive) such that the 1996 dummy should equal 1 if it is 1996 and 0 if else using the foreach command in Stata to cut down on time (at least for future projects). What is currently happening is that the dummy for 1996 is being produced, but no others are generated.
I think that it has to do with how I am defining j, but I cannot quite figure out the formatting to achieve the results that I want. I have looked online and in the Stata help files and cannot find anything on this specific topic.
Here is what I have thus far:
local var year
local j = 1996
foreach j of var year {
gen d`j' = 1 if year==`j'
local ++j
}
I will continue to try and figure this out on my own, but if anyone has a suggestion I would be greatly appreciative.
Let us look at this line by line.
local var year
You defined a local macro var with content "year". This is legal but you never refer to that local macro in this code, so the definition is pointless.
local j = 1996
You defined a local macro j with content "1996". This is legal.
foreach j of var year {
You open a loop and define the loop index to be j. That means that within the loop any reference to local macro j will be interpreted in terms of the list of arguments you provide. (The previous definition of j is irrelevant within the loop, and so has no effect in the rest of your code.)
... of var year
You specify that the loop is over a variable list here. Note that the keyword var here is short for varlist and has absolutely nothing to do the local macro name var you just defined. The variable list consists of the single variable name year.
gen d`j' = 1 if year==`j'
This statement will be interpreted, the one and only time the loop is executed, as
gen dyear = 1 if year==year
as references to the local macro j are replaced with its contents, the variable name year. year==year is true for every observation. The effect is a new variable dyear which is 1 in every observation. That is not an indicator or dummy variable as you want it. If you look at your dataset carefully, you will see that is not a dummy variable for year being 1996.
local ++j
You are trying to increment the local macro j by 1. But you just set local macro j to contain the string "year", which is a variable name. But you can't add 1 to a string, and so the error message will be type mismatch. You don't report that error, which is a surprise. It is a little subtle, as in the previous command the context of generate allows interpretation of the reference to year as an instruction to calculate with the variable year, which is naturally numeric. But local commands are all about string manipulation, which may or may not have numeric interpretation, and your command is equivalent, first of all, to instructing Stata to add
"year" + 1
which triggers a type mismatch error.
Turning away from your code: Consider a loop
forval y = 1996/2012 {
gen d`y' = 1 if year == `y'
}
This is closer to what you want but makes clearer another bug in your code. This would create variables d1996 to d2012 but each will be 1 in the year specified but missing otherwise, which is not what you want.
You could fix that by adding a further line in the loop
replace d`y' = 0 if year != `y'
but a much cleaner way to do it is the single line
gen d`y' = year == `y'
The expression
year == `y'
is evaluated as 1 when true and 0 when false, which is what you want.
All this is standard technique documented in [U] or [P].
As #Roberto Ferrer pointed out, however, experienced Stata users would not define dummies this way, as tabulate offers an option to do it without a loop.
A tutorial that brings together comments on local macros, foreach and forvalues loops is within http://www.stata-journal.com/sjpdf.html?articlenum=pr0005
search foreach
within Stata would have pointed to that as one of various pieces you can read.
Looping is not necessary. Try the tabulate command with the gen() option. See help tabulate oneway.
See also help xi and help factor variables.
You are trying to loop through the distinct values of year but the syntax is not correct. You are actually looping through a list of variables with only one element: year. The command levelsof gives you the distinct values, but like I said, looping is not necessary.
Maybe this might help.
/*assuming the data is from 1970-2012*/
/*assuming your year variable name is fyear*/
forvalues x=1970/2012 {
gen fyear `x'=0
replace fyear `x'=1 if fyear==`x'
}
However, I do agree with Roberto Ferrer that loop may not be necessary.

Confused by this unless statement in rubykoans

Lines 4 & 5 are causing me grief:
1 def test_break_statement
2 i = 1
3 result = 1
4 while true
5 break unless i <= 10
6 result = result * i
7 i += 1
8 end
9 assert_equal 3628800, result
10 end
I'm not sure what needs to remain true in the while true statement, however I believe it is the code that follows it. This leads to further confusion because I am reading the line:
break unless i <= 10 as break if i is not smaller or equal to 10. What procedure is this code going through ie how does the while and break statements interplay. I think I am nearly there but can't put the process in my head. Thanks.
The code will break out of the endless while loop when i is greater than 10.
But I'm not sure why the condition isn't checked in the while statement.
Edit: Had I read the method name I would have understood why the condition isn't checked directly with the while statement. The method's purpose is to test the break statement.
while statements test whatever comes after the word while. If the expression that follows them is true they execute the code within the loop. If the expression is false, they do not.
Thus, as other posters have pointed out, while true will always execute the code within the loop. Luckily for your code there is a break statement within the loop. If there wasn't, the loop would run forever and you'd have to kill the process running your program.
In your code sample the break keyword is followed by unless which means that it will break the loop unless the expression following it is true. Your code will break out of the loop when i is greater than 10.
while true is an infinite loop. break, when executed, will exit it immediately, to continue with the first line after it (assert_equal...).
In this specific case (nothing intervening between while and break unless), it is equivalent to this:
while i <= 10
result = result * i
i += 1
end
while true it is endless loop.
break unless i <= 10 is same as break if i > 10 it will break that loop if i is smaller or equal to 10

Resources