Recursion and linked list - ruby

I want to see the representation of the linked list. I created a class for creating a linked list:
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
def print_values(list_node)
print "#{list_node.value} --> "
if list_node.next_node.nil?
print "nil"
return
else
print_values(list_node.next_node)
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
print_values(node3)
end
I get:
practice.rb:24:in `<class:LinkedListNode>': undefined method `print_values' for LinkedListNode:Class (NoMethodError)
Is recursion a method calling itself? Is it possible to have a method call another method to replace recursion? Or is calling another method not allowed?

Is recursion a method calling upon itself?
Yes, generally. For specifics, examples, and exceptions see Wikipedia.
You may be able to understand recursion in your own code if you simplify your method.
The code that you wrote is more akin to procedural code, whereas Ruby typically uses object oriented code that is more akin to this:
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
# This is how to write a typical Ruby recursive method.
# Notice the method does something with this object's value,
# then transfers control to the next object's same method name.
def to_s
"#{value} --> " + (next_node ? next_node.to_s : "nil")
end
end
# This code is moved out of your class definition.
# This fixes one of the errors in your original code.
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
print node3.to_s
Is it possible to have a method call on another method to replace recursion?
Yes, generally. For example in your code, you could call a method that uses iteration instead of recursion, something like this example.
Recursion:
def to_s
"#{value} --> " + (next_node ? next_node.to_s : "nil")
end
Iteration:
def to_s
s = ""
node = self
while node != nil
s += "#{value} --> "
node = next_node
end
s += "nil"
end
An algorithm that is implemented using iteration often runs much faster than a similar algorithm that is implemented using recursion.
Some kinds of recursion (including your code here) are much more efficient than other kinds of recursion. Your code is a good example of code that can use efficient tail call optimization.

Your print_values method is an instance method, though it does not use the instance in it.
I believe you meant to use the instance data for your implementation:
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
def print_values
print "#{value} --> "
if next_node.nil?
print "nil"
return
else
next_node.print_values
end
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
node3.print_values
Another option is to make the method a static method, which does not need an instance, which will look like:
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
def self.print_values(list_node)
print "#{list_node.value} --> "
if list_node.next_node.nil?
print "nil"
return
else
print_values(list_node.next_node)
end
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
LinkedListNode.print_values(node3)
Both options will be considered recursive, since the method calls itself. There are no rules about recursion (calling another method is allowed), but there are things you need to be aware of, like if you don't have a good stopping condition, your method might "explode" with a stack overflow exception.

You should move the code dealing with class out of the class definition:
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
def print_values(list_node)
print "#{list_node.value} --> "
if list_node.next_node.nil?
print "nil"
return
else
print_values(list_node.next_node)
end
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
node3.print_values(node3)
The code has an amount of other glitches, like print_values is ment to be a class method, rather than instance method, but the main problem is above. This is how I would turn the code to use class method for printing values:
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
def self.print_values list_node
print "#{list_node.value} --> "
if list_node.next_node.nil?
print "nil"
return
else
print_values(list_node.next_node)
end
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
LinkedListNode.print_values node3
Hope it helps.
NB The answer provided by #joelparkerhenderson is in fact a way better.

Related

Ruby Binary Search Tree insert method stack level too deep

I am trying to write a recursive insert method for a binary search tree but keep getting stack level too deep What is going on that it keeps giving me the error?
my node class
class Node
attr_accessor :value, :left, :right
def initialize(value)
#value = value
left = nil
right = nil
end
end
binary search tree class
class Bst
attr_accessor :root, :size
def initialize
#root = nil
#size = 0
end
def insert(value, root=nil)
if #root == nil
#root = Node.new(value)
end
if value < #root.value
if #root.left == nil
#root.left = Node.new(value)
else
return insert(value, #root.left)
end
return root
end
if value > #root.value
if #root.right == nil
#root.right = Node.new(value)
else
return insert(value, #root.right)
end
end
return root
end
It happens once I try to add 4 to the tree
tree = Bst.new
tree.insert(10)
tree.insert(6)
tree.insert(19)
tree.insert(4)
When you recurse and provide new root, you are still comparing the value with #root.value.
Since 4 is still less than 10, you recurse, and pass #root.left as root. However, root is never used; you are again comparing #root.value, and recursing with #root.left, and those never change; thus, you have infinite recursion (or at least infinite till you blow the stack).
You want to be comparing to root.value, and recursing with root.left instead.
Having #root and root be different things is confusing, and leads to logic errors. Better variable naming would likely have prevented this error.
EDIT:
class Node
attr_accessor :value, :left, :right
def initialize(value)
#value = value
#left = nil
#right = nil
end
end
class Bst
attr_accessor :root, :size
def initialize
#root = nil
#size = 0
end
def insert(value, node=nil)
unless #root
#root = Node.new(value)
return
end
node ||= #root
if value < node.value
if node.left
return insert(value, node.left)
else
node.left = Node.new(value)
end
elsif value > node.value
if node.right
return insert(value, node.right)
else
node.right = Node.new(value)
end
end
#size += 1
return node
end
end
tree = Bst.new
tree.insert(10)
tree.insert(6)
tree.insert(19)
tree.insert(4)
p tree

inserting in linked lists with ruby

Hi I'm trying to insert a value at a specific index in a linked list in ruby.
Here is my code thus far:
class Node
attr_accessor :data, :pointer, :next
def initialize(data, pointer = nil)
#data = data
#pointer = pointer
end
def next
#data = #pointer
end
end
class LinkedList
attr_accessor :head, :data, :pointer
def initialize(data)
#head = Node.new(data, pointer)
end
def index_at(value_of_index)
current = head
value_of_index.times do
if current.pointer == nil
current = Node.new(nil, nil)
return current = current.data
else
current = current.next
end
end
current.data
end
def insert_at_index(index, value)
current = head
index.times do
current.next
end
current = Node.new(value)
end
end
The problem I've having is with the def insert_at_index method... I can't seem to figure out how to place the new node at the index and value. Any help you can give me would be greatly appreciated.
Say your linked list looks like this:
a -> b -> d -> e
To insert c into the 3rd index, you would move to the second index to get b, create a new node, set b's next to the new node c, and set c's next to the old third index item, d.
This will give you:
a -> b -> c -> d -> e
That said, the code should look like this:
def insert_at_index(index, value)
current = head
# make current b. You may want to put this in a function node_at_index
(index - 1).times do
raise "List not long enough" if current.nil?
current = current.next
end
new_node = Node.new(value) # new node c
new_node.next = current.next # c's next is b's next, d
current.next = new_node # b's next is c
end
From the looks of it there seem to be other issues with your code as well. You're overwriting #data in your next function (you probably meant to just return #pointer), LinkedList#initialize doesn't have pointer defined, etc
You could simplify your Node to look like this:
class Node
attr_accessor :data, :next
def initialize(data, next=nil)
#data = data
#next = next
end
end
Which should work for you.
Here is one solution that worked for me:
class Node
attr_accessor :data, :pointer
alias_method :next, :pointer
def initialize(data, pointer = nil)
#data = data
#pointer = pointer
end
def next
#pointer
end
end
class LinkedList
attr_accessor :head, :data, :pointer
def initialize(data)
#head = Node.new(data, pointer)
end
def index_at(value_of_index)
current = head
value_of_index.times do
if current.pointer == nil
current = Node.new(nil, nil)
return current = current.data
else
current = current.next
end
end
current.data
end
def insert_at_index(index, value)
current = head
(index - 1).times do
if current.pointer != nil
current = current.next
end
end
new_node = Node.new(value)
if current.pointer != nil
new_node.pointer = current.pointer
end
current.pointer = new_node
end
end

Ruby Singly Linked List Implementation

I'd like to write an exist function that returns true if a value exists as a node in a linkedlist and returns false otherwise. So far, I have the following code which always returns true. Any help is appreciated:
class SinglyLinkedList
attr_accessor :head, :tail, :count
def initialize
#head = nil
#tail = nil
#count = 0
end
def insert_front(value)
node = Node.new(value)
if #head.nil?
#head = node
#tail = node
else
node.next = #head
#head = node
end
#count +=1
end
def print_first()
puts head.data
end
def print_last()
puts tail.data
end
def exist(value)
walker = #head
until walker.nil?
if walker.data == value
return true
end
walker = walker.next
end
false
end
def size()
count
end
end
class Node
attr_accessor :data, :next
def initialize(data)
#next = nil
#data = data
end
end
This is my test code:
list = SinglyLinkedList.new
list.insert_front(1)
list.exist(2)
which returns true.
Before solution just consider that singly linked list can insert only via append to list. You try to insert nodes in wrong direction.
The problem with you code is that you use reserved method name next, just refactor you code and write simple:
class SinglyLinkedList
class Node
attr_reader :value
attr_accessor :pointer
def initialize(value, pointer = nil)
#value = value
#pointer = pointer
#count = 0
end
end
attr_reader :head, :tail
def initialize
#head = nil
#tail = nil
end
def insert(value)
node = Node.new(value)
#count += 1
if #head.nil?
#head = node
#tail = node
else
#tail.pointer = node
#tail = node
end
end
def inspect
return [] unless #head
values = []
node = #head
begin
values << node.value
node = node.pointer
end while node != nil
values
end
def exists?(value)
return false unless #head
node = #head
begin
node = node.pointer
end while node != nil && node.value != value
node.nil?
end
end

Implement a tree iterator

I created a very simple node class with a name and an array of nodes. I also created an iterator class with a next method that helps me iterate on each node and child nodes. I need to write the next method, but I don't what is the best way to do it.
class Node
def initialize(name, nodes
#name = name
#nodes = nodes
end
end
class Iterator
def initialize(node)
#node = node
end
def next
???
end
end
Example:
z = Node.new("z", [])
b = Node.new("b", [z])
c = Node.new("c", [])
parent = Node.new("a", [b, c])
iterator = Iterator.new(parent)
str = ''
next = iterator.next
while next do
str += next.name
next = iterator.next
end
str should equal "abzc"
Can anybody help me with this?
If I may suggest a more idiomatic approach:
class Node
attr_accessor :name, :children
def initialize(name, children = [ ])
#name = name
#children = children
end
def traverse(&block)
yield self
#children.each { |child| child.traverse(&block) }
end
end
z = Node.new("z")
b = Node.new("b", [z])
c = Node.new("c")
parent = Node.new("a", [b, c])
str = ''
parent.traverse { |node| str += node.name }
puts str
This has a benefit over btilly's solution (which is also correct) in that it doesn't proliferate Iterator objects and suck up memory- in fact Iterator disappears from the implementation (while still retaining the ability to DO something to each node in succession). This is more idiomatic; more Ruby-esque.
In your iterator, if node has any children, next would be the first of them. If it doesn't, then you need to "back up" to the last sibling that you skipped over. This implies that you need to keep track of the siblings that have been skipped over, so that you can go back to them.
Here is some running code that demonstrates what I think you're looking for.
class Node
attr_accessor :name, :nodes
def initialize(name, nodes)
#name = name
#nodes = nodes
end
end
class Iterator
def initialize(node)
#node = node
end
def each_node
yield #node
for node in #node.nodes do
iterator = Iterator.new(node)
iterator.each_node {|next_node|
yield next_node
}
end
end
end
z = Node.new("z", [])
b = Node.new("b", [z])
c = Node.new("c", [])
parent = Node.new("a", [b, c])
iterator = Iterator.new(parent)
str = ''
iterator.each_node {|node|
str += node.name
}
puts str
I have been able to solve my problem by doing the following. But what I don't like with this approach is that I traverse the nodes during the initialization instead of in the next method...
class Iterator
def initialize(node)
#node = node
#index = -1
#list = []
traverse(#node)
end
def next
#index += 1
#list[#index]
end
private
def traverse(root)
#list[#list.size] = root
if root.nodes
for n in root.nodes do
traverse(n)
end
end
end
end

ruby hash tree with blocks

how can I do this:
class MyClass
tile 'some title'
collection do
node1 'node1'
node2 'node2'
another_collection do
node1 'node1'
node2 'node2'
end
end
end_node 'some text'
end
and produce following:
MyClass.build #=>{:title=>'some title',:collection=>{:node1=>'node1',:node2=>'node2',:another_collection=>{:node1=>'node1',:node2=>'node2'}},:end_node=>'some text'}
What i was trying is to make simple DSL and build hash tree. I'm sure that can be done with method_missing and instance_eval, but i don't now how to build that logic.
Thanks for help
In your method_missing, you should check if a block is given, and, if so, recursively call the main method with it:
class HashBuilder
def self.build &block
hb = HashBuilder.new
hb.instance_eval(&block)
hb.hash
end
attr_reader :hash
def initialize
#hash = {}
end
def method_missing meth, *args, &block
#hash[meth] = block ? HashBuilder.build(&block) : args.first
end
end
p HashBuilder.build{
a :b
c :d
e do
f :g
end
}
#=> {:a=>:b, :c=>:d, :e=>{:f=>:g}}

Resources