Here's Mathematica's Nest function Definition. What's the eqv. in Ruby?
The idea is this:
nest(f, x, 3) #=> f(f(f(x)))
You could define your own using inject:
def nest(f, x, n)
n.times.inject(x) { |m| f.call(m) }
end
Then you could call it like this:
>> def f(x) 2*x end
>> nest(method(:f), 1, 3)
=> 8
If you want a function back (i.e. leave x unspecified) then you could return a lambda:
def nestx(f, n)
->(x) { n.times.inject(x) { |m| f.call(m) } }
end
and use it like this:
>> nestx(method(:f), 3).call(1)
=> 8
Or you could rearrange the nest arguments and use Proc#curry:
def nest(f, n, x)
n.times.inject(x) { |m| f.call(m) }
end
>> method(:nest).to_proc.curry.call(method(:f), 3).call(1)
=> 8
You can also use [] in place of call if want something that looks more like a function call:
def nest(f, n, x)
n.times.inject(x) { |m| f[m] }
end
>> method(:nest).to_proc.curry[method(:f), 3][1]
=> 8
I do not know Ruby, but I looked into the description of the language and wrote the following code..
Let it be your function
def func(x)
return sin(x)
end
and let define a nest function
def nest(f, x, n)
count = 0
while count<n
x = send(f, x)
count += 1
end
return x
end
Call it as nest(:func, 1, 3) and result will be 0.67843047736074
I've compared it with the result on http://www.wolframalpha.com and got the same answer.
Related
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]).
I want to find the max number without running the function twice
def foo(num)
num * 10
end
def bar
x = 0
for i in 0..5
if foo(i) > x
x = foo(i) # I don't want to run foo a second time
end
end
end
How about
def bar
(1..5).map{|i| foo(i)}.max
end
This will traverse 1 to 5, and max a new enumerable with foo(i) instead of i, then return the max.
If you want the value of x:
define_method(:foo) { |x| x * 10 }
(1..5).max_by { |x| foo(x) }
#=> 5
If you want the value of f(x):
(1..5).map { |x| foo(x) }.max
#=> 50
You can save the result of the function as a variable, so you can use it later without calling the function again.
Applied to your code example, it would look like this:
#...
fooOfI = foo(i)
if fooOfI > x
x = fooOfI
end
#...
Store the result of the method in a local variable.
def bar
x = 0
for i in 0..5
foo_result = foo i
if foo_result > x
x = foo_result
end
end
end
I would do some change in your code :
def foo(num)
num * 10
end
def bar
x = 0
for i in 0..5
_,x = [foo(i),x].sort #or you can write as x = [foo(i),x].max
end
x
end
p bar
# >> 50
Elegant and simple
foo = -> x { x * 10 }
(1..5).map(&foo).max
# => 50
In one iteration (no so elegant but performs better)
def foo(num); num * 10; end;
(1..5).reduce(-1.0/0) { |a, e| f = foo(e); f > a ? f : a }
# => 50
An example of what I'm trying to do is probably best:
def repeater(n = 1)
n.times { yield }
end
By default, repeater will go through the block given once. However, I want it to go through the block multiple times if given n > 1. For some reason the above code doesn't work.
For instance:
I would expect this to result in 64, but instead it returns 5:
y = 2
repeater(5) { y *= 2 }
Why is this happening? Where am I going wrong? I'm fairly new to yield, and don't understand it entirely (clearly).
The problem is that the return value of repeater is the return value of times, which will always be n, so you should interrogate the resulting value of y itself instead:
y = 2
repeater(5) { y *= 2 } #=> 5
y #=> 64
If you want repeater to actually return the final result, you could reduce over a Range:
def repeater(n = 1)
(0..n).reduce { yield }
end
y = 2
repeater(5) { y *= 2 } #=> 64
There is nothing wrong with yield. The function returns a result of n.times { … } which is obviously equals 5:
> 5.times { }
# => 5
You want to accumulate the result of yield and explicitely return it from your function.
I managed to solve this using the times method as I was attempting to do:
def repeater(n = 1)
(n - 1).times { yield }
yield
end
The above looks nice, as I wanted, but I was hoping I could do this with n.times instead of (n - 1).times.
The following is a solution using that, but it doesn't look elegant:
def repeater(n = 1)
result = nil
n.times {result = yield}
result
end
I'll attempt to find a more elegant solution.
Just wondering if there's a syntax shortcut for taking two procs and joining them so that output of one is passed to the other, equivalent to:
a = ->(x) { x + 1 }
b = ->(x) { x * 10 }
c = ->(x) { b.( a.( x ) ) }
This would come in handy when working with things like method(:abc).to_proc and :xyz.to_proc
More sugar, not really recommended in production code
class Proc
def *(other)
->(*args) { self[*other[*args]] }
end
end
a = ->(x){x+1}
b = ->(x){x*10}
c = b*a
c.call(1) #=> 20
a = Proc.new { |x| x + 1 }
b = Proc.new { |x| x * 10 }
c = Proc.new { |x| b.call(a.call(x)) }
you could create a union operation like so
class Proc
def union p
proc {p.call(self.call)}
end
end
def bind v
proc { v}
end
then you can use it like this
a = -> (x) { x + 1 }
b = -> (x) { x * 10 }
c = -> (x) {bind(x).union(a).union(b).call}
An updated answer. Proc composition is already available in Ruby 2.6. There are two methods << and >>, differing in the order of the composition. So now you can do
##ruby2.6
a = ->(x) { x + 1 }
b = ->(x) { x * 10 }
c = a >> b
c.call(1) #=> 20
I'm trying to learn Ruby, and am going through some of the Project Euler problems. I solved problem number two as such:
def fib(n)
return n if n < 2
vals = [0, 1]
n.times do
vals.push(vals[-1]+vals[-2])
end
return vals.last
end
i = 1
s = 0
while((v = fib(i)) < 4_000_000)
s+=v if v%2==0
i+=1
end
puts s
While that works, it seems not very ruby-ish—I couldn't come up with any good purely Ruby answer like I could with the first one ( puts (0..999).inject{ |sum, n| n%3==0||n%5==0 ? sum : sum+n }).
For a nice solution, why don't you create a Fibonacci number generator, like Prime or the Triangular example I gave here.
From this, you can use the nice Enumerable methods to handle the problem. You might want to wonder if there is any pattern to the even Fibonacci numbers too.
Edit your question to post your solution...
Note: there are more efficient ways than enumerating them, but they require more math, won't be as clear as this and would only shine if the 4 million was much higher.
As demas' has posted a solution, here's a cleaned up version:
class Fibo
class << self
include Enumerable
def each
return to_enum unless block_given?
a = 0; b = 1
loop do
a, b = b, a + b
yield a
end
end
end
end
puts Fibo.take_while { |i| i < 4000000 }.
select(&:even?).
inject(:+)
My version based on Marc-André Lafortune's answer:
class Some
#a = 1
#b = 2
class << self
include Enumerable
def each
1.upto(Float::INFINITY) do |i|
#a, #b = #b, #a + #b
yield #b
end
end
end
end
puts Some.take_while { |i| i < 4000000 }.select { |n| n%2 ==0 }
.inject(0) { |sum, item| sum + item } + 2
def fib
first, second, sum = 1,2,0
while second < 4000000
sum += second if second.even?
first, second = second, first + second
end
puts sum
end
You don't need return vals.last. You can just do vals.last, because Ruby will return the last expression (I think that's the correct term) by default.
fibs = [0,1]
begin
fibs.push(fibs[-1]+fibs[-2])
end while not fibs[-1]+fibs[-2]>4000000
puts fibs.inject{ |sum, n| n%2==0 ? sum+n : sum }
Here's what I got. I really don't see a need to wrap this in a class. You could in a larger program surely, but in a single small script I find that to just create additional instructions for the interpreter. You could select even, instead of rejecting odd but its pretty much the same thing.
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
puts fib.take_while{|i| i < 4000000}
.reject{|x| x.odd?}
.inject(:+)
That's my approach. I know it can be less lines of code, but maybe you can take something from it.
class Fib
def first
#p0 = 0
#p1 = 1
1
end
def next
r =
if #p1 == 1
2
else
#p0 + #p1
end
#p0 = #p1
#p1 = r
r
end
end
c = Fib.new
f = c.first
r = 0
while (f=c.next) < 4_000_000
r += f if f%2==0
end
puts r
I am new to Ruby, but here is the answer I came up with.
x=1
y=2
array = [1,2]
dar = []
begin
z = x + y
if z % 2 == 0
a = z
dar << a
end
x = y
y = z
array << z
end while z < 4000000
dar.inject {:+}
puts "#{dar.sum}"
def fib_nums(num)
array = [1, 2]
sum = 0
until array[-2] > num
array.push(array[-1] + array[-2])
end
array.each{|x| sum += x if x.even?}
sum
end