How to combine two procs into one? - ruby

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

Related

Harmonic series

1.upto(sums) do |n|
puts harmonic_sum(n)
end
is there a way to label whatever is outputed so if the user enters 6 it counts them as 1 2 3 4 5 6?
The harmonic series isn't implemented in Ruby standard library, but Rational is :
def harmonic_sum(n)
(1..n).inject(Rational(0,1)) {|r, i| r + Rational(1,i) }
end
puts harmonic_sum(5)
#=> 137/60
puts harmonic_sum(50)
#=> 13943237577224054960759/3099044504245996706400
puts harmonic_sum(10_000).to_f
#=> 9.787606036044382
NOTE: Your code is fine BTW. Here are some slight modifications and a few TODOS ;)
class Fraction
attr_reader :numerator, :denominator
def initialize(n, d)
#numerator = n
#denominator = d
end
def to_f
numerator.to_f/denominator
end
#TODO: Add *
#TODO: Define - and / with + and *
#TODO: Check that rhs is a Fraction, convert self to float otherwise.
def +(rhs)
n = #numerator*rhs.denominator + #denominator*rhs.numerator
d = #denominator*rhs.denominator
n, d = reduce(n, d)
return Fraction.new(n, d)
end
def to_s
"#{#numerator} / #{#denominator}"
end
private
def reduce(n, d)
r = gcd(n, d)
return n / r, d / r
end
def gcd(a, b)
if a % b == 0
return b
else
return gcd(b, a % b)
end
end
end
def harmonic_sum(n)
(1..n).inject(Fraction.new(0,1)) {|r, i| r + Fraction.new(1,i) }
end
puts harmonic_sum(100)
#=> 14466636279520351160221518043104131447711 / 2788815009188499086581352357412492142272

Rewriting Ruby Inject

Here is a brain bender.
I am trying to rewrite the Ruby Inject method. I have got as far as below.
class Array
def injector(input = nil)
if input == nil
num = self.first
else
num = input
end
self[0..-1].each do |x|
num = yield(num, x)
end
return num
end
end
It is passing some tests, but it is not fully accurate, for example;
[1,2,3,4,5].injector(0) {|x,y| x + y} #=> 14
As opposed to the expected output 15, is it a rounding error? I cannot seem to figure this one out
Additional example (above updated [0..-1]):
[9,8,7,6,5].injector {|x,y| x * y} #=> 136080
Ruby .inject outputs 15120
The starting index is important as it depends on your input.
class Array
def injector(input = nil)
if input.nil?
start = 1
num = self.first
else
start = 0
num = input
end
self[start..-1].each do |x|
num = yield(num, x)
end
return num
end
end
Using nil as the default is probably wrong, I should be able to pass nil in as the default memo.
class Array
def injector(memo = (i=1; first))
(i||0).upto(length-1) { |i| memo = yield memo, self[i] }
memo
end
end
[1,2,3,4,5].injector(1) { |sum, n| sum + n }
[1,2,3,4,5].injector(0) { |sum, n| sum + n }
[1,2,3,4,5].injector { |sum, n| sum + n }
[1,2,3].injector(2) { |product, n| product * n }
[1,2,3].injector(1) { |product, n| product * n }
[1,2,3].injector { |product, n| product * n }
['b', 'c', 'd'].injector('a') { |str, char| str + char } # => "abcd"
['b', 'c', 'd'].injector { |str, char| str + char } # => "bcd"
seen = []
[1].injector(nil) { |prev, crnt| seen << prev << crnt }
seen # => [nil, 1]

Ruby find max number w/o running method twice

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

Add to Array Loop

Ruby code is:
a = []
h = {}
2.times.each do |i|
%w(a b c).each do |x|
h[x] = x + i.to_s
end
a << h
end
the result is:
a = [{"c"=>"c1", "b"=>"b1", "a"=>"a1"}, {"c"=>"c1", "b"=>"b1", "a"=>"a1"}]
but i hope the result is:
a = [{"c"=>"c0", "b"=>"b0", "a"=>"a0"}, {"c"=>"c1", "b"=>"b1", "a"=>"a1"}]
who can help me.thx
After a << h you have to do h = {}. This is because you are assigning a new object to h so that it doesn't override the previous values.
[Complementary answer] Are you familiar with the principles of functional programming?
(0..1).map { |n| Hash[("a".."c").map { |c| [c, "#{c}#{n}"] }] }
#=> {"a"=>"a0", "b"=>"b0", "c"=>"c0"}, {"a"=>"a1", "b"=>"b1", "c"=>"c1"}]

Ruby's Eqv for Mathematica's Nest Function?

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.

Resources