Guidance on how to implement certain problems in Ruby - ruby

For the class NumberSet, I have to define the [] method so that it takes one argument, which it uses as a filter to select members of the set and returns a new set containing those elements.
For example, I have
Filter.new { |number| number.even? }
and
SignFilter.new(:non_negative)
which are classes that I must construct.
I also have to define the & and | operators so that they work with the filters. Something along the lines of
numbers[SignFilter.new(:non_negative) & Filter.new { |number| number.even? }]
The class so far is:
class NumberSet
include Enumerable
def initialize
#arr=[]
end
def each (&block)
#arr.each do |member|
block.call (member)
end
end
def << number
#arr<<number unless #arr.include?(number)
end
end
For Filter I think something like works:
class Filter
def initialize
yield
end
end
My biggest problem is the [], $and | parts, which I have no idea how to do.
What I want to accomplish is :
numbers = NumberSet.new
[-3, -2, -1, 0, 1, 2, 3, 4, 5].each do |number|
numbers << number
end
numbers[SignFilter.new(:non_negative) & Filter.new { |number| number.even?}].to_a
#=>[0, 2, 4]

I think this should do it.
Code
SignFilter class
class SignFilter
def initialize(sign)
#sign = sign
end
def filter
case #sign
when :negative
-> i { i < 0 }
when :positive
-> i { i > 0 }
when :non_negative
-> i { i >= 0 }
when :non_positive
-> i { i <= 0 }
when :zero
-> i { i.zero? }
end
end
end
Filter class
class Filter
attr_reader :filter
def initialize &filter
#filter = filter
end
end
NumberSet class
class NumberSet
def initialize arr
#arr = arr
end
def process(op, sf, f)
sign_filter = sf.filter
filter = f.filter
#arr.send(op).each { |e| sign_filter.call(e) }
.send(op).each { |e| filter.call(e) }
end
end
Examples
sf = SignFilter.new :negative
f = Filter.new { |number| number.even? }
ns = NumberSet.new [-3, -2, -1, 0, 1, 2, 3, 4, 5]
ns.process(:reject, sf, f)
#=> [1, 3, 5]
sf = SignFilter.new :non_negative
f = Filter.new { |number| number % 3 == 0 }
ns = NumberSet.new [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6]
ns.process(:select, sf, f)
#=> [0, 3, 6]
Explanation
Blocks are not objects, so you can't pass them around. They can be converted to procs, however, which are objects (instances of the class Proc), and therefore can be passed. You will need to understand procs (and lambdas, which are a type of proc). Here is a good explanation. (Aside: one thing that's a little confusing about procs is the multitude of ways they can be invoked. For example, if p -> i { 3*i }, p.call(2), p.yield(2), p[2] and p.(2) all return the value 6.)
Here is what is happening:
An instance sf of the SignFilter class is created by passing the symbol denoting the signs of the elements of the array that are to be selected or rejected (:negative, :non_negative and so on). The symbol is saved in an instance variable #sign.
The SignFilter class has a method filter which returns a lambda based on the value of #sign.
An instance of the Filter class is created by passing a block which is received as a proc and saved into the instance variable #filter, which has a read accessor.
An instance of the NumberSet class is created by passing the array, which is saved into the instance variable #arr.
NumberSet#process is passed three arguments: the Enumerable method :reject or :select (saved into op), the SignFilter instance (sf) and the Filter instance (f).
Within NumberSet#process, #arr is sent op, which creates an enumerator (arr.reject or arr.select).
The SignFilter lambda is called on each element of the enumerator. An array comprised of a subcollection of #arr is returned.
The returned array is sent op, creating another reject or select enumerator.
The Filter proc is called on the each element of the new enumerator, causing the desired array to be returned.
Considering that both reject and select are not necessary (either would do), it would have been simpler to just replace .send(op) in NumberSet#process with, say, reject, but I chose to do it this way just to illustrate the generalization.
Notice that it would be easy to generalize NumberSet#process to process(sf,f,o), where, as now, sf and f provide filters and o would be an instance of an Operation class that specifies a proc to send to the filtered subcollection of #arr to invoke an Enumerable method with a block (map, group_by and so on).

Since this appears to be a homework question, I'm not going to give you the full implementation, but I'll see you on your way. The big thing you need to realize here is that methods such as [] and | can be defined as normal methods in Ruby. In Ruby, you simply send messages (such as []) to a "receiver". How you handle those methods are defined via def instructions on your class definition. So, for example:
class Filter
def |(other_filter)
# Do some work to build a new filter which is a union of this filter and other_filter
end
end
class SignFilter < Filter
# SignFilter inherits the & method from Filter, and you can then go on to implement SignFilter-specific functionality
# ...
end
class NumberSet
def [](filter)
# Given a filter, apply each of the numbers of this NumberSet to the filter, and return those which pass the filter
end
end
To invoke those methods, would do something like:
filter = Filter.new {|num| num.even? }
sign_filter = SignFilter.new(:non_negative)
union_filter = filter | sign_filter
This third line is equivalent to calling:
union_filter = filter.|(sign_filter)
or:
union_filter = filter.send("|", sign_filter)
In all three cases, the "|" message is sent to the the filter instance, with sign_filter as an additional argument. You could also do something like:
numset = NumberSet.new(1,2,3,4,5)
filtered_numbers = numset[union_filter]
This second line is equivalent to:
numset.[](union_filter)
# or
numset.send("[]", union_filter)
The original syntax is just syntactic sugar for those method calls - it's just there because it makes Ruby code look nicer, and helps the programmer mentally map it to common conventions for those kinds of operations.

Related

Trying to write my own all? method in Ruby

There is a method called all? in Enumerable.
I'm trying to learn all the methods of Enumberable's library by writing them myself.
This is what I've come up so far for the all? method. I sorta understand it but I got stumped when trying to pass initialized values to my method.
EDIT for the record, I'm aware that enum method that I have is not the right way ie, it's hard-coded array. This is for self-learning purposes. I'm just trying to figure out how to pass the initialized values to my all? method. That's why I wrote enum in the first place, to see that it is working for sure. Please don't take this class as a literal gospel. Thank you.
class LearningMethods
def initialize(values)
#values = values
end
def enum
array = [10, 3, 5]
end
def all?(a)
yield(a)
end
end
c = LearningMethods.new([10, 3, 5])
p c.enum.all? {|x| x >= 3 } #this works
p c.all?(10) { |x| x >= 3 } #this works
p c.all?(#values) { |x| x >= 3 } #this doesn't work. Why not? And how do I pass the initialized values?
I'm not sure why you need enum at all? Enumerable is a module included in array, so if you're not familiar with this I recommend you read about "modules and mix-ins" in Ruby.
all? works simply by passing EACH of the array elements to the block. If there is ANY element (at least 1) for which the block returns false, then all? evaluates to false. Try analyzing this code:
class MyAllImplementation
def initialize(array)
#array = array
end
def my_all?
#array.each do |element| # for each element of the array
return true unless block_given? # this makes sure our program doesn't crash if we don't give my_all? a block.
true_false = yield(element) # pass that element to the block
return false unless true_false # if for ANY element the block evaluates to false, return false
end
return true # Hooray! The loop which went over each element of our array ended, and none evaluted to false, that means all elements must have been true for the block.
end
end
a = MyAllImplementation.new([1,2,3])
p a.my_all? { |x| x > 0 } #=> true
p a.my_all? { |x| x > 1 } # false, because 1 is not bigger than 1, it's equal to 1

Ruby background: What are linked lists?

I'm a self taught programmer and started off with Ruby. I'm currently trying to learn algorithms and data structures and noticed something called a linked list. It looks like Ruby doesn't have that data structure (maybe in Array?). I'm familiar with arrays and hashes.
How would you describe/explain what a linked list is for someone coming from my background?
Linked lists are rather simple: they are lists which are created by linking the elements together. (Kind of obvious, when you think about it, no?)
In its most basic form, a linked list is simply either empty or a pair. The first element of the pair is a value, and the second element of the pair is a linked list representing the rest of the values.
Traditionally, the pair is called a cons cell, the first element is called the head or the car of the list and the second element is called the tail or the cdr of the list. The empty list is called Nil or simply [].
Here is an extremely simple implementation of a linked list in Ruby, which uses nothing but functions to implement a linked list (and booleans and conditionals, while we're at it):
True = ->(iff, _) { iff }
False = ->(_, els) { els }
Pair = ->(first, rest) { -> x { x.(first, rest) }}
First = -> list { list.(True ) }
Rest = -> list { list.(False) }
Here, we have a simple list with three elements:
List = Pair.(1, Pair.(2, Pair.(3, nil)))
First.(Rest.(List))
# => 2
A more realistic object-oriented encoding of a list looks like this:
class List
def cons(el) Pair.new(el, self) end
Empty = new
class Pair < self
attr_reader :first, :rest
def initialize(first, rest=Empty)
self.first, self.rest = first, rest
end
private
attr_writer :first, :rest
end
end
Again, a list with two elements:
list1 = List::Pair.new(1, List::Pair.new(2, List::Pair.new(3, List::Empty)))
# corresponds to the list [1, 2, 3]
list1.rest.first
# => 2
list2 = List::Empty.cons(6).cons(5).cons(4)
# List[4, 5, 6]
list2.rest.first
# => 5
A more complete and Rubyish implementation might look like this:
class List
include Enumerable
def self.[](*els) els.reverse_each.inject(Empty, &:cons) end
def cons(el) Pair[el, self] end
def prepend(prefix)
case
when empty? then prefix
when prefix.empty? then self
else prepend(prefix.rest).cons(prefix.first)
end
end
def to_s; "List[#{map(&:to_s).join(', ')}]" end
def inspect; "List[#{map(&:inspect).join(', ')}]" end
def each; return enum_for(__method__) unless block_given? end
class << Empty = new
def empty?; true end
alias_method :inspect, def to_s; 'Empty' end
freeze
end
Empty.freeze
class Pair < self
def initialize(first, rest=Empty)
self.first, self.rest = first, rest
freeze
end
def empty?; false end
def each(&blk)
return super unless block_given?
yield first
rest.each(&blk)
end
private
attr_writer :first, :rest
protected
attr_reader :first, :rest
class << self; alias_method :[], :new end
freeze
end
freeze
end
Some examples:
list1 = List::Pair[1, List::Pair[2, List::Pair[3, List::Empty]]]
# => List[1, 2, 3]
list2 = List::Empty.cons(6).cons(5).cons(4)
# => List[4, 5, 6]
list3 = List[7, 8, 9]
# => List[7, 8, 9]
list4 = list3.prepend(list2).prepend(list1)
# => List[1, 2, 3, 4, 5, 6, 7, 8, 9]
list4.partition(&:odd?)
# => [[1, 3, 5, 7, 9], [2, 4, 6, 8]]
In computer science, a linked list is a data structure consisting of a group of nodes which together represent a sequence. Under the simplest form, each node is composed of a data and a reference (in other words, a link) to the next node in the sequence; more complex variants add additional links. This structure allows for efficient insertion or removal of elements from any position in the sequence.
http://en.wikipedia.org/wiki/Linked_list
Here is a implementation on ruby: http://matt.weppler.me/2013/08/14/implementing-a-linked-list-in-ruby.html
Kudos for studying Ruby one of my favorites languages.

Linked List written in ruby

I'm preparing for a technical interview and will be asked to write the algorithm for a linked list in ruby. I understand linked lists completely, but have struggled writing the code. Can someone show me how this is done? I started it below..
class Node
def initialize(item)
#item = item
#next = nil
end
end
You almost did it, really. I can give you very old-school, Lisp-like implementation, if you are brave enough to show it to your interviewer. In this approach, list is a pair (two elements touple), which first element contains the element, and second contains another pair, etc, etc. The last pair have nil as a second element. And here is the whole implementation of the list in Ruby:
class Pair
attr_reader :car, :cdr
def initialize(car, cdr=nil)
#car = car
#cdr = cdr
end
end
To construct the list, just use a lot of parenthesis, like in old, good Lisp:
list = Pair.new(1, Pair.new(2, Pair.new(3)))
Now, the world is yours. You can do whatever you want with the list, using simple recursion. Here is an example of recursive inspect:
class Pair
def inspect
if cdr.nil?
car.inspect
else
"#{car.inspect}, #{cdr.inspect}"
end
end
end
pry(main)> list = Pair.new(1, Pair.new(2, Pair.new(3)))
=> 1, 2, 3
As you mentioned in a comment, you want to search the list. Here is the code for this:
class Pair
def find(index)
find_ index, 0
end
def find_(index, i)
if index == i
car
else
cdr.find_ index, i+1
end
end
end
pry(main)> list.find 2
=> 3
This is the standard Church Encoding of Lists (and Booleans):
True = ->(iff, _) { iff }
False = ->(_, els) { els }
Pair = ->(first, rest) { -> x { x.(first, rest) }}
First = -> list { list.(True ) }
Rest = -> list { list.(False) }
List = Pair.(1, Pair.(2, nil))
First.(Rest.(List))
# => 2
It's not what you would actually write in Ruby, of course, but it is very simple and demonstrates an understanding of one of the most important principles of programming: code is data and data is code.
Here's a more realistic object-oriented encoding of lists:
class List
include Enumerable
def self.[](*els) els.reverse_each.inject(Empty, &:cons) end
def cons(el) Pair[el, self] end
def prepend(prefix)
case
when empty? then prefix
when prefix.empty? then self
else prepend(prefix.rest).cons(prefix.first)
end
end
def to_s; "List[#{map(&:to_s).join(', ')}]" end
def inspect; "List[#{map(&:inspect).join(', ')}]" end
def each; return enum_for(__method__) unless block_given? end
class << Empty = new
def empty?; true end
alias_method :inspect, def to_s; 'Empty' end
freeze
end
Empty.freeze
class Pair < self
def initialize(first, rest=Empty)
self.first, self.rest = first, rest
freeze
end
def empty?; false end
def each(&blk)
return super unless block_given?
yield first
rest.each(&blk)
end
private
attr_writer :first, :rest
protected
attr_reader :first, :rest
class << self; alias_method :[], :new end
freeze
end
freeze
end
Note that there are absolutely no conditionals and no loops in the code. That is always a good sign for object-oriented code: polymorphic method calls are more powerful than conditionals anyway, oftentimes, there simply is no need for conditionals.
Some examples:
list1 = List::Pair[1, List::Pair[2, List::Pair[3, List::Empty]]]
# => List[1, 2, 3]
list2 = List::Empty.cons(6).cons(5).cons(4)
# => List[4, 5, 6]
list3 = List[7, 8, 9]
# => List[7, 8, 9]
list4 = list3.prepend(list2).prepend(list1)
# => List[1, 2, 3, 4, 5, 6, 7, 8, 9]
list4.partition(&:odd?)
# => [[1, 3, 5, 7, 9], [2, 4, 6, 8]]
Unfortunately, this object-oriented encoding will blow the stack for larger lists (on my system List[*(1..9338)].each {} still works, but 9339 doesn't), even though each is tail-calling itself and thus should run in O(1) stack space. As Guy L. Steele pointed out multiple times, OO languages must support proper tail calls, otherwise you are required to break OO in order to avoid blowing the stack. (prepend is not coded for tail-calls, but it can be rewritten that way.)

How can I create an enumerator that does certain things after iteration?

How can I create an enumerator that optionally takes a block? I want some method foo to be called with some arguments and an optional block. If it is called with a block, iteration should happen on the block, and something should be done on it, involving the arguments given. For example, if foo were to take a single array argument, apply map on it with the given block, and return the result of join applied to it, then it would look like:
foo([1, 2, 3]){|e| e * 3}
# => "369"
If it is called without a block, it should return an enumerator, on which instance methods of Enumerator (such as with_index) should be able to apply, and execute the block in the corresponding way:
enum = foo([1, 2, 3])
# => Enumerator
enum.with_index{|e, i| e * i}
# => "026"
I defined foo using a condition to see if a block is given. It is easy to implement the case where the block is given, but the part returning the enumerator is more difficult. I guess I need to implement a sublass MyEnum of Enumerator and make foo return an instance of it:
def foo a, &pr
if pr
a.map(&pr).join
else
MyEnum.new(a)
end
end
class MyEnum < Enumerator
def initialize a
#a = a
...
end
...
end
But calling MyEnum.new raises a warning message: Enumerator.new without a block is deprecated; use Object#to_enum. If I use to_enum, I think it would return a plain Enumerator instance, not the MyEnum with the specific feature built in. On top of that, I am not sure how to implement MyEnum in the first place. How can I implement such enumerator? Or, what is the right way to do this?
You could do something like this.
def foo a, &pr
if pr
a.map(&pr).join
else
o = Object.new
o.instance_variable_set :#a, a
def o.each *y
foo #a.map { |z| yield z, *y } { |e| e }
end
o.to_enum
end
end
Then we have
enum = foo([1,2,3])
enum.each { |x| 2 * x } # "246"
or
enum = foo([1,2,3])
enum.with_index { |x, i| x * i } # "026"
Inspiration was drawn from the Enumerator documentation. Note that all of your expectations about enumerators like you asked for hold, because .to_enum takes care of all that. enum is now a legitimate Enumerator!
enum.class # Enumerator

Return a value from a block without returning from method

I have a class Test:
class Test
attr_accessor :data
def initialize
#data = [0, 1, 2, 3]
end
def map
#data.map!{|i| i = yield i }
end
end
and I attempt to use it like:
a = Test.new
a.map{|i|
if(i==2)
i+=1
break i #<--- -This line is the focus
else
1
end
}
puts a.data
The output I expect is [1, 1, 3, 3]. Instead, I get [1, 1, 2, 3]. The last iteration of the block in map doesn't return the modified i.
I replaced break i with next i. This performed as I expected, and produced the output [1, 1, 3, 1].
How can I modify this piece of code (or, ideally the line I point out in my second code-snippet) so that I would get the output [1, 1, 3, 3]? In other words, how can I make the block finish, but pass one last value back to map? Is there a neat and readable way to do this (besides, say, toggling a boolean flag break_now)?
I'm assuming you're asking how to leave a block and make use of the last value that was calculated rather than how to calculate a specific set of numbers; for the latter, there is probably a clever one-liner.
How about something like this:
class Test
attr_accessor :data
def initialize
#data = [0, 1, 2, 3]
end
def modify
#data.map! {|i| yield i }
end
end
a = Test.new
a.modify do |i|
break i if #done
#done = i == 2
#done ? (i + 1) : 1
end
puts a.data
An additional thought—#map is an important method in Ruby with a specific interface. In your example you're violating the interface by modifying a field in Test. For this reason I've used the name #modify instead.
In general, you could get away with this by modifying the yielded values in place. For example, if your array consisted of Strings instead of Fixnums:
class Test
attr_accessor :data
def initialize
#data = %w{a b c d}
end
def map
#data.map! { |i| yield i }
end
end
a = Test.new
a.map do |i|
if i == 'c'
i.next!
break
else
'b'
end
end
p a.data #=> ["b", "b", "d", "d"]
The problem with your example is this:
Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object. Assignment does not alias Fixnum objects. There is effectively only one Fixnum object instance for any given integer value…
Fixnums can't be altered in-place, so your expression i += 1 in the lower block doesn't affect the value of i in the upper block. That's why you get 2 in your example but d in my example.
You have to do this:
a.map{ |i| (i % 2 == 0) ? i + 1 : i }
When you use map function you don't change 'a' variable, if you want change 'a' variable do this:
a.map!{ |i| (i % 2 == 0) ? i + 1 : i }
The new value of 'i' is the value return by the block, so don't do something like:
a.map{|i| i = 1 }
because if you do:
a.map{|i| i = 1; 5 }
the result will be:
[5, 5, 5, 5]

Resources