How should I convert it to the real number? - algorithm

I tried both str and repr. but both of them doesn't work and still return <main.UnorderedList object at 0x10cefccc0> these things.
class Stack:
def __init__(self):
self.items = UnorderedList()
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def __repr__(self):
return str(self.items)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items) - 1]
def size(self):
length = self.items.size()
count = 0
for i in range(0, length):
count += 1
return count
print(stack_list.__repr__())
result is:
[<main.Node object at 0x10db27c18>, <main.Node object at 0x10db27d30>]

If you are interested in getting the output you wrote after "result is" then (your question is a bit unclear and) you can use this code:
def __repr__(self):
return '[ %s ]' % ', '.join(repr(item) for item in self.items)
The __repr__() function is supposed to return a representation of the object, though, which should recreate the object again when interpreted. So consider this instead:
class Stack:
def __init__(self, items):
self.items = UnorderedList(items)
def __repr__(self):
return 'Stack([ %s ])' % ', '.join(repr(item) for item in self.items)
This will produce repr output like Stack([ "foo", "bar" ]).
I find it peculiar, though, that you program a stack which is based on an unordered list. This is confusing and I would not recommend to do that in the first place. Normally, stacks have a fixed order of their items.

Related

Sum values recursively in one line

I am pretty sure that it can be done in one line using things like map, sum etc. I cannot figure out how exactly, because I just started learning ruby. Could someone help? Thanks
class Something < ApplicationRecord
def function
res = items.count
items.each do |i|
res += i.function
end
res
end
I'm not sure why you need to do it recursively and in one line, but you can try something like this:
edit:
def add(arr)
return 0 if arr.length == 0
# if the arr argument is an empty array, return 0.
arr[0] + add(arr[1..-1])
# add the first element of the array to the result of calling add
# on the array minus the first element.
end
If you just want to sum an array as concisely as possible, all you need to do is [1, 2, 3].sum or [1,2,3,4].reduce(&:+). No recursion needed.
The straightforward oneliner equivalent to yours:
def function
items.count + items.sum(&:function)
end
Demo (testing it alongside your original):
class Something
attr_accessor :items
def initialize(items = [])
self.items = items
end
def function
res = items.count
items.each do |i|
res += i.function
end
res
end
def function2
items.count + items.sum(&:function2)
end
end
root = Something.new([
Something.new,
Something.new([
Something.new,
Something.new([
Something.new,
Something.new([
Something.new
])
])
])
])
puts root.function
puts root.function2
Prints:
7
7
Another way:
def function
items.sum { |i| 1 + i.function }
end
By the way, you count all items except for the root item. Is that intentional?
You could count all including the root with this:
def function
1 + items.sum(&:function)
end
Not in one line but this is how you can do this recursively.
def add_array(arr)
return arr.first if arr.length == 1
return nil if arr.length < 1
arr.pop + add_arr(arr)
end

ruby trie implementation reference issue

I am trying to implement a trie in Ruby but can't figure out what the problem is with my print + collect methods.
I just implemented the same in JS and working fine. I guess the issue could be that Ruby is passed by reference (unlike JS) and how variable assignment works in Ruby.
So if I run the code with string.clone as argument when I recursively call the collect function then I get:
["peter", "peter", "petera", "pdanny", "pdjane", "pdjanck"]
and if I pass string then:
["peterradannyjaneck", "peterradannyjaneck", "peterradannyjaneck", "peterradannyjaneck", "peterradannyjaneck", "peterradannyjaneck"]
Any ideas how to fix this?
the code:
class Node
attr_accessor :hash, :end_node, :data
def initialize
#hash = {}
#end_node = false
#data = data
end
def end_node?
end_node
end
end
class Trie
def initialize
#root = Node.new
#words = []
end
def add(input, data, node = #root)
if input.empty?
node.data = data
node.end_node = true
elsif node.hash.keys.include?(input[0])
add(input[1..-1], data, node.hash[input[0]])
else
node.hash[input[0]] = Node.new
add(input[1..-1], data, node.hash[input[0]])
end
end
def print(node = #root)
collect(node, '')
#words
end
private
def collect(node, string)
if node.hash.size > 0
for letter in node.hash.keys
string = string.concat(letter)
collect(node.hash[letter], string.clone)
end
#words << string if node.end_node?
else
string.length > 0 ? #words << string : nil
end
end
end
trie = Trie.new
trie.add('peter', date: '1988-02-26')
trie.add('petra', date: '1977-02-12')
trie.add('danny', date: '1998-04-21')
trie.add('jane', date: '1985-05-08')
trie.add('jack', date: '1994-11-04')
trie.add('pete', date: '1977-12-18')
print trie.print
Ruby's string concat mutates the string and doesn't return a new string. You may want the + operator instead. So basically change the 2 lines inside collect's for-loop as per below:
stringn = string + letter
collect(node.hash[letter], stringn)
Also, you probably want to either always initialize #words to empty in print before calling collect, or make it a local variable in print and pass it to collect.

Ruby: Instantiating a new variable within a block

I'm trying to shorten my Ruby code.
def count_palindromes_in_an(array)
palindromes = 0
array.each { |word| palindromes += 1 if word == word.reverse }
return palindromes
end
so that palindromes is instantiated within the block executed by the each method. Something along the lines of;
def count_palindromes_in_an(array)
array.each { |word| (palindromes != nil ? palindromes += 1 : palindromes = 1) if word == word.reverse }
return palindromes
end
However this returns an error of undefined method 'palindromes'. Any tips gratefully received.
This is not going to work because a block creates a new scope. Variables defined inside the block are isolated from the outer scope.
[1].each do
palindromes = 1
local_variables #=> [:palindromes]
end
local_variables #=> []
To count array elements, use Array#count:
array.count { |word| word == word.reverse }
You could even add a palindrome? method to String:
class String
def palindrome?
self == reverse
end
end
And shorten your code to:
array.count(&:palindrome?)

Check if two linked lists are equal in Ruby?

I have the following implementation of a linked list in Ruby:
class Node
attr_accessor :data, :next
def initialize(data = nil)
#data = data
#next = nil
end
end
class LinkedList
def initialize(items)
#head = Node.new(items.shift)
items.inject(#head) { |last, data| #tail = last.next = Node.new(data) }
end
def iterate
return nil if #head.nil?
entry = #head
until entry.nil?
yield entry
entry = entry.next
end
end
def equal?(other_list)
#How do I check if all the data for all the elements in one list are the same in the other one?
end
end
I have tried using the .iterate like this:
def equals?(other_list)
other_list.iterate do |ol|
self.iterate do |sl|
if ol.data != sl.data
return false
end
end
end
return true
end
But this is doing a nested approach. I fail to see how to do it.
You can't do it easily with the methods you have defined currently, as there is no way to access a single next element. Also, it would be extremely useful if you implemented each instead of iterate, which then gives you the whole power of the Enumerable mixin.
class LinkedList
include Enumerable # THIS allows you to use `zip` :)
class Node # THIS because you didn't give us your Node
attr_accessor :next, :value
def initialize(value)
#value = value
#next = nil
end
end
def initialize(items)
#head = Node.new(items.shift)
items.inject(#head) { |last, data| #tail = last.next = Node.new(data) }
end
def each
return enum_for(__method__) unless block_given? # THIS allows block or blockless calls
return if #head.nil?
entry = #head
until entry.nil?
yield entry.value # THIS yields node values instead of nodes
entry = entry.next
end
end
def ==(other_list)
# and finally THIS - get pairs from self and other, and make sure all are equal
zip(other_list).all? { |a, b| a == b }
end
end
a = LinkedList.new([1, 2, 3])
b = LinkedList.new([1, 2, 3])
c = LinkedList.new([1, 2])
puts a == b # => true
puts a == c # => false
EDIT: I missed this on the first run through: equal? is supposed to be referential identity, i.e. two variables are equal? if they contain the reference to the same object. You should not redefine that method, even though it is possible. Rather, == is the general common-language meaning of "equal" as in "having the same value", so I changed it to that.
I think there is something wrong with your initialize method in LinkedList, regardless could this be what you need
...
def equal?(other_list)
other_index = 0
cur_index = 0
hash = Hash.new
other_list.iterate do |ol|
hash[ol.data.data] = other_index
other_index += 1
end
self.iterate do |node|
return false if hash[node.data.data] != cur_index
return false if !hash.has_key?(node.data.data)
cur_index += 1
end
return true
end
...
Assuming this is how you use your code
a = Node.new(1)
b = Node.new(2)
c = Node.new(3)
listA = [a,b,c]
aa = Node.new(1)
bb = Node.new(2)
cc = Node.new(3)
listB = [aa,bb,cc]
linkA = LinkedList.new(listA)
linkB = LinkedList.new(listB)
puts linkA.equal?(linkB)

Ruby yield called from within Integer#times not returning the evaluated block

Got a very simple question why when I define a block as so:
def test
yield
end
a=test{7} => a=7
yet when I define a block like this
def test(n)
n.times{ yield }
end
a=test(4){7} => 4
why does the return value become n not yield?
It is returning the value from Integer#times (which happens to be same number on which you called the method - as can be seen on the Rubinius source or on RubySpec) instead of the block return value.
Since Integer#times calls the block multiple times, you have basically two alternatives to that:
Combine the results of all the calls on an array and return that.
def test(n)
result = []
n.times { |current| result << yield(current) }
result
end
# Or, leveranging Enumerator#map:
def test(n)
n.times.map { |current| yield(current) }
end
# Or, still shorter, by forwarding the block:
def test(n, &block)
n.times.map(&block)
end
test(4) { |n| n * 2 } # => [0, 2, 4, 6]
Store the last value returned from the block on a variable, and return it:
def test(n)
result = nil
n.times { |current| result = yield(current) }
result
end
test(4) { |n| n * 2 } # => 6
If you look at the source, times method will return the number of times it ran, not the result of the block it runs.

Resources