NoMethodError: undefined method `join' - ruby

So Here's the Ruby code I'm working on:
def translate(x)
array = x.split(" ")
array.each do |y|
if y.match(/^[aeiou]/)
y += "ay"
else
until y.match(/^[aeiou]/) do
var = y[/^[^aeiou]*/]
y.slice! /^[^aeiou]*/
y += (var + "ay")
end
end
x = y.join(" ")
x
end
end
There's an issue when I test it. It's this:
NoMethodError:
undefined method `join' for "appleay":String
Not at all sure what the matter with my join method is.

y is a string. If you need make from it array of chars you should do:
x = y.split(//).join(" ")
but probably you want to place it after the loop. It will looks like:
def translate(x)
array = x.split(" ")
x = []
array.each do |y|
if y.match(/^[aeiou]/)
y += "ay"
else
until y.match(/^[aeiou]/) do
var = y[/^[^aeiou]*/]
y.slice! /^[^aeiou]*/
y += (var + "ay")
end
end
x << y
end
x.join(' ')
end

Related

What's wrong with my code?

def encrypt(string)
alphabet = ("a".."b").to_a
result = ""
idx = 0
while idx < string.length
character = string[idx]
if character == " "
result += " "
else
n = alphabet.index(character)
n_plus = (n + 1) % alphabet.length
result += alphabet[n_plus]
end
idx += 1
end
return result
end
puts encrypt("abc")
puts encrypt("xyz")
I'm trying to get "abc" to print out "bcd" and "xyz" to print "yza". I want to advance the letter forward by 1. Can someone point me to the right direction?
All I had to do was change your alphabet array to go from a to z, not a to b, and it works fine.
def encrypt(string)
alphabet = ("a".."z").to_a
result = ""
idx = 0
while idx < string.length
character = string[idx]
if character == " "
result += " "
else
n = alphabet.index(character)
n_plus = (n + 1) % alphabet.length
result += alphabet[n_plus]
end
idx += 1
end
return result
end
puts encrypt("abc")
puts encrypt("xyz")
Another way to solve the issue, that I think is simpler, personally, is to use String#tr:
ALPHA = ('a'..'z').to_a.join #=> "abcdefghijklmnopqrstuvwxyz"
BMQIB = ('a'..'z').to_a.rotate(1).join #=> "bcdefghijklmnopqrstuvwxyza"
def encrypt(str)
str.tr(ALPHA,BMQIB)
end
def decrypt(str)
str.tr(BMQIB,ALPHA)
end
encrypt('pizza') #=> "qjaab"
decrypt('qjaab') #=> "pizza"
Alternatively if you don't want to take up that memory storing the alphabet you could use character codings and then just use arithmetic operations on them to shift the letters:
def encrypt(string)
result = ""
idx = 0
while idx < string.length
result += (string[idx].ord == 32 ? (string[idx].chr) : (string[idx].ord+1).chr)
idx += 1
end
result
end
Other strange thing about ruby is that you do not need to explicitly return something at the end of the method body. It just returns the last thing by default. This is considered good style amongst ruby folks.
Your question has been answered, so here are a couple of more Ruby-like ways of doing that.
Use String#gsub with a hash
CODE_MAP = ('a'..'z').each_with_object({}) { |c,h| h[c] = c < 'z' ? c.next : 'a' }
#=> {"a"=>"b", "b"=>"c",..., "y"=>"z", "z"=>"a"}
DECODE_MAP = CODE_MAP.invert
#=> {"b"=>"a", "c"=>"b",..., "z"=>"y", "a"=>"z"}
def encrypt(word)
word.gsub(/./, CODE_MAP)
end
def decrypt(word)
word.gsub(/./, DECODE_MAP)
end
encrypt('pizza')
#=> "qjaab"
decrypt('qjaab')
#=> "pizza"
Use String#gsub with Array#rotate
LETTERS = ('a'..'z').to_a
#=> ["a", "b", ..., "z"]
def encrypt(word)
word.gsub(/./) { |c| LETTERS.rotate[LETTERS.index(c)] }
end
def decrypt(word)
word.gsub(/./) { |c| LETTERS.rotate(-1)[LETTERS.index(c)] }
end
encrypt('pizza')
#=> "qjaab"
decrypt('qjaab')
#=> "pizza"

Turning a method into an enumerable method

I rewrote the map method:
def my_map(input, &block)
mod_input = []
x = -1
while x < input.length - 1
x = x + 1
if block == nil
return input
break
end
mod_input.push(block.call(input[x]))
end
return mod_input
end
I need to call this code as I would call map or reverse. Does anyone know the syntax for that?
Are you asking how you put a method into a module? That's trivial:
module Enumerable
def my_map(&block)
mod_input = []
x = -1
while x < length - 1
x = x + 1
if block == nil
return self
break
end
mod_input.push(block.call(self[x]))
end
return mod_input
end
end
[1, 2, 3, 4, 5].my_map(&2.method(:*))
# => [2, 4, 6, 8, 10]
Or are you asking how to make your method an Enumerable method? That's more involved: your method currently uses many methods that are not part of the Enumerable API. So, even if you make it a member of the Enumerable module, it won't be an Enumerable method. Enumerable methods can only use each or other Enumerable methods. You use length and [] both of which are not part of the Enumerable interface, for example, Set doesn't respond to [].
This would be a possible implementation, using the Enumerable#inject method:
module Enumerable
def my_map
return enum_for(__method__) unless block_given?
inject([]) {|res, el| res << yield(el) }
end
end
[1, 2, 3, 4, 5].my_map(&2.method(:*))
# => [2, 4, 6, 8, 10]
A less elegant implementation using each
module Enumerable
def my_map
return enum_for(__method__) unless block_given?
[].tap {|res| each {|el| res << yield(el) }}
end
end
[1, 2, 3, 4, 5].my_map(&2.method(:*))
# => [2, 4, 6, 8, 10]
Note that apart from being simply wrong, your code is very un-idiomatic. There is also dead code in there.
the break is dead code: the method returns in the line just before it, therefore the break will never be executed. You can just get rid of it.
def my_map(&block)
mod_input = []
x = -1
while x < length - 1
x = x + 1
if block == nil
return self
end
mod_input.push(block.call(self[x]))
end
return mod_input
end
Now that we have gotten rid of the break, we can convert the conditional into a guard-style statement modifier conditional.
def my_map(&block)
mod_input = []
x = -1
while x < length - 1
x = x + 1
return self if block == nil
mod_input.push(block.call(self[x]))
end
return mod_input
end
It also doesn't make sense that it is in the middle of the loop. It should be at the beginning of the method.
def my_map(&block)
return self if block == nil
mod_input = []
x = -1
while x < length - 1
x = x + 1
mod_input.push(block.call(self[x]))
end
return mod_input
end
Instead of comparing an object against nil, you should just ask it whether it is nil?: block.nil?
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x = x + 1
mod_input.push(block.call(self[x]))
end
return mod_input
end
Ruby is an expression-oriented language, the value of the last expression that is evaluated in a method body is the return value of that method body, there is no need for an explicit return.
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x = x + 1
mod_input.push(block.call(self[x]))
end
mod_input
end
x = x + 1 is more idiomatically written x += 1.
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x += 1
mod_input.push(block.call(self[x]))
end
mod_input
end
Instead of Array#push with a single argument it is more idiomatic to use Array#<<.
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x += 1
mod_input << block.call(self[x])
end
mod_input
end
Instead of Proc#call, you can use the .() syntactic sugar.
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x += 1
mod_input << block.(self[x])
end
mod_input
end
If you don't want to store, pass on or otherwise manipulate the block as an object, there is no need to capture it as a Proc. Just use block_given? and yield instead.
def my_map
return self unless block_given?
mod_input = []
x = -1
while x < length - 1
x += 1
mod_input << yield(self[x])
end
mod_input
end
This one is opinionated. You could move incrementing the counter into the condition.
def my_map
return self unless block_given?
mod_input = []
x = -1
while (x += 1) < length
mod_input << yield(self[x])
end
mod_input
end
And then use the statement modifier form.
def my_map
return self unless block_given?
mod_input = []
x = -1
mod_input << yield(self[x]) while (x += 1) < length
mod_input
end
Also, your variable names could use some improvements. For example, what does mod_input even mean? All I can see is that it is what you output, so why does it even have "input" in its name? And what is x?
def my_map
return self unless block_given?
result = []
index = -1
result << yield(self[index]) while (index += 1) < length
result
end
This whole sequence of initializing a variable, then mutating the object assigned to that variable and lastly returning the object can be simplified by using the K Combinator, which is available in Ruby as Object#tap.
def my_map
return self unless block_given?
[].tap {|result|
index = -1
result << yield(self[index]) while (index += 1) < length
}
end
The entire while loop is useless. It's just re-implementing Array#each, which is a) unnecessary because Array#each already exists, and b) means that your my_map method will only work with Arrays but not other Enumerables (for example Set or Enumerator). So, let's just use each instead.
def my_map
return self unless block_given?
[].tap {|result|
each {|element|
result << yield(element)
}
}
end
Now it starts to look like Ruby code! What you had before was more like BASIC written in Ruby syntax.
This pattern of first creating a result object, then modifying that result object based on each element of a collection and in the end returning the result is very common, and it even has a fancy mathematical name: Catamorphism, although in the programming world, we usually call it fold or reduce. In Ruby, it is called Enumerable#inject.
def my_map
return self unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
That return self is strange. map is supposed to return a new object! You don't return a new object, you return the same object. Let's fix that.
def my_map
return dup unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
And actually, map is also supposed to return an Array, but you return whatever it is that you called map on.
def my_map
return to_a unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
But really, if you look at the documentation of Enumerable#map, you will find that it returns an Enumerator and not an Array when called without a block.
def my_map
return enum_for(:my_map) unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
And lastly, we can get rid of the hardcoded method name using the Kernel#__method__ method.
def my_map
return enum_for(__method__) unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
Now, that looks a lot better!
class Array
def my_map(&block)
# your code, replacing `input` with `self`
end
end
The code itself is not really idiomatic Ruby - while is very rarely used for iteration over collections, and if you don't need to pass a block somewhere else, it is generally cleaner to use block_given? instead of block.nil? (let alone block == nil), and yield input[x] instead of block.call(input[x]).

How to improve time complexity of this code piece?

I am having a hard time trying to down down the time. If this can be done in O(n^2) thatd be awesome.
def printDistance(file)
line = file.gets
if line == nil then return end
sz, sx, sy, ex, ey = line.split(/\s/)
#counter = 0
while line = file.gets do
if line[0...4] == "path"
else
x, y, ds, w = line.split(/\s/,4)
x = x.to_i
y = y.to_i
matrix= Array.new
later = Array.new
tmp = Array.new
processing = Array.new
if matrix[y].class != Array
matrix[y] = Array.new
end
if ds == "" #this cell has NO way to get to
matrix[y][x] = nil
else
matrix[y][x] = ds
end
end
end
for y in 0...matrix.length
processing[y] = Array.new
tmp[y] = Array.new
later[y] = Array.new
end
printing = Array.new
counter = 0
sy = sy.to_i
sx = sx.to_i
processing[sy][sx] = matrix[sy][sx]
matrix[sy][sx] = nil
puts "#{counter},(#{sx},#{sy})" #first one
counter += 1
loop do
print "#{counter},"
counter += 1
for y in 0...processing.length
for x in 0...processing[y].length
if processing[y][x].class != nil
tmp[y][x] = processing[y][x]
dirArr = tmp[y][x].to_s.split(//)
dirArr.each { |c|
if c == "u"
newY = y - 1
newX = x
elsif c == "d"
newY = y + 1
newX = x
elsif c == "l"
newY = y
newX = x - 1
else #c == r
newY = y
newX = x + 1
end
if matrix[newY][newX] != nil
tmpStr = "(#{newX},#{newY})"
printing.unshift(tmpStr)
later[newY][newX] = matrix[newY][newX]
matrix[newY][newX] = nil
end
}
end
end
end
printing.sort!
for i in 0...printing.length
print printing[i]
if i < printing.length - 1
print ","
end
end
printing = [] #resetting
puts
for i in 0...later.length
for j in 0...later[i].length
if later[i][j] != nil
processing[i][j] = later[i][j]
end
end
end
break if NotEmpty(matrix) == false
end
end
def NotEmpty (a)
for i in 0...a.length
for j in 0...a[i].length
if a[i][j] != nil
return true
end
end
end
return false
end
Basically this code reads in a file and places it in a 2-d array representing a maze, then based on maze's starting point it will perform a BFS to put all cells in order from closest to the start to the farthest, then print everything out
This code is now O(n^3) but I am trying to shrink it to O(n^2), is there anyway I can traverse a 2-d array and keeping track of the x and y values without using two forloops?
Any help is appreciated!! Thanks!

very simple ruby programing, getting error and don't understand it

I'm asked to write the ruby program that generate the output based the given command,
The full description
I'm really new in ruby (maybe few hours that I have started ruby)
I'm getting this error, please check my code for other possible errors:
Thank you.
n `block in each2': undefined method `[]' for #<MyVector:0x00000002c4ad90 #array=[2, 3, 4]> (NoMethodError)
What I have done so far:
# MyVector Class
class MyVector
def initialize (a)
if !(a.instance_of? Array)
raise "ARGUMENT OF INITIALIZER MUST BE AN ARRAY"
else
#array = a
end
end
def array
#array
end
def to_s
#array.to_s
end
def length
#array.length
end
def each2(a)
raise Error, "INTEGER IS NOT LIKE VECTOR" if a.kind_of?(Integer)
Vector.Raise Error if length != a.length
return to_enum(:each2, a) unless block_given?
length.times do |i|
yield #array[i], a[i]
end
self
end
def * (a)
Vector.Raise Error if length != a.length
p = 0
each2(a) {|a1, a2|p += a1 * a2}
p
end
end
# MyMatrix Class
class MyMatrix
def initialize a
#array=Array.new(a.length)
i=0
while(i<a.length)
#array[i]=MyVector.new(a[i])
end
end
def to_s
#array.to_s
end
def transpose
size=vectors[0].length
arr= Array.new(size)
i=0
while i<size
a=Array.new(vector.length)
j=0
while j<a.length
a[j]=vectors[j].arr[i]
j+=1
end
arr[i]=a
i+=1
end
arr[i]=a
i+=1
end
def *m
if !(m instance_of? MyMatrix)
raise Error
a=Array.new(#array.length)
i=0
while (i<#array.length)
a[i]=#array[i]*m
i=i+1
end
end
end
end
Input:
Test code
v = MyVector.new([1,2,3])
puts "v = " + v.to_s
v1 = MyVector.new([2,3,4])
puts "v1 = " + v1.to_s
puts "v * v1 = " + (v * v1).to_s
m = MyMatrix.new([[1,2], [1, 2], [1, 2]])
puts "m = " + m.to_s + "\n"
puts "v * m = " + (v * m).to_s
m1 = MyMatrix.new([[1, 2, 3], [2, 3, 4]])
puts "m1 = " + m1.to_s + "\n"
puts "m * m1 = " + (m * m1).to_s
puts "m1 * m = " + (m1 * m).to_s
Desired Output:
v = 1 2 3
v1 = 2 3 4
v * v1 = 20
m =
1 2
1 2
1 2
v * m = 6 12
m1 =
1 2 3
2 3 4
m * m1 =
5 8 11
5 8 11
5 8 11
m1 * m =
6 12
9 18
length.times do |i|
yield #array[i], a[i]
end
In the above block, a is an instance of MyVector. You need to define the [] operator on it, probably something like:
def [](i)
#array[i]
end

ArgumentError in #new, Subclassing Enumerator

I'm subclassing Enumerator like this:
class CuadraticPrimeGenerator < Enumerator
def initialize(a=1,b=49)
super do |y|
x = 1
loop do
y << x**2 + a*x + b
x += 1
end
end
end
end
However...
> CuadraticPrimeGenerator.new(1,49)
0027.rb:41:in `initialize': 49 is not a symbol (TypeError)
from 0027.rb:41:in `initialize'
from 0027.rb:48:in `new'
from 0027.rb:48:in `<main>'
Thoughts?
What about:
class CuadraticPrimeGenerator < Enumerator
def initialize(a=1,b=49)
super() do |y|
count, x = 0, 1
loop { y.yield(x**2 + a*x + b) }
end
end
end

Resources