Advertisement
Guest User

Untitled

a guest
Jun 28th, 2017
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 4.09 KB | None | 0 0
  1. require "fiber"
  2.  
  3. class LazyArray
  4.         attr_accessor :fs
  5.         protected :fs
  6.  
  7.         @@ENDMARK = Object.new
  8.  
  9.         def LazyArray.[](*args)
  10.                 args.inject(LazyArray.new){|a, b| a.push b }
  11.         end
  12.  
  13.         def initialize(n = 0)
  14.                 @a = []
  15.                 @fs = []
  16.                 n.times{|i| self.concat yield i }
  17.         end
  18.  
  19.         def [](idx)
  20.                 case idx
  21.                 when Range
  22.                         xs = LazyArray.new
  23.                         xs.fs.push(Fiber.new do
  24.                                 i = idx.first
  25.                                 if idx.last >= 0
  26.                                         l = idx.last
  27.                                         d = 0
  28.                                 else
  29.                                         l = 1 / 0.0
  30.                                         d = -idx.last
  31.                                 end
  32.                                 while i <= l && (self.inbound? i + d)
  33.                                         Fiber.yield self[i]
  34.                                         i += 1
  35.                                 end
  36.                                 @@ENDMARK
  37.                         end)
  38.                         xs
  39.                 when Integer
  40.                         until @a.size > idx || @fs.empty?
  41.                                 self.progress
  42.                         end
  43.                         @a[idx]
  44.                 end
  45.         end
  46.  
  47.         def progress
  48.                 o = @fs.first.resume
  49.                 if o == @@ENDMARK
  50.                         @fs.shift
  51.                 else
  52.                         @a.push o
  53.                 end
  54.         end
  55.  
  56.         def concat(o)
  57.                 o
  58.                 case o
  59.                 when LazyArray
  60.                         @fs.push(Fiber.new do
  61.                                 o.each{|i| Fiber.yield i }
  62.                                 @@ENDMARK
  63.                         end)
  64.                 when Enumerable
  65.                         @fs.push(Fiber.new do
  66.                                 o.each{|i| Fiber.yield i }
  67.                                 @@ENDMARK
  68.                         end)
  69.                 else
  70.                         raise TypeError.new
  71.                 end
  72.                 self
  73.         end
  74.  
  75.         def +(o)
  76.                 self.clone.concat(o)
  77.         end
  78.  
  79.         def push(o)
  80.                 @fs.push(Fiber.new do
  81.                         Fiber.yield o
  82.                         @@ENDMARK
  83.                 end)
  84.                 self
  85.         end
  86.  
  87.         def inbound?(idx)
  88.                 self[idx]
  89.                 if @fs.empty?
  90.                         idx < @a.size
  91.                 else
  92.                         true
  93.                 end
  94.         end
  95.  
  96.         def size
  97.                 self.progress until @fs.empty?
  98.                 @a.size
  99.         end
  100.  
  101.         def zip(other)
  102.                 xs = LazyArray.new
  103.                 xs.fs.push(Fiber.new do
  104.                         i = 0
  105.                         self.each do |a|
  106.                                 Fiber.yield [a, other[i]]
  107.                                 i += 1
  108.                         end
  109.                         @@ENDMARK
  110.                 end)
  111.                 xs
  112.         end
  113.  
  114.         def map
  115.                 xs = LazyArray.new
  116.                 xs.fs.push(Fiber.new do
  117.                         self.each{|i| Fiber.yield yield i }
  118.                         @@ENDMARK
  119.                 end)
  120.                 xs
  121.         end
  122.  
  123.         def select
  124.                 xs = LazyArray.new
  125.                 xs.fs.push(Fiber.new do
  126.                         self.each{|i| Fiber.yield i if yield i }
  127.                         @@ENDMARK
  128.                 end)
  129.                 xs
  130.         end
  131.  
  132.         def each
  133.                 i = 0
  134.                 while self.inbound? i
  135.                         yield self[i]
  136.                         i += 1
  137.                 end
  138.         end
  139.  
  140.         def to_a
  141.                 i = @a.size
  142.                 while self.inbound? i
  143.                         i += 1
  144.                 end
  145.                 @a.clone
  146.         end
  147. end
  148.  
  149. fib = LazyArray.new.tap{|fib| fib + [0, 1] + fib.zip(fib[1..(1/0.0)]).map{|a, b| a + b } }
  150. p fib.select{|i| i % 7 == 0 }[0..4].to_a #=> [0, 21, 987, 46368, 2178309]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement