while loop less than symbol '<' raising error in Ruby (RubyMine) - ruby

I am adding all numbers that are multiples of 3 and 5 less-than 1000.
This is my error:
in `multiple_sum': undefined method `<' for nil:NilClass (NoMethodError)
Here is my code:
def multiple_sum(n)
five_total, three_total, three_subtract = 0
while five_total < n
five_total += five_total+5
end
while three_total < n
if (three_total+3)%5 == 0
three_subtract += three_total+3
end
three_total += three_total+3
end
puts (three_total-three_subtract) + five_total
end
multiple_sum(1000)
Is there a problem with my while loop condition?

You're probably looking for chained assignment: five_total = three_total = three_subtract = 0.

Nope. You are just not setting a value for all the variables listed:
five_total, three_total, three_subtract = 0
That code assigns zero to the first variable, five_total only. three_total and three_subtract are set to nil.
You should set them too:
five_total, three_total, three_subtract = 0, 0, 0

Related

Gettting frozen error after iterating with each_char in String class. Any fixes?

# Character Counter
class String
def count_char
#lcase_count ,#upcase_count, #num_count, #spl_char_count = [0, 0 ,0 ,0]
each_char { |char|
if ('a'..'z').cover?(char)
#lcase_count += 1
elsif ('A'..'Z').cover?(char)
#upcase_count += 1
elsif ('0'..'9').cover?(char)
#num_count += 1
else
#spl_char_count += 1
end
}
return #lcase_count,#upcase_count,#num_count,#spl_char_count
end
end
input = ARGV[0]
if ARGV.empty?
puts 'Please provide an input'
exit
end
puts 'Lowercase characters = %d' % [input.count_char[0]]
puts 'Uppercase characters = %d' % [input.count_char[1]]
puts 'Numeric characters = %d' % [input.count_char[2]]
puts 'Special characters = %d' % [input.count_char[3]]
Traceback (most recent call last):
1: from new.rb:25:in <main>'
new.rb:3:incount_char': can't modify frozen String (FrozenError)
I think as far, i didnt modify string not sure why getting FrozenError
You are monkeypatching the String class and at the same time introduce new instance variables to String, which already is a terrible design decision, because - unless you are the author of the String class -, you don't know whether or not these variables exist already. Then, in your code, you modify the variables by incrementing them. Since ARGV is an array of frozen strings, you get the error.
Using instance variables here is absolutely unnecessary. Just use normal local variables.
It’s impossible to tell what exactly is wrong with your code, it looks like one of the instance variables you use is initialized as string or likewise. Introducing instance variables in foreign classes is not a good practice in general, also you do abuse each for reducing. Here is an idiomatic ruby code for your task:
class String
def count_char
each_char.with_object(
{lcase_count: 0, upcase_count: 0, num_count: 0, spl_char_count: 0}
) do |char, acc|
case char
when 'a'..'z' then acc[:lcase_count] += 1
when 'A'..'Z' then acc[:upcase_count] += 1
when '0'..'9' then acc[:num_count] += 1
else acc[:spl_char_count] += 1
end
end
end
end
Please note, that this code deals with a simple latin alphabet only. Better approach would be to match regular expressions, like:
lcase_count = scan(/\P{Lower}/).count
upcase_count = scan(/\P{Upper}/).count
...
You can try following,
class String
def count_char
chars = { lcase_count: 0 ,upcase_count: 0, num_count: 0, spl_char_count: 0 }
each_char do |char|
if ('a'..'z').cover?(char)
chars[:lcase_count] += 1
elsif ('A'..'Z').cover?(char)
chars[:upcase_count] += 1
elsif ('0'..'9').cover?(char)
chars[:num_count] += 1
else
chars[:spl_char_count] += 1
end
end
return chars
end
end
str = 'Asdssd'
# => "Asdssd"
str.count_char
# => {:lcase_count=>5, :upcase_count=>1, :num_count=>0, :spl_char_count=>0}
str.count_char[:upcase_count]
# => 1
I couldn't find a document regarding ARGV being a frozen string.
But it seems to be that is the case.
You can use dup to fix your error.
input = ARGV[0].dup

An integer I pass as an argument becomes a method

I am trying to write a function. Here is the code.
def get_sum(a,b)
if a == b do
return a
end
else
total = 0
for num in a...b
total += num
end
return total
end
end
I get this error:
undefined method `b' for main:Object (NoMethodError)
Can anyone tell me why I get this?
No do for ifs
if a == b
return a
end
Note that you can do the same thing so
def get_sum(a, b)
return a if a == b
(a...b).inject(:+)
end
It is because you have a block do ... end after b. Neither the keyword if nor the syntax sugar form ... == ... accepts a block. The only possibility left to interpret your code syntactically is to interpret b as a method that takes this do ... end block, and that is how it is parsed.

longest_palindrome, expected 0, got nil, where should if-else statement?

Taking on the CodeWar Challenge. Struggling to fix my code so that if the length of the string input is 0, it would show 0 instead of nil.
Code is below: (suggestions?)
def longest_palindrome(string)
i = 0
a = []
while !string[i..-1].empty?
j = -1
while !string[i..j].empty?
s = string[i..j]
if s.reverse == s
a << s.length
if s.length == nil
a.max = 0
end
end
j -= 1
end
i += 1
end
a.max
end
First, I'd like to point out a couple of issues with the code you posted.
The body of the innermost if statement is never executed because
0 != nil
This means that even if s.length evaluates to zero
s.length == nil
will still be false.
Another issue I'd like to point out is that
a.max = 0
will throw an error that looks like this:
undefined method max=' for []:Array (repl):17:inlongest_palindrome'
(repl):1:in `initialize'
You can't set the max value directly. The reason you never run into this error with the code you posted is because of the first issue I outlined above.
Now to answer your question. There are a lot of ways to do what you are asking. For example, you could just check whether the input string is empty
at the beginning of the code and immediately return 0 if it is therefore
never executing the while loops at all. Maybe with something like
return 0 if string.empty?
at the beginning of the code.
But from your question, I think what you are looking is something more like the following:
def longest_palindrome(string)
i = 0
a = []
while !string[i..-1].empty?
j = -1
while !string[i..j].empty?
s = string[i..j]
if s.reverse == s
a << s.length
end
j -= 1
end
i += 1
end
a.max.to_i
end
Of interest here is the second last line which makes sure a.max is converted
to an integer using the to_i method. Calling this method on nil converts it to 0.
Also, please note I have changed the code to fix the issues I had highlighted earlier.

Ruby undefined method `-' for nil:NilClass (NoMethodError)

I am working on a project and have encounter an error which I am not familiar with. When I run my code, I received 'undefined method `-' for nil:NilClass (NoMethodError)' which after some research means that target_floors[j] is nil. Why is this happening and how to I solve it?
def retrieve_floor(n, target_floors)
smallestDifference = n
toReturn = 0
for i in 1..n
tempDiff = 0
for j in 0..target_floors.length
difference = target_floors[j] - i
if difference > 0
tempDiff += difference
else
tempDiff += difference.abs
end
end
if tempDiff < smallestDifference
smallestDifference = tempDiff
toReturn = i
end
end
return toReturn
end
Ranges of the form first..last include the endpoints, so you are iterating one beyond the end of the array.
You could instead use 0...target_floors.length (which includes the 0 but excludes the end) but a better and more rubyish approach would be to use each to iterate over the array, rather than working with indices.

Ruby - Finding primes under 100?

I'd like to write a code that prints out all primes under 100. Here is the code I have so far
class Numbers
def is_a_prime?(int)
x = 2
while x < int/2
if int % x == 0
return false
else
return true
end
end
end
def primes_under_100
x = 2
while x < 100
print x if is_a_prime?(x) # calling the method I defined above
x+= 1
end
end
end
Unfortunately when I call the method using primes_under_100 I get
undefined local variable or method 'primes_under_100' for main:Object
I'd like to know where I went wrong. None of my methods are private. Help is appreciated.
An other way to do this is extend Fixnum. Whit this you should be able to call it on int values.
this should be something like this
class Fixnum
def is_a_prime?
(2..(self/2)).each do |x|
if self % x == 0
return false
end
end
return true
end
end
In order for your code to work you will need to make the following modifications
class Numbers
def is_a_prime?(int)
x = 2
while x < int/2
if int % x == 0
return false
else
return true
end
end
end
def primes_under_100
x = 2
while x < 100
# Notice you're calling is_a_prime? on the instance of the Numbers object
# and sending x as an argument. Not calling is_a_prime? on the 'x'
print x if is_a_prime?(x)
x+= 1
end
end
end
Then call Numbers.new.primes_under_100
How are you calling it? They are public methods of the Number class, so in order to call them, you need to instantiate an object of the Number class:
number = Numbers.new
primes = number.primes_under_100
Also, as the comment from Leo Correa in my answer stated, the method is_a_prime? can't be called like that, you should use:
print x if is_a_prime?(x)
I don't know which version of Ruby include this method to Prime, but if you are using 2.2 and higher you can do it like this.
Add this to top of the file
require 'prime'
And method for showing primes under specific number.
Prime.each(100) do |prime|
p prime #=> 2, 3, 5, 7, 11, ...., 97
end
Here is the reference

Resources