Is there an opposite of String.next? [duplicate] - ruby

This question already has an answer here:
What is the opposite of string.next?
(1 answer)
Closed 9 years ago.
What is the opposite of next in Ruby?
I am trying to find a function that is like prev which doesn't exist.
"b".prev would == "a", just like "a".next == "b"
# A grad student at a local university thinks he has discovered a formula to
# predict what kind of grades a person will get. He says if you own less than
# 10 books, you will get a "D". If you own 10 to 20 books, you will get a "C",
# and if you own more than 20 books, you will get a "B".
# He further hypothesizes that if you actually read your books, then you will
# get a full letter grade higher in every case.
#
# grade(4, false) # => "D"
# grade(4, true) # => "C"
# grade(15, true) # => "B"

If your case is limited to unique character the following will allow you to get the previous
or next character:
def next_char(c)
(c.chr.ord + 1).chr
end
def prev_char(c)
(c.chr.ord - 1). chr
end
puts next_char('A')
puts prev_char('B')
However, as you deal with grades, I'd go for a kind a Enumeration of grade. For instance, take a look at that blog post for possible implementation.
Ref:
String.chr
String.ord
Integer.chr

Related

How to get the cyclomatic complexity of a ruby function? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 months ago.
Improve this question
I am looking for a function or gem that gives me the cyclomatic complexity of a function.
For example, using rubocop, If I write
def my_func(foo)
foo.details['errors'].each do |attr, message|
case attr
when 1 then foo.errors.add(:err1, :format)
when 2 then foo.errors.add(:err3, :format)
when 3 then foo.errors.add(:err5, :format)
when 4 then foo.errors.add(:err7, :format)
when 5 then foo.errors.add(:err9, :format)
when 6 then foo.errors.add(:err11, :format)
when 7 then foo.errors.add(:err13, :format)
else foo.errors.add(:base, message)
end
end
return foo
end
When I run rubocop, then I got the error:
Metrics/CyclomaticComplexity: Cyclomatic complexity for my_func is too high. [9/7]
def my_func(foo) ..."
And I know my cylcomatic complexity is [9/7].
If I change my function and no error is raised by rubocop, how to get the function cyclomatic complexity ? A code snippet with an example would be great ! (I am not looking for a manual computation).
Bonus: Provide a solution for JavaScript functions also.
Thanks!
From Rubocop::Cop::Metrics::CyclomaticComplexity itself;
# Checks that the cyclomatic complexity of methods is not higher
# than the configured maximum. The cyclomatic complexity is the number of
# linearly independent paths through a method. The algorithm counts
# decision points and adds one.
#
# An if statement (or unless or ?:) increases the complexity by one. An
# else branch does not, since it doesn't add a decision point. The &&
# operator (or keyword and) can be converted to a nested if statement,
# and ||/or is shorthand for a sequence of ifs, so they also add one.
# Loops can be said to have an exit condition, so they add one.
# Blocks that are calls to builtin iteration methods
# (e.g. `ary.map{...}) also add one, others are ignored.
#
# def each_child_node(*types) # count begins: 1
# unless block_given? # unless: +1
# return to_enum(__method__, *types)
#
# children.each do |child| # each{}: +1
# next unless child.is_a?(Node) # unless: +1
#
# yield child if types.empty? || # if: +1, ||: +1
# types.include?(child.type)
# end
#
# self
# end # total: 6
So, going part by part in your code, you get an initial count of 1, plus 1 for the each loop and plus 1 for each when branch;
def my_func(foo) # count begins: 1
foo.details['errors'].each do |attr, message| # each{}: +1
case attr
when 1 then foo.errors.add(:err1, :format) # when: +1
when 2 then foo.errors.add(:err3, :format) # when: +1
when 3 then foo.errors.add(:err5, :format) # when: +1
when 4 then foo.errors.add(:err7, :format) # when: +1
when 5 then foo.errors.add(:err9, :format) # when: +1
when 6 then foo.errors.add(:err11, :format) # when: +1
when 7 then foo.errors.add(:err13, :format) # when: +1
else foo.errors.add(:base, message)
end
end
return foo
end # total: 9
You could check the class examples to get a better idea as well.

How to solve ruby string [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm new to ruby, and I'm trying to make a simple calculator in which a user types in a simple problem (such as addition or subtraction) and the answer is returned. The problem is when the user types in a question, the question itself is being returned instead of the answer to that question.
puts "How many Questions?"
questions = gets.chomp.to_i
questions.times do |problem|
puts "question: "
problem = gets.chomp
puts "answer: #{problem}"
end
Inside your loop, instead of:
problem = gets.chomp
puts "answer: #{problem}"
Try this:
problem = gets.chomp
solved_problem = eval(problem)
puts "answer : #{solved_problem}"
eval will take care of interpreting your string as a Ruby instruction. But it's very messy, because anyone could write any Ruby program in your input and eval will make it run, so it's not safe at all.
If you only want to take care of simple operations, you can use a regex first to check if the input string looks like what you want:
problem_is_ok = (problem =~ /^\d+ *[+-] *\d+$/)
This will be true if the string starts with a number, followed by 0 to many spaces, followed by either a + or - sign, followed by 0 or more spaces, followed by another number and nothing else. Then you raise an error if this is not true.
Your loop now look like this:
questions.times do |problem|
puts "question: "
problem = gets.chomp
problem_is_ok = (problem =~ /^\d+ *[+-] *\d+$/)
if problem_is_ok
puts "answer: #{eval(problem)}"
else
#I raise an error, but you might aswell just print it instead for your simple program
raise ArgumentError("Can't compute this")
end
end
Add and subtract can be simple ruby definitions
We pass in 5 and 1
The lower portion of the code is the clear user interface implementation
when we loop we do it 3 times
It outputs 3 options for the user to select from
We read in with chomp, standard in, the keyboard, chooses 1, 2, or 3
If elsif statements conditionally select for each case
Using string interpolation we render the variables a and b into a new string,
and run their respective methods (add or subtract)
Converting that methods integer output to a string, and concatenate it.
Outputting that to the users screen
The 3rd option does no calculation,
instead it prints to users screen a simple string
our else condition catches the case when people don't enter one of the choices of 1, 2 or 3
It tells you to correct your choice to the options provided
Hope this helps
#!/usr/bin/env ruby
questions = 3
a, b = 5, 1
def add(a,b)
a + b
end
def subtract(a,b)
a - b
end
questions.times do |questions|
puts "Please choose:
1. add
2. subtract
3. exit"
questions = gets.chomp
if questions == '1'
puts "#{a} + #{b} = " + add(a,b).to_s
elsif questions == '2'
puts "#{a} - #{b} = " + subtract(a,b).to_s
elsif questions == '3'
puts 'exiting, goodbye.'
exit
else
p 'please choose again'
end
end

Improving calculate function where input string does not follow normal computational order

I am working through some sample interview questions and came across this problem where I have to write a calculate function. The caveat is that the input string isn't written in computational order - instead numbers are first and operators come after.
Test cases:
calculate("2 3 +") # => 5
calculate("12 2 /") #=> 6
calculate("48 4 6 * /") # => 2
def calculate(string)
numbers = string.scan(/\d+/)
operators = string.scan(/\D\W/).map{|o|o.gsub(" ","")} #TODO Better regex to remove space without having to map
formatted_string = numbers.inject(""){|string, b| string+"#{b}#{operators.shift}" }
eval(formatted_string)
end
I was able to come up with a solution, but am wondering if there is a more efficient/better way to solve this problem. I don't come from a programming background so I am not familiar with any tools/algorithms that may help.
Any feedback is greatly appreciated.
Ooh, fun! This syntax is called Reverse Polish notation (RPN), aka "postfix notation" and is still used by some powerful calculators (the HP-48G made me fall in love with programming!).
The typical way to parse and calculate RPN is to split the input string into whitespace-separated tokens, and for each token, push it onto a stack if it's an integer, otherwise perform the arithmetic operation designated by the token using the last two items on the stack as operands and push the result back on.
Here is a solution I came up with quickly:
def calculate(str)
stack = []
tokens = str.split(/\s+/) # Split tokens by whitespace.
tokens.each do |token|
if token =~ /^\d+$/ # It's a number
stack.push(token.to_i) # ...push it on to the stack.
elsif %w(+ - * /).include? token # It's an operator
a, b = stack.pop(2) # ...grab the last two numbers
c = a.send(token, b) # ...perform the operation
stack.push(c) # ...and push the resulting value.
else
raise "invalid token: #{token}" # Punt!
end
end
stack.pop # Return the last value pushed to the stack.
end
calculate("2 3 +") # => 5, since 2+3 = 5
calculate("12 2 /") # => 6, since 12/2 = 6
calculate("48 4 6 * /") # => 2, since 48/(4*6) = 2

I am trying to understand this standalone method for practice [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Improve this question
Im trying to write a standalone method named count_lines that returns the number of lines in an input string.
If i run this test code it should produce the output shown:
s = %W/This
is
a
test./
print "Number of lines: ", count_lines(s), "\n"
# Output:
Number of lines: 4
I am fairly new to Ruby and I am trying to figure out if this pseudocode of the actual output or not. Please help me!!
I would assume count_lines is a method that counts the number of elements in a an array, you can count the number of elements using of the several methods ruby provides look up the Array Documentation for this, and %W is a one of ruby niceties which allows you create an array of strings, e.g:
arr = %W{a b c}
arr # => ["a", "b", "c"]
It takes almost any special character as a delimiter e.g using . as a delimeter
arr = %W.a b c.
arr # => ["a", "b", "c"]
So in your snippet from the question / is delimiter used, so s would evaluate as below:
s = %W/This
is
a
test./
s # => ["This", "is", "a", "test."]
The above explains why the below works as it does
def count_lines(arr)
arr.size
end
s = %W/This
is
a
test./
print "Number of lines: ", count_lines(s), "\n"
# >> Number of lines: 4

next and previous for letters and symbols array [duplicate]

This question already has an answer here:
What is the opposite of string.next?
(1 answer)
Closed 9 years ago.
Because
"A".next => "B"
and
"#".next => "$"
How would I find the previous item? So that:
"$".previous => "#"
If you only need it to work on single character strings, you could extend String:
class String
def previous
return (self.ord - 1).chr
end
end
Then:
"$".previous # => "#"
I'm not a big ruby programmer, so I don't know how bad of a practice this is, but it does work if you need it.
Here's one way to do it for individual characters:
('B'.ord-1).chr # => 'A'
('$'.ord-1).chr # => '#'
From What is the opposite of string.next?
prev or something similar is not in the standard API because succ and a hypoethetical prev are surjective. Despite this, "Implement Ruby String Class Prev / Pred / Prev! / Pred! - Opposite Of Next / Succ Methods" is a possible version you could use.
The root problem is that succ is not inversible. This means, once you applied succ, then prev would end up with some ambiguity.
Credits to Bjoern Rennhak.

Resources