In Ruby, how to implement "20 - point" and "point - 20" using coerce()? - ruby

In Ruby, the operation of
point - 20 # treating it as point - (20,20)
20 - point # treating it as (20,20) - point
are to be implemented.
But the following code:
class Point
attr_accessor :x, :y
def initialize(x,y)
#x, #y = x, y
end
def -(q)
if (q.is_a? Fixnum)
return Point.new(#x - q, #y - q)
end
Point.new(#x - q.x, #y - q.y)
end
def -#
Point.new(-#x, -#y)
end
def *(c)
Point.new(#x * c, #y * c)
end
def coerce(something)
[self, something]
end
end
p = Point.new(100,100)
q = Point.new(80,80)
p (-p)
p p - q
p q - p
p p * 3
p 5 * p
p p - 30
p 30 - p
Output:
#<Point:0x2424e54 #x=-100, #y=-100>
#<Point:0x2424dc8 #x=20, #y=20>
#<Point:0x2424d3c #x=-20, #y=-20>
#<Point:0x2424cc4 #x=300, #y=300>
#<Point:0x2424c38 #x=500, #y=500>
#<Point:0x2424bc0 #x=70, #y=70>
#<Point:0x2424b20 #x=70, #y=70> <--- 30 - p the same as p - 30
30 - p will actually be taken as p - 30 by the coerce function. Can it be made to work?
I am actually surprised that the - method won't coerce the argument this way:
class Fixnum
def -(something)
if (/* something is unknown class */)
a, b = something.coerce(self)
return -(a - b) # because we are doing a - b but we wanted b - a, so it is negated
end
end
end
that is, the function returns a negated version of a - b instead of just returning a - b.

Subtraction is not a commutative operation, so you can't just swap operands in your coerce and expect it to work. coerce(something) should return [something_equivalent, self]. So, in your case I think you should write your Point#coerce like this:
def coerce(something)
if something.is_a?(Fixnum)
[Point.new(something, something), self]
else
[self, something]
end
end
You'd need to slightly change other methods, but I'll leave that to you.

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

Setting method local variables from a proc

If I have a class with two instance variables #x and #y, I can change them from a proc using self.instance_exec:
class Location
attr_accessor :x, :y
def initialize
#x = 0
#y = 0
end
def set &block
self.instance_exec(&block)
end
end
location = Location.new
location.set do
#x = rand(100)
#y = rand(100)
end
puts location.x
puts location.y
If I have a class with a method set with two local variables x and y, I can use proc return values to set them:
class Location
def set &block
x = 0;
y = 0;
x, y = block.call()
# do something with x and y
puts x
puts y
end
end
location = Location.new
location.set do
x = rand(100)
y = rand(100)
[x, y]
end
Is there a way to access the set method local variables x and y from the proc without using return values?
You can do it, sort of, but it isn't pretty
There is a way for block to set a variable in a calling method, but it isn't pretty. You can pass in a binding, then eval some code using the binding:
def foo(binding)
binding.eval "x = 2"
end
x = 1
foo(binding)
p x # => 2
Blocks also carry with them the binding in which they were defined, so if a block is being passed, then:
def foo(&block)
block.binding.eval "x = 2"
end
x = 1
foo {}
p x # => 2
What's in the block doesn't matter, in this case. It's just being used as a carrier for the binding.
Other ways to achieve the same goal
Yield an object
A more pedestrian way for a block to interact with it's caller is to pass an object to the block:
class Point
attr_accessor :x
attr_accessor :y
end
class Location
def set
point = Point.new
yield point
p point.x # => 10
p point.y # => 20
end
end
location = Location.new
location.set do |point|
point.x = 10
point.y = 20
end
This is often preferred to fancier techniques: It's easy to understand both its implementation and its use.
instance_eval an object
If you want to (but you probably shouldn't want to), the block's caller can use instance_eval/instance_exec to call the block. This sets self to the object, for that block.
class Location
def set(&block)
point = Point.new
point.instance_eval(&block)
p point.x # => 10
p point.y # => 20
end
end
location = Location.new
location.set do
self.x = 10
self.y = 20
end
You see that the block had to use use self. when calling the writers, otherwise new, local variables would have been declared, which is not what is wanted here.
Yield or instance_eval an object
Even though you still probably shouldn't use instance_eval, sometimes it's useful. You don't always know when it's good, though, so let's let the method's caller decide which technique to use. All the method has to do is to check that the block has parameters:
class Location
def set(&block)
point = Point.new
if block.arity == 1
block.call point
else
point.instance_eval(&block)
end
p point.x
p point.y
end
end
Now the user can have the block executed in the scope of the point:
location = Location.new
location.set do
self.x = 10
self.y = 20
end
# => 10
# => 20
or it can have the point passed to it:
location.set do |point|
point.x = 30
point.y = 40
end
# => 30
# => 40

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

very simple ruby programing, getting into infinite loop

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)
When I run the program I get into infinite loop, I don't understand why.
Thank you.
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 [](i)
#array[i]
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
To answer the infinite loop issue, it looks like you forgot to add a i += 1 in the #initialize method of Matrix class.
However, you will encounter more errors further in the code since, for example, you're checking length of the Matrix object which is undefined, and iterating over the Matrix object in each2 defined inside of the Vector class which needs the object to be an Enumerable (Array/Hash etc). These will throw an error as the Matrix class is not an Enumerator. These are some good resources to help you learn how the powerful Enumerator module works.
Once you get familiar with the syntax and structure, be sure to use the Pry tool. It will be your best friend for debugging Ruby code.

more ruby way of doing project euler #2

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

Resources