I am new to ruby. I am a bit stuck on a class question. I am writing a grammar checker class method that first checks( check method) if the text given follows correct punctuation(starts with a capital letter and ends with a correct punctuation mark). In the percentage good method, I want to then use the correct texts from the check method and divide it by total texts inputted to get a percentage of how many texts are grammatically correct but I don't know how to access the results from the check method in the percentage good method? Any tips would be greatly appreciated
class GrammarStats
def initialize
#correct_texts= []
#total_texts = []
end
def check(text) # text is a string
#total_texts.push(text)
fail "Give me a string" if !text.is_a? String or text == ""
result = text.match?(/^[A-Z][\s\S]*?\+?[.?!](?:\n\n|$)/)
end
def percentage_good
# Returns as an integer the percentage of texts checked so far that passed
# the check defined in the `check` method. The number 55 represents 55%.
end
end
I may not have fully understood what you wanted.. But I think something like this? ;)
class GrammarStats
def initialize
#correct_texts = []
#total_texts = []
end
def correct?(text)
raise "Give me does not enpty string" unless text.is_a? String && text.present?
#total_texts << text
return false unless text.match?(/^[A-Z][\s\S]*?\+?[.?!](?:\n\n|$)/)
#correct_texts << text
true
end
def percentage_good
retrun '0%' if #total_texts.blank?
"#{((#correct_texts.count.to_f/#total_texts.count) * 100).round(2)}%"
end
end
Related
Ok i am not here to ask for an answer. But to be honest i am not really good in class variable. So i would appreciate you can guide me along with this piece of code.
I have read on class variable at those docs. I some what kind of understand it. But it comes to applying it for my own use. I would get confused.
class Square
##sqArray = {}
#attr_accessor :length
def initialize
if defined?(##length)
randno = "%s" % [rand(20)]
##length = randno.to_i
##sqArray = ##length
else
randno = "%s" % [rand(20)]
##length = randno.to_i
##sqArray = ##length
end
end
def Area
##area = ##length * ##length
return ##area
##sqArray[##length.to_sym] = ##area
puts ##sqArray
end
end
s1 = Square.new
puts s1.Area
Let me explain this piece of code. Basically every time i create a Square object it would go to initialize method. A random number will be generated and pass it to ##length, and ##length will be assigned to hash ##sqArray as it's key. But now the problem is when i create a new object s1. When i want to display the Area i want to test out to print the hash ##sqArray with it's length as it's key and area as it's value. But now the problem is only returning it's area only. e.g 114 only.
suppose to be e.g [ 24 => 114]
When defining the object's property (i.e. it's length), the correct approach is to use an instance variable, not a class variable. This is because (in your particular example), length is an attribute of a specific square and not something that applies to all squares. Your code should look something like this:
class Square
def initialize(length = rand(20))
#length = length
end
def area
#length * #length
end
end
s1 = Square.new
puts s1.area
Now, I am a little unclear what exactly you aim to achieve by use of that class variable ##sqArray - but for example, you could use this store a list of all defined Squares:
class Square
##squares_list = []
def self.all_known
##squares_list
end
def initialize(length = rand(20))
#length = length
##squares_list << self
end
def area
#length * #length
end
end
This would allow you to write code like:
s1 = Square.new #=> #<Square:0x0000000132dbc8 #length=9>
s2 = Square.new(20) #=> #<Square:0x000000012a1038 #length=20>
s1.area #=> 81
s2.area #=> 400
Square.all_known #=> [#<Square:0x0000000132dbc8 #length=9>, #<Square:0x000000012a1038 #length=20>]
Class variables have some odd behaviour and limited use cases however; I would generally advise that you avoid them when starting out learning Ruby. Have a read through a ruby style guide to see some common conventions regarding best practice - including variable/method naming (use snake_case not camelCase or PascalCase), whitespace, etc.
The below combined programs should ask for a number remove the first digit (lets call this new number x) and then compute x % 7. Ex: (1121546 % 7) = 5
This all appears to be working except that the number entered in will always compute to 0. modulo_7.rb works by itself and will print the correct outcome when passed a parameter.
The question is am I not passing the variables/ parameters properly or is there something else that is getting in the way?
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
#cert_id = nil
until #cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
#cert_id = Integer(gets)
rescue ArgumentError
end
end
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
n.get_cert_number
checking_policy_number = Get_policy_check_digit.new(#cert_id)
checking_policy_number.create_check_digit
end
end
run = Run_number_check_interface.new
run.run
modulo_7.rb
This program removes the first digit (index 0) of a 7 digit number and returns the difference 7%18 is 4 since 4 is remainder of how many times 7 can fit into 18.
class Get_policy_check_digit
def initialize(cert_id)
#instance variable
#cert = cert_id
end
def create_check_digit
cert_id_6 = #cert.to_s
cert_id_6.slice!(0)
puts cert_id_6
check_digit = cert_id_6.to_i % 7
puts "Your check digit is #{check_digit}"
end
end
# n = Get_policy_check_digit.new(1121546) When uncommented this will create a new instance
# of Get_policy_check_digit with the parameter 1121546
# n.create_check_digit This will run the method create_check_digit with the
# parameter 1121546
Instance variables are scoped to an individual instance of a class. So when you say #cert_id = Integer(gets) inside Number_check_interface, you are only setting #cert_id for that particular instance of Number_check_interface. Then, when you later write Get_policy_check_digit.new(#cert_id) inside Run_number_check_interface, you are referring to an entirely different #cert_id, one which is specific to that particular instance of Run_number_check_interface, and not to the Number_check_interface you stored in n earlier.
The simple solution is to return #cert_id from Number_check_interface#get_cert_number, and then pass the returned value to Get_policy_check_digit.new:
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
#cert_id = nil # This is an instance variable. It's only accessible
# from inside this instance of `Number_check_interface`
until #cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
#cert_id = Integer(gets)
rescue ArgumentError
end
end
return #cert_id # Return the contents of #cert_id
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
cert_number = n.get_cert_number # Here we call `get_cert_number` and
# set `cert_number` to it's return
# value.
# Notice how we use `cert_number` here:
checking_policy_number = Get_policy_check_digit.new(cert_number)
checking_policy_number.create_check_digit
end
end
Other tips:
Convention in Ruby is to name classes with CamelCase.
Require dependencies at the top of your files, not in the middle of method calls.
Unless you have a very good reason not to, use require, not load
You might want to think a bit harder about what purpose these classes serve, and what behavior they are intending to encapsulate. The API seems a bit awkward to me right now. Remember, tell, don't ask.
Why are these separate classes? The design here seems strange, is this ported from another language? It's more complicated than it needs to be. Without changing your structure, here's what's wrong:
In Run_number_check_interface you are reading #cert_id, it doesn't have an instance variable named that, but Number_check_interface does. Just return it from get_cert_number:
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
cert_id = nil
until cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
cert_id = Integer(gets)
rescue ArgumentError
end
end
cert_id # <-- returing the value here
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
cert_id = n.get_cert_number # <-- saving here
checking_policy_number = Get_policy_check_digit.new(cert_id) # <-- no longer an ivar
checking_policy_number.create_check_digit
end
end
run = Run_number_check_interface.new
run.run
I am trying to write fast and concise code. I'd appreciate your thoughts on which is the best way to write the following code and why:
Option #1
def get_title
title = check_in_place_one
if title.empty?
title = check_in_place_two
if title.empty?
title = check_in_place_three
end
end
return title
end
Option #2
def get_title
title = check_in_place_one
title = check_in_place_two unless !title.empty?
title = check_in_place_three unless !title.empty?
return title
end
I think Option #1 is better since if the title is found by check_in_place_one, we test title.empty? once and then skip the rest of the code in the method and return. But, it looks too long. Option #2 appears better, but processes title.empty? one extra time, and unnecessary time before returning. Also, am I missing a third option?
From performance, there is no difference between the two versions of your code (besides very minor difference that may come from parsing, which should be ignorable). The control structures are the same.
From readability, if you can get away with nesting, doing so is better. Your second option is better.
It is usually better to get rid of any case that does not need further processing. That is done by return.
def get_title
title = check_in_place_one
return title unless title.empty?
title = check_in_place_two
return title unless title.empty?
title = check_in_place_three
return title
end
The last title = and return in the code above are redundant, but I put them there for consistency, which improves readability.
You can further compact the code using tap like this:
def get_title
check_in_place_one.tap{|s| return s unless s.empty?}
check_in_place_two.tap{|s| return s unless s.empty?}
check_in_place_three
end
tap is a pretty much fast method, and unlike instance_eval, its performance penalty is usually ignorable.
The following approach could be used for any number of sequential tests. Moreover, it is completely general. The return condition could be changed, arguments could easily be assigned to the test methods, etc.
tests = %w[check_in_place_one check_in_place_two check_in_place_three]
def do_tests(tests)
title = nil # Define title outside block
tests.each do |t|
title = send(t)
break unless title.empty?
end
title
end
Let's try it:
def check_in_place_one
puts "check 1"
[]
end
def check_in_place_two
puts "check 2"
''
end
def check_in_place_three
puts "check 3"
[3]
end
do_tests(tests) #=> [3]
check 1
check 2
check 3
#=> [3]
Now change one of the tests:
def check_in_place_two
puts "check 2"
'cat'
end
do_tests(tests) #=> 'cat'
check 1
check 2
#=> "cat"
If there were more tests, it might be convenient to put them in a module which would be included into a class. Mixed-in methods behave the same as those that you define for the class. For example, they have access to instance variables. I will demonstrate that with the definition of the first test method. We probably want to make the test methods private. We could do it like this:
module TestMethods
private
def check_in_place_one
puts "#pet => #{#pet}"
puts "check 1"
[]
end
def check_in_place_two
puts "check 2"
''
end
def check_in_place_three
puts "check 3"
[3]
end
end
class MyClass
##tests = TestMethods.private_instance_methods(false)
puts "##tests = #{##tests}"
def initialize
#pet = 'dog'
end
def do_tests
title = nil # Define title outside block
##tests.each do |t|
title = send(t)
break unless title.empty?
end
title
end
include TestMethods
end
The following is displayed when the code is parsed:
##tests = [:check_in_place_one, :check_in_place_two, :check_in_place_three]
Now we perform the tests:
MyClass.new.do_tests #=> [3]
#pet => dog
check 1
check 2
check 3
Confirm the test methods are private:
MyClass.new.check_in_place_one
#=> private method 'check_in_place_one' called for...'
The advantage of using a module is that you can add, delete, rearrange and rename the test methods without making any changes to the class.
Well, here's a few other alternatives.
Option 1: Return first non-empty check.
def get_title
return check_in_place_one unless check_in_place_one.empty?
return check_in_place_two unless check_in_place_two.empty?
return check_in_place_three
end
Option 2: Helper method with short-circuit evaluation.
def get_title
check_place("one") || check_place("two") || check_place("three")
end
private
def check_place(place)
result = send("check_in_place_#{place}")
result.empty? ? nil : result
end
Option 3: Check all places then find the first that's non-empty.
def get_title
[
check_in_place_one,
check_in_place_two,
check_in_place_three,
].find{|x| !x.empty? }
end
Option 2 looks good although you did a 360 degree turn with the unless !title.empty?. You can shorten that to if title.empty? since unless is equivalent to an if ! so doing an unless ! takes you back to just if.
If you're only ever going to have 3 places to look in then option 2 is the best. It's short, concise, and easy to read (easier once you fix the aforementioned whoopsie). If you might add on to the places you look for a title in you can get a bit more dynamic:
def get_title(num_places = 4)
title, cur_place = nil, 0
title = check_in_place(cur_place += 1) while title.nil? && cur_place < num_places
end
def check_in_place(place_num)
# some code to check in the place # given by place_num
end
The tricky line is that one with the while in it. What's happening is that the while will check the expression title.nil? && cur_place < num_places and return true because the title is still nil and 0 is less than 4.
Then we'll call the check_in_place method and pass in a value of 1 because the cur_place += 1 expression will increment its value to 1 and then return it, giving it to the method (assuming we want to start checking in place 1, of course).
This will repeat until either check_in_place returns a non nil value, or we run out of places to check.
Now the get_title method is shorter and will automatically support checking in num_places places given that your check_in_place method can also look in more places.
One more thing, you might like to give https://codereview.stackexchange.com/ a look, this question seems like it'd be a good fit for it.
I don't think there's any reason to get too clever:
def get_title
check_in_place_one || check_in_place_two || check_in_place_three
end
Edit: if the check_in_place_X methods are indeed returning an empty string on failure it would be better (and more idiomatic) to have them instead return nil. Not only does it allow for truthy comparisons like the above code, return "" results in the construction of a new and unnecessary String object.
Here comes another Codecademy question:
The following challenge has been presented.
Define two methods in the editor:
A greeter method that takes a single string parameter, name, and
returns a string greeting that person. (Make sure to use return and
don't use print or puts.)
A by_three? method that takes a single integer parameter, number, and
returns true if that number is evenly divisible by three and false if
not. Remember, it's a Ruby best practice to end method names that
produce boolean values with a question mark.
The code I put in re: was..
def greeter(name)
return "Greet #{name}"
end
def by_three?(x)
if x % 3==0
returns true
else
return false
end
greeter("Brant")
by_three?(6)
The console then gives me the following error:
Did you define your greeter method?
It seems like I have. Am I wrong?
this would be it:
def greeter(name)
"Greet #{name}"
end
def by_three?(x)
x % 3 == 0
end
greeter("Brant") # => "Greet Brant"
by_three?(6) # => true
It looks like you did not add "end" after your else statement. Here you go.
#For the greeter method, i decided to use this format
def greeter(name)
return name
end
greeter("Hello Jane, good morning")
def by_three?(number)
if number % 3 != 1
return true
else
return false
end #Add end here to end your statement
end
by_three?(5)
I've been sifting through the prior questions and answers on stackoverflow, and I have gotten most of my question figured out. I figured out that I can't place a function call within a hash, without placing it within a proc, or a similar container.
What I'm ultimately trying to do is have a menu displayed, grab user input, and then iterate through the hash, and run the specified function:
def Main()
menu_titles = {"Answer1" => Proc.new{Choice1()}}
Menu(menu_titles)
end
def Choice1()
puts "Response answer"
end
def Menu(menu_titles)
menu_titles.each_with_index do |(key, value),index|
puts "#{index+1}. #{key}"
end
user_input = 0
menu_titles.each_with_index do |(key, value), index|
if index.eql?(user_input)
menu_titles[value]
break
end
end
end
Main()
The issue I'm having right now is that I'm not entering the functions that my hash calls for. Whether I use a return or a "puts", I either get a blank line or nothing at all. If anyone has other recommendations about my code, I'm all ears also. To be honest, I don't like using procs, but that's mostly because I don't entirely know how they work and where to use them.
Right now for my menus I have:
user_input = 1
if user_input == 1
Choice1()
...
end
Here's how I would refactor this:
class Menu
attr_reader :titles
# initialize sets up a hard-coded titles instance variable,
# but it could easily take an argument.
def initialize
#titles = {
"Answer1" => Proc.new{ puts "choice 1" },
"Answer2" => Proc.new{ puts "choice 2" }
}
end
# This is the only public instance method in your class,
# which should give some idea about what the class is for
# to whoever reads your code
def choose
proc_for_index(display_for_choice)
end
private
# returns the index of the proc.
def display_for_choice
titles.each_with_index { |(key,value), index| puts "#{index + 1}. #{key}" }
gets.chomp.to_i - 1 # gets will return the string value of user input (try it in IRB)
end
# first finds the key for the selected index, then
# performs the hash lookup.
def proc_for_index(index)
titles[titles.keys[index]]
end
end
If you're serious about Ruby (or object-oriented programming in general), I would highly recommend learning about the advantages of packaging your code into behavior-specific classes. This example allows you to do this:
menu = Menu.new
proc = menu.choose
#=> 1. Answer1
#=> 2. Answer2
2 #(user input)
proc.call
#=> choice 2
And you could actually run it on one line:
Menu.new.choose.call