Playing round with fibers and I know I'm doing something stupid here. But trying to create a simple enumerable type thing based on fibers (it's obviously trivial using Enumerable). When I run the following I get a dead fiber error after it prints out the first couple of iterations. Does anyone know why?
class SumPow
def initialize(a)
sum = a
pow = a
#fiber = Fiber.new do
Fiber.yield sum
pow = pow * a
sum = sum + pow
end
end
def next
#fiber.resume
end
def each
loop do
yield self.next
end
end
end
sp = SumPow.new(3)
sp.each do |sum|
puts sum
end
output:
3
12
tmp/fiber_enum.rb:96:in `resume': dead fiber called (FiberError)
from tmp/fiber_enum.rb:96:in `next'
from tmp/fiber_enum.rb:101:in `block in each'
from tmp/fiber_enum.rb:100:in `loop'
from tmp/fiber_enum.rb:100:in `each'
from tmp/fiber_enum.rb:108:in `<main>'
This code on the other hand works completely fine:
fib = Fiber.new do
x, y = 0, 1
loop do
Fiber.yield y
x, y = y, x + y
end
end
7.times { puts fib.resume }
output:
1
1
2
3
5
8
13
The code is calling resume regardless of state of the fiber.
Check whether fiber can resume by calling Fiber#alive?
def each
while #fiber.alive? do
yield self.next
end
end
NOTE You need to do require 'fiber' to use alive? method.
UPDATE accoridng to the question edit.
The original code yields only once. To iterate indefinitely, you need loop.
def initialize(a)
sum = a
pow = a
#fiber = Fiber.new do
loop do # <-------------
Fiber.yield sum
pow = pow * a
sum = sum + pow
end # <-----------------
end
end
Related
I'm working on project Euler #35. I am getting the wrong number returned and I can't find where I have done wrong!
def is_prime?(num)
(2..Math.sqrt(num)).each { |i| return false if num % i == 0}
true
end
def is_circular?(num)
len = num.to_s.length
return true if len == 1
(len - 1).times do
new_n = cycle(num)
break unless is_prime?(new_n)
end
end
def cycle(num)
ary = num.to_s.split("")
return ary.rotate!.join.to_i
end
def how_many
circulars = []
(2..1000000).each do |num|
if is_prime?(num) && is_circular?(num)
circulars << num
end
end
p circulars.count
end
how_many #=> 14426
The returned number is '14426'. I am only returning the circular primes, supposedly the correct answer is '55'
I have edited your code with few fixes in Ruby way. Your mistake was including corect set of [a, b, c] three times to count, instead of counting them as a one circular prime number. Your answer was correct, while 55 is the number of unique sets.
require 'prime'
class Euler35
def is_circular?(num)
circulars_for(num).all?{ |el| ::Prime.instance.prime?(el) }
end
def circulars_for(a)
a.to_s.split("").length.times.map{|el| a.to_s.split("").rotate(el).join.to_i }
end
def how_many
circulars = []
::Prime.each(1_000_000) do |num|
continue if circulars.include?(num)
if is_circular?(num)
circulars << circulars_for(num)
end
end
circulars.count
end
end
puts Euler35.new.how_many # => 55
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.
Alright, so I asked an earlier question on my syntax error. I got rid of the errors, but the program doesn't do what it was intended to do. My math is wrong and doesn't find the number of trailing zeros. Here is my code:
num = " "
a = 0
sumOfFact = 1
def factorial
num = gets.to_i
a = num
(1..num).each do |a|
if a != 1
sumOfFact *= a
a -= 1
else
break
end
end
end
for c in 1..sumOfFact
if sumOfFact / c == 10
zeros += 1
end
end
factorial()
puts sumOfFact
puts zeros
Well, first, you should do the gets outside your method. Your method should accept a param. Second, why do you need the condition?
You want the multiplication from 1 to n to get the factorial. You should get started with this:
def factorial(n)
total = 1
(1..n).each do |n|
total *= n
end
total
end
puts factorial(gets.to_i)
Next is factorial with inject in case you want to learn new syntax :-)
def factorial(n)
n == 0? 1 : (1..n).inject(1) { |total, i| total*= i; total }
end
puts factorial(gets.to_i)
As #pjs commented below, here's a beautiful way of doing factorial!
def factorial(n)
n == 0? 1 : (1..n).inject(:*)
end
And, a final enhancement:
def factorial(n)
(1..n).inject(1, :*)
end
Supposing that n is a non-negative integer number, you can define a method to calculate the factorial:
def factorial(n)
tot = 1
(1..n).each do |n|
tot *= x
end
tot
end
Examples of its usage:
puts factorial(0) # 1
puts factorial(1) # 1
puts factorial(2) # 2
puts factorial(3) # 6
puts factorial(4) # 24
puts factorial(5) # 120
If you wan't to read the user input, call it like this:
puts 'Type the non-negative integer:'
n = gets.to_i
puts factorial(n)
class Factorial
attr_reader :num
def initialize(num)
#num = num
end
def find_factorial
(1..num).inject(:*) || 1
end
end
number = Factorial.new(8).find_factorial
puts number
Or you could just simply write:
(1..num).inject(:*) || 1
Try this too. Hope this helps anyone having the same problem in some way.
Method for finding the factorial of any number:
def factorial(number)
for i in 1...number do
number *= i
end
number
end
puts factorial(5)
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
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