Error in my ruby code [closed] - ruby

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I can't get this code to work. Can anyone help me by pointing out the error in this code so that I can understand where I made mistakes?
STDOUT.print 'Do you wish to input another length in meters? '
more = STDIN.getString
more = STDIN.getint( );
more = more.toUpper( )
while(more[1] = 'Y')
STDOUT.puts 'Enter length in meters: '
gets(meter)
f = meter * 3.28084
feet = f.toInt
inches = (12.0 * (feet - f)).to_i
print 'The length is '
if feet = 1
STDIN.print feet + 'foot ';
else
STDOUT.print feet + 'feet '
if inches = 1
STDOUT.print inches + ' inch.\n'
else if (inches < 1)
STDOUT inches + ' inches.\n'
else
STDOUT.print '.\n'
STDOUT.print 'Do you wish to input another length in meters: '
more = STDIN.getint
end

Where do I start?
In Ruby, you need to terminate your blocks with end. You did it for while, but not for if.
Ruby uses elsif; you can't write else if.
Ruby does not have toInt; it's called to_i, as you use in the very next line
gets(meter) is an error; you need to say meter = gets
STDIN does not have getString, it has gets. It also doesn't have getint, you need to write gets.to_i.
toUpper does not exist, use upcase, as in more = more.upcase. You can also use the more readable and more efficient more.upcase!.
In if and while, you have assignment =, where you presumably want to have comparison ==.
more[1] is the second character of more; the first being more[0].
more = ... is being called twice in a row. That means the first value you input will be discarded without effect.
STDIN.print is an obvious mistake for STDOUT.print.
You can use puts "..." instead of print "...\n".
STDIN and STDOUT are redundant when you are using gets, print and others; STDIN.gets is identical to gets, STDOUT.print is identical to print.
STDOUT inches + ' inches.\n' is an obvious mistake, since STDOUT is not a function.
'.\n' contains three characters: a period, a backslash and a letter. The double-quoted ".\n" contains two: a period and a newline.
Ruby does not typically use ;, and it does not usually use empty parentheses for calling 0-parameter functions. These are just stylistic errors, and won't impact runtime.
There may or may not be more.

Related

Does ruby's case statement fall through?

I am writing a hangman game in ruby and I wanted to use a case statement to determine which body part to place corresponding to a number of incorrect guesses. I made this game using a board class I use for other games like chess and connect-4 because I have a method which serializes the board class allowing me to save and load the game without any extra code. For the game to be saved, I needed some way of determining the number of incorrect guesses for the hangman without adding extra variables to the board class. To solve this I used an instance variable on the board class called history, which can be used to push moves from the game to the boards history. When the board gets serialized, the history is saved as well, which can be read by the game and used to determine incorrect guesses.
In the hangman game, I have a method called read history (which I use for all the games since it solves the serialization issue described above). The read_history method is responsible for reading the past guesses, display them, and determine the number of incorrect guesses. This number is then passed to a hang method which determines which body parts of the hangman to add.
def hang(incorrect)
case incorrect
when 0
#hangman = [" ", " ", " "]
break
when 7
#hangman[2][2] = '\\'
when 6
#hangman[2][0] = '/'
when 5
#hangman[2][1] = '*'
when 4
#hangman[1][2] = '\\'
when 3
#hangman[1][0] = '/'
when 2
#hangman[1][1] = '|'
when 1
#hangman[0][1] = 'o'
end
end
If I were writing this in java, and a value of 5 were passed to the above method, it would read the statement until it hit "when 5" or in java terms "case 5:". It would notice that there is not a break in the statement and will move down the list executing the code in "case 4:" and repeating until a break is found. If 0 were passed however it would execute the code, see the break, and would not execute and other statements.
I am wondering if Ruby is capable of using case statements the way java does in the way that they fall through to the next statement. For my particular problem I am aware that I can use a 0.upto(incorrect) loop and run the cases that way, but I would like to know the similarities and differences in the case statement used in ruby as opposed to the switch-case used in java
No, Ruby's case statement does not fall through like Java. Only one section is actually run (or the else). You can, however, list multiple values in a single match, e.g. like this site shows.
print "Enter your grade: "
grade = gets.chomp
case grade
when "A", "B"
puts 'You pretty smart!'
when "C", "D"
puts 'You pretty dumb!!'
else
puts "You can't even use a computer!"
end
It's functionally equivalent to a giant if-else. Code Academy's page on it recommends using commas to offer multiple options. But you can still won't be able to execute more than one branch of logic.
It does not fall through.
Ruby just doesn't have the same behavior as Java for this type of statement.
If you want to simulate the fall through behavior, you can do something like this:
def hang(incorrect)
#hangman = [" ", " ", " "]
#hangman[2][2] = '\\' if incorrect > 6
#hangman[2][0] = '/' if incorrect > 5
#hangman[2][1] = '*' if incorrect > 4
#hangman[1][2] = '\\' if incorrect > 3
#hangman[1][0] = '/' if incorrect > 2
#hangman[1][1] = '|' if incorrect > 1
#hangman[0][1] = 'o' if incorrect > 0
#hangman
end

struggling with my pseudocode

I'm about to build a program written in pseudocode. I've already done most of the work , but I'm stuck on the code and I don't know what to do exactly. im a begginer and not everything is clear to me ...in one of the tasks i have to do , i have to make the program ask for the players name , which will be stored as a string then the program has to check if it exceeds the limit between 2/20 characters and inform the user if the input is wrong . i have researched and tried to figure out how i might be able to fix my code but i have a really short amount of time left and coudn't find anything regarding my problem :/ . this is the code ive done for this specific task. i know its wrong but i just dont know how to fix it . any help with be much appreciated . Thanks in advance :)
pseudocode:
// Getting user's name
valid = false
loop until valid is equal to true
Output" please enter your name "
Input playName
If (playName is => 1)AND(=<20)then
Valid = true
Otherwise
output "name exceeds the character limit"
I'm not sure what the syntax of your pseudo code is but :
assuming tabulation has meaning, you may have forgot to indent some lines to include them in the loop
'valid' is first declared with a lower case first letter so you may continue referencing it same way in line "Valid = true" -> "valid = true"
In the 'If' you want to test the lenght of the String and not compare the string to an int so maybe call a function length(String) that would return the length of the string or access a string.length attribute (as you wish in pseudo code)
You want the playName to be superior or equal to 2 "length(playName) >= 2" and inferior or equal to 20 "length(playname) <= 20"
The commonly used keyword meaning Otherwise is 'Else' as in
IF (Condition) THEN (code) ELSE (code)
I may modify you code like this :
// Getting user's name
valid = false
loop until valid is equal to true
Output" please enter your name "
Input playName
If (length(playName) >= 2) AND (length(playName) <= 20)
Then
valid = true
Else
output "name exceeds the character limit"

How do I get Ruby to search for a pattern on the tail of a local file?

Say I have a file blah.rb which is constantly written to somehow and has patterns like :
bagtagrag" " hellobello " blah0 blah1 " trag kljesgjpgeagiafw blah2 " gneo" whatttjtjtbvnblah3
Basically, it's garbage. But I want to check for the blah that keeps on coming up and find the latest value i.e. number in front of the blah.
Hence, something like :
grep "blah"{$1} | tail var/test/log
My file is at location var/test/log and as you can see, I need to get the number in front of the blah.
def get_last_blah("filename")
// Code to get the number after the last blah in the less of the filename
end
def display_the_last_blah()
puts get_last_blah("var/test/log")
end
Now, I could just keep on reading the file and performing something akin to string pattern search on the entire file again and again. Obtaining the last value, I can then get the number. But what if I only want to look at the added text in the less and not the entire text.
Moreover, is there a quick one-liner or smart command to get this?
Use IO.open to read the file and Enumerable#grep to search the desired text using a regular expression like the following code does:
def get_last_blah(filename)
open(filename) { |f| f.grep(/.*blah(\d).*$/){$1}.last.to_i }
end
puts get_last_blah('var/test/log')
# => 3
The method return the number in from of the last "blah" word of the file. It is reading the entire file but the result is the same as if is done with tail.
If you want to use a proper tail, take a look at the File::Tail gem.
I presume you wish to avoid reading the entire file each time; rather, you want to start at the end and work backward until you find the last string of interest. Here's a way to do that.
Code
BLOCK_SIZE = 30
MAX_BLAH_NBR = 123
def doit(fname, blah_text)
#f = File.new(fname)
#blah_text = blah_text
#chars_to_read = BLOCK_SIZE + #blah_text.size + MAX_BLAH_NBR.to_s.size
ptr = #f.size
block_size = BLOCK_SIZE
loop do
return nil if ptr.zero?
ptr -= block_size
if ptr < 0
block_size += ptr
ptr = 0
end
blah_nbr = read_block(ptr)
(f.close; return blah_nbr.to_i) if blah_nbr
end
end
def read_block(ptr)
#f.seek(ptr)
#f.read(#chars_to_read)[/.*#{#blah_text}(\d+)/,1]
end
Demo
Let's first write something interesting to a file.
MY_FILE = 'my_file.txt'
text =<<_
Now is the time
for all blah2 to
come to the aid of
their blah3, blah4 enemy or
perhaps do blagh5 something
else like wash the dishes.
_
File.write(MY_FILE, text)
Now run the program:
p doit(MY_FILE, "blah") #=> 4
We expected it to return 4 and it did.
Explanation
doit first instructs read_block to read up to 37 characters, beginning BLOCK_SIZE (30) characters from the end of the file. That's at the beginning of the string
"ng\nelse like wash the dishes.\n"
which is 30 characters long. (I'll explain the "37" in a moment.) read_block finds no text matching the regex (like "blah3"), so returns nil.
As nil was returned, doit makes the same request of read_block, but this time starting BLOCK_SIZE characters closer to the beginning of the file. This time read_block reads the 37 character string:
"y or\nperhaps do blagh5 something\nelse"
but, again, does not match the regex, so returns nil to doit. Notice that it read the seven characters, "ng\nelse", that it read previously. This overlap is necessary in case one 30-character block ended, "...bla" and the next one began "h3...". Hence the need to read more characters (here 37) than the block size.
read_block next reads the string:
"aid of\ntheir blah3, blah4 enemy or\npe"
and finds that "blah4" matches the regex (not "blah3", because the regex is being "greedy" with .*), so it returns "4" to doit, which converts that to the number 4, which it returns.
doit would return nil if the regex did not match any text in the file.

Can't convert String into Integer (TypeError)

I am learning Ruby
I am trying to create a simple script that will convert a given number to roman numerals (old style roman numerals)
I am unable to understand why I get the "can't convert String into Integer (TypeError)"
def convert_to_roman number
romans_array = [[1000,'M'],[500,'D'],[100,'C'],[50,'L'],[10,'X'],[5,'V'][1,'I']]
converted_array = []
romans_array.each do |rom_num|
num = rom_num[0]
letter = rom_num[1]
if number > num
times = number / num
roman_letter = letter*times
converted_array.push(roman_letter)
number = number % num
end
end
converted_array.join()
end
number = ''
puts 'please write a number and I will convert it to old style Roman numerals :)'
puts 'p.s. to exit this program simply hit enter on an empty line, or type 0 and enter :)'
while number != 0
number = gets.chomp.to_i
puts convert_to_roman number
end
My code is at:
https://github.com/stefanonyn/ruby-excercises/blob/master/roman_numerals.rb
You will see that at the end of the file commented out there is an old revision of the code, which actually does work but has a lot of repetition.
I would appreciate if someone could clarify why I get the error described above.
Please don't write the code for me, I am trying to learn Ruby, I would appreciate just some support in moving to the next step.
Thank you very much!
You are missing a comma in your array
romans_array = [[1000,'M'],[500,'D'],[100,'C'],[50,'L'],[10,'X'],[5,'V'][1,'I']]
^ here
This error is definitely not all that helpful, but the reason that it is appearing is that to the interpreter it looks like you are attempting to access a range of indexes in the [5,'V'] array for the last element. However the index's that are being provided go from 1 to 'I' which of course makes no sense. If it had been written [5,'V'][1,1] the last element of the array would be ['V'], which might have been even more confusing to debug!

Ruby: String Comparison Issues

I'm currently learning Ruby, and am enjoying most everything except a small string comparason issue.
answer = gets()
if (answer == "M")
print("Please enter how many numbers you'd like to multiply: ")
elsif (answer. == "A")
print("Please enter how many numbers you'd like to sum: ")
else
print("Invalid answer.")
print("\n")
return 0
end
What I'm doing is I'm using gets() to test whether the user wants to multiply their input or add it (I've tested both functions; they work), which I later get with some more input functions and float translations (which also work).
What happens is that I enter A and I get "Invalid answer."The same happens with M.
What is happening here? (I've also used .eql? (sp), that returns bubcus as well)
gets returns the entire string entered, including the newline, so when they type "M" and press enter the string you get back is "M\n". To get rid of the trailing newline, use String#chomp, i.e replace your first line with answer = gets.chomp.
The issue is that Ruby is including the carriage return in the value.
Change your first line to:
answer = gets().strip
And your script will run as expected.
Also, you should use puts instead of two print statements as puts auto adds the newline character.
your answer is getting returned with a carriage return appended. So input "A" is never equal to "A", but "A(return)"
You can see this if you change your reject line to print("Invalid answer.[#{answer}]"). You could also change your comparison to if (answer.chomp == ..)
I've never used gets put I think if you hit enter your variable answer will probably contain the '\n' try calling .chomp to remove it.
Add a newline when you check your answer...
answer == "M\n"
answer == "A\n"
Or chomp your string first: answer = gets.chomp

Resources