Fixnum class method modification - ruby

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

Related

defining my_each in terms of my_times

I'm reading The Well-Grounded Rubyist and have come across an extra credit challenge to which there is no answer.
class Array
def my_each
c = 0
until c == size
yield(self[c])
c += 1
end
self
end
end
An example is given of creating a my_each with my_times
class Array
def my_each
size.my_times do |i|
yield self[i]
end
self
end
end
With the point that many of Ruby's iterators are built on top of each and not the other way around.
Given the above my_each, how could I use it in an implementation of my_times?
To make it clear, an example of a my_times implementation was given before:
class Integer
def my_times
c = 0
until c == self
yield(c)
c += 1
end
self
end
end
5.my_times { |e| puts "The block just got handed #{e}." }
So it would seem that the question most certainly implies using my_each in an implementation of my_times.
To implement my_times using my_each, all you need to do is call my_each on an array that looks like [0, 1, ..., (x - 1)], where x is self (the Integer):
class Integer
def my_times(&block)
(0...self).to_a.my_each do |n|
yield n
end
self
end
end
P.S. If you defined my_each on Enumerable instead of Array (like the "real" each), you could remove to_a from the third line above and iterate directly over the Range, instead of converting the Range to an Array first.
In order to implement my_times we need an array to send my_each message to. At that point of the book I don't think range is covered so I implemented without using a range. Here is the solution:
require_relative "my_each"
class Integer
def my_times
array = Array.new(self)
c = 0
array.my_each do
array[c] = c
yield(c)
c += 1
end
self
end
end
Edit: I just noticed Jordan used ... instead of .. which generates the correct output; See this answer for more detail on the difference for ranges. I've updated my answer below.
My account is too new and I can't comment on Jordan's solution; I see this was posted about a year ago but I am currently reading through The Well-Grounded Rubyist and wanted to comment on the solution.
I had approached it the same in a similar way as Jordan but found that the output is off compared to; The Well-Grounded Rubyist implementation of my_times which produces:
puts 5.my_times { |i| puts "I'm on iteration # {i}!" }
I'm on iteration 0!
I'm on iteration 1!
I'm on iteration 2!
I'm on iteration 3!
I'm on iteration 4!
Jordan's solution outputs:
puts 5.my_times { |i| puts "I'm on iteration # {i}!" }
I'm on iteration 0!
I'm on iteration 1!
I'm on iteration 2!
I'm on iteration 3!
I'm on iteration 4!
I'm on iteration 5!
I used a magic number to match The Well-Grounded Rubyist output [See Jordan's solution, using ... instead of .. which removes the need for the magic number]
class Integer
def my_times
(0..(self-1)).to_a.my_each do |n|
yield n
end
self
end
end
I shortened dwyd's implementation to supply a block rather than using the do..end.
class Integer
def my_times
(0...self).to_a.my_each { |i| yield i }
end
end
Also, I don't think you need to do self-1.

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

What do c == self and yield do?

Can you help me understand what this class does and how we can make use of it?
class Integer
def myt
c=0
until c == self
yield(c)
c+=1
end
self
end
end
Thank you.
x = Integer.new
x.myt
I tried to test it but it doesn't work. Error is: "no block given (yield)"
Also, in my book it says to test like this:
5.myt (|| puts "I'm on iteration #{i}! "} but it also gives an error - not sure why or what this line of code means.
allonhadaya and PNY did a good job explaining the purpose (enumeration) of the myt method.
Regarding your two questions mentioned in the title:
1.) What does 'c == self' do?
The '==' operator checks whether the integer c and Integer object you instantiate, are equal in value. If they are, the expression evaluates to true.
2.) What does 'yield' do?
The 'yield' statement passes control from the current method to a block which has been provided to the method. Blocks are ruby's implementation of a closure which, simple put, means that a method can be "extended" by calling the method with a block of additional code as long as the method supports a block (ie. incorporates yield statements)
The method seems to be a times implementation.
Basically 5.times { |i| puts i } and 5.myt { |i| puts i } will do exactly the same thing.
First, it sets a counter to 0, c = 0. Then you have a conditional where it checks if c is equal with self which will always be the integer attached to the method myt. It, then yields the counter and return self when is done.
Looks like it enumerates the values between zero inclusively and self exclusively.
allon#ahadaya:~$ irb
irb(main):001:0> class Integer
irb(main):002:1> def myt
irb(main):003:2> c=0
irb(main):004:2> until c == self
irb(main):005:3> yield(c)
irb(main):006:3> c+=1
irb(main):007:3> end
irb(main):008:2> self
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> 5.myt { |i| puts i }
0
1
2
3
4
=> 5
irb(main):012:0>
Using the example your book gave --
5.myt {|i| puts "I'm on iteration #{i}! "}
#You were missing an object in the pipes and a curly bracket before the pipes (not parentheses)
Allows you to see the internal workings of your myt method. Initializing variable c with a value of 0 the method executes an until look until the condition "c == self" is satisfied. Self references the object, here 5, which the method is acting on.
Therefore ...
def myt
until c == 5 #Until this is true
yield(c) #Do this .. here yield will do whatever the block specified
c+=1 #Increment on each iteration the value of variable c by 1
end #closing the until loop
self #return self
end
The yield within the method passes control from your method to the parameter, a block, back to the method.
Yield therefore allows you to build methods which can have similar patterns but with block you customize it to do your particular need.
If instead of putting each number maybe all you want to do is put the odd integers between 0 and the integer you call the method on --
5.myt {|i| puts i if i.odd?} # returns I am odd: 1 and I am odd: 3
I would suggest that you write your own blocks here to see how yield works and how you can keep the same method but pass in different blocks and create different method outputs!

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.

What is the fastest way of summing set bits in Ruby's NArray?

I used NArray to implement a bit array, but I am not quite satisfied with the speed of the bits_on method. Currently I have:
# Method that returns the number of bits set "on" in a bit array.
def bits_on
bits_on = 0
self.byte_array.each do |byte|
bits_on += #count_array[byte]
end
bits_on
end
byte_array is an NArray.byte() type, and #count_array is build like this:
# Method that returns an array where the element index value is
# the number of bits set for that index value.
def init_count_array
count_array = []
(0 ... (2 ** BitsInChar)).each do |i|
count_array << bits_in_char(i)
end
count_array
end
Ideas?
Cheers,
Martin
I am not sure I understand the background correctly, a possible solution is:
def bits_on
NArray.to_na(#count_array)[self.byte_array].sum
end
Sorry, the above is wrong, the next will work:
def bits_on
index = NArray.int(*self.byte_array.shape)
index[] = self.byte_array
NArray.to_na(#count_array)[index].sum
end

Categories

Resources