Ruby - Finding primes under 100? - ruby

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

Related

Is there a nicer way to call the current method recursively, without using its name?

For example:
def recurse(value)
if value < 5
self.send(__method__, value + 1)
else
value
end
end
This works, but it's a bit ugly.
Basically I'm looking for a prettier way to call the currently executing method, without referring to it explicitly by name.
If there is a less-cryptic syntax for this, I would probably use it (to avoid the name duplication, reduce effort required for renaming a function, etc). If there isn't a nicer syntax for this, I'll just hard-code the name like normal.
It's a comment rather, as #sagarpandya82 mentioned, you can omit some redundant parts and use both variants. I would refactor it a bit:
def recurse(value)
return value unless value < 5 # return value if value >= 5
send(__method__, value + 1) # or just recurse(value + 1)
end
Non-recursion version with a block:
def non_recurse(value)
if value >= 5
yield value
else
(value..5).each do |i|
yield i
end
end
end
non_recurse(3) {|i| puts i}
#=> 3, 4, 5
non_recurse(6) {|i| puts i}
#=> 6
If you really want to use __method__, your method is correct and reasonably readable. To comply with usual Ruby guidelines, you could just remove returns and use 2 spaces as indent (as mentioned by #sagarpandya82 in the comments):
def recurse(value)
if value < 5
self.send(__method__, value + 1)
else
value
end
end
I don't see any reason to use self.send(__method__) here, so you could write :
def recurse(value)
if value < 5
recurse(value + 1)
else
value
end
end
Actually, I'd say that you don't need recursion at all. All your method does is to keep adding 1 to the value until it reaches 5. If the value is bigger than 5, it returns the value :
For integers:
def no_recurse(value)
[value, 5].max
end
no_recurse(4)
# 5
no_recurse(-3)
# 5
no_recurse(7)
# 7
no_recurse(-2**1000)
# 5
no_recurse(4.5)
# 5 # <- That's wrong
For floats, you'd just need to add the decimal part to 5. This will work for any number:
def no_recurse(value)
[value, 5 + value % 1].max
end
no_recurse(4.5)
# 5.5
no_recurse(5.5)
# 5.5
no_recurse(6)
# 6
no_recurse(-7)
# 5

Global vs local variables?

I am wondering why my code works in one instance but doesn't in another. Does it have something to do with local and global variables?
This works:
def factorial num
result = 1
while (num > 1)
result = result * num
num -= 1
end
puts result
end
This doesn't work:
result = 1
def factorial num
while (num > 1)
result = result.to_i * num
num -= 1
end
puts result
end
Everything inside of a method definition cannot see local variables from other places. That sounds weird, but here's two ways to fix it:
result = 1
number = 10
def factorial(num,result_value)
while (num > 1)
result_value = result_value.to_i * num
num -= 1
end
puts result_value
end
factorial(number, result)
That passes result as an argument. That's a great way of handling the method because it doesn't allow you to change the value of result from within the method. That might not seem like a big deal but "pure methods" like this become very valuable as the size the code increases.
This is the "dirty" or un-pure way of doing the same thing:
#result = 1
def factorial(num)
while (num > 1)
#result = #result.to_i * num
num -= 1
end
puts #result
end
Putting an # in front of a variable name allows its scope to expand to methods defined outside of its scope. This becomes a problem as the complexity of your code increases.
Random personal opinion: even though Ruby doesn't require you to put the parentheses next to a method definition, you always should. It makes the code a lot more explicit and easier to read. Follow your heart though ;)
You could experiment by prepending all results with a $ sign, making it global. Prepending with a # results in an instance variable, also interesting. Sidenote: puts prints and returns nil, so your method returns nil.
result = 1 # line 1
def factorial num
while (num > 1)
result = result.to_i * num
num -= 1
end
puts result
end
In this code, factorial doesn't know about result variable from the line 1.
When Ruby find result = result.to_i * num in your method it will first assign nil to the result. Then Ruby will try to run result.to_i * num. Since result is already nil, result.to_i is equal 0.
Here is another example:
def foo
a = a
puts "#{a.class}"
end
foo #NilClass
In the Doesn't Work version the result variable you've assigned to 1 isn't visible inside the factorial method.
Now there is a possibly unexpected behaviour in Ruby that if you try to assign a variable and you refer to the same variable on the right hand side of the assignment, if that variable doesn't have a value yet then it is treated as nil rather than raising an error. So the first time round the loop when you perform
result = result.to_i * num
it's equivalent to result = nil.to_i * num and nil.to_i is equal to 0 so this then sets up result to be 0 for subsequent iterations of the loop and as you're just multiplying the value of result stays on 0.

Fixnum class method modification

This is a description of a code kata that I'm working on for code wars. The aim of the kata is to accomplish this:
The aim of this Kata is to modify the Fixnum class to give it the palindrome_below method. This method returns all numbers from and including 1 up to but not including itself that are palindromes for a given base.
For example in base 2 (binary)
1 = "1"
2 = "10"
3 = "11"
4 = "100"
Therefore 1 and 3 are palindromes in base two and the method should return the following.
5.palindrome_below(2)
=> [1, 3]
Here is the code that I wrote so far for this kata:
class Fixnum
def self.palindrome_below(binary)
palindrome_match = []
until self == 0
if to_s(binary) == to_s(binary).reverse
palindrome_match << self
self -= 1
end
end
palindrome_match
end
end
I tried to decrease self by 1. Sublime is telling me that I'm not able to decrease the value of self but I need to reduce self. Because this is a class method, I need to modify self.
This is what I tried as a work around:
class Fixnum
def self.palindrome_below(binary)
palindrome_match = []
self_placeholder = self
until self_placeholder == 0
if self_placeholder.to_s(binary) == self_placeholder.to_s(binary).reverse
palindrome_match << self_placeholder
self_placeholder -= 1
end
end
palindrome_match
end
end
This time, I placed self in a wrapper variable so I could modify it. When I try this, it says that there is an undefined method called palindrome_below. Doing this implementation should have monkey patched Fixnum. I'm not sure what I'm doing wrong. Can someone point me in the right direction?
A Working Solution (based your second attempt above):
class Fixnum
def palindrome_below(base)
palindrome_match = []
num = self - 1
until num == 0
if num.to_s(base) == num.to_s(base).reverse
palindrome_match << num
end
num -= 1
end
palindrome_match.reverse
end
end
What I changed:
You were right in adding a self_placeholder -- I named this variable num. In Ruby, Fixnums are immutable, so you can't change the value of the particular Fixnum itself.
I subtracted 1 from num right at the beginning, so as to avoid including the number itself in the result array
palindrome_below(base) needs to be an instance method. You very much care about the value of the specific instance of the Fixnum class (ie., the value of the number).
You need to subtract 1 from num outside your if statement.
I reversed the palindrome_match array so that it returns in the proper ascending order.
A Far Superior Solution (courtesy of #CarySwoveland's comment above).
class Fixnum
def palindrome_below(base)
1.upto(self-1).select { |num| num.to_s(base) == num.to_s(base).reverse }
end
end

Creating a Matrix class in ruby. The [] method

I've been assigned to create a new matrix class. I cannot use the require 'Matrix'.
I have this to access the element of the matrix, where #matrix is an array of arrays.
def [] (i, j)
#matrix[i][j]
end
if i try to access it like this:
#a[0][0]
it wont work. (wrong number of arguments)
but if i do it like this:
#a.[](0,0)
or
#a[0,0]
it works just fine.
Any ideas on how to make it work?
def [] (i, j)
#matrix[i][j]
end
According to the method [] it needs 2 arguments. But #a[0][0] doesn't do that,as here you are passing the method [] only 1 argument,ie.e 0. only. So you got the error. But #a.[](0,0) or #a[0,0] are perfect,as you are sending 2 arguments to the method []. When you write #a[0,0],then Ruby internally does the method call as #a.[](0,0).
how would you modify the code so #a[0][0] works?
Here is a code example:
class Matrix
def initialize(a)
#matrix=a
end
def [](*a)
a.size == 1 ? #matrix[*a] : #matrix[a.first][a.last]
end
end
a = [[1,2,3],[4,7,5],[11,21,33]]
m = Matrix.new(a)
p m[2,2] # => 33
You need to write a method that either calls it self recursively or checks how many arguments that are passed to the function. It is hard to say if this works as I do not have you entire class, but something like this might work:
def [] (*cords)
return #matrix[*cords] if cords.size == 1
#matrix[cords.first][cords.last]
end
Or a recursive version that works for any number dimensions:
def [] (*cords)
cords.inject(#matrix){|m, c| m[c]}
end
def [](i)
#matrix[i]
end
would do it, I guess. FWIW, Ruby's Matrix has [] implemented same as you: [](i,j)

In Ruby, how can I collect each new element passing through a method into an array?

I'm creating a small prime number program, and am confused about one thing.
I have a function called create_numbers, that generates numbers and passes them to a new function called check_for_primes, which passes only prime numbers to a final function called count_primes. I want to collect each prime into an array in the function count_primes, but for some reason each number is collected as its own array.
Any idea of what I'm doing wrong?
Here is the code:
def create_numbers
nums = 1
while nums < 100
nums = nums + 2
check_for_primes(nums)
end
end
def count_primes(nums)
array = []
array << nums
puts array.inspect
end
def check_for_primes(nums)
(2...nums).each do |i|
if nums%i == 0
nums = false
break
end
end
if nums != false
count_primes(nums)
end
end
create_numbers
Try this:
START = 1
STEP = 2
class Integer
def prime?
return if self < 2
(2...self).each do |i|
return if self % i == 0
end
true
end
end
def create_numbers
num = START
while (num + STEP) < 100
num += STEP
primes << num if num.prime?
end
end
def primes
#primes ||= []
end
create_numbers
p primes
When you want to save the 'state' of something, put it in an instance variable (#var).
It'll be accessible outside of the current function's scope.
Also, try naming your variables differently. For instance, instead of 'nums', in the
create_numbers method, use 'num'. Since the variable is only referencing one number at a
time and not a list of numbers, naming it in the plural will confuse people (me included)...
Hope it helps,
-Luke
each time into count_primes you put a value into array (which should have a better name, btw). Unfortunately, each time it's a new variable called array and since no one outside the function can see that variable it's lost when the function ends. If you want to save the values you've already found you'll need to set some state outside your function.
I can think of 2 quick solutions. One would be to declare your storage at the top of create_numbers and pass it into both functions.
def count_primes(num, arr)
def check_for_primes(nums, arr)
The other would be to set a variable outside all the functions, $array, for example to hold the values.
$array = []
...
$array << num
Since the scope of $array is global (i.e. all functions have access to it) you have access to it from anywhere in the file and can just add things to it in count primes. Note that using globals in this way is generally considered bad style and a more elegant solution would pass parameters and use return values.

Resources