Skip to content

Instantly share code, notes, and snippets.

@ir-norn
Last active November 28, 2015 20:28
Show Gist options
  • Save ir-norn/e0616bd6c20e255329d6 to your computer and use it in GitHub Desktop.
Save ir-norn/e0616bd6c20e255329d6 to your computer and use it in GitHub Desktop.
Enumerable#prev #chino_to_enum / count_lib_v2 / Fiber

info

  • Count_lib_v2  / prev peek
  • chino_to_enum  / prev

この三つは非常に低速 nextの数百倍~

この実装はpeekだけの速度を犠牲にした ( rewind の使用

基本はseekを使い、前回のnextの結果を得るほうを使う

prevをリアルタイムで使う場合は、Array_cycle、またはFocusを使う


count_lib_v2.rb

( obsolete Enumerableで全部書いた )

以前500行くらいのlambda無双で書いたコードをFiberにして小さくしたやつ


chino_to_enum

メニューSelect等で使う場合、最初に100回くらい先にnext廻しとけば

cc = 0.step(sstr.size-1,1).cycle.chino_to_enum
(100*sstr.size.-(0)).times { cc.next }

最初からcc.prev が動く

この程度をバグじゃなくて仕様扱いに出来るなら

chino_to_enum使うと楽

chino_to_enumはEnumerableすべてで seek prev を使えるようにしてるから

prevを現実的な速度で実装すれば利点はあるかも


Array_cycle

プラス・マイナスの添え字で配列にアクセスする事を前提のフォーカス Array_cycle

添え字以外のフォーカスには使えない


Focus

class Focus は、どの言語でも出来る普通の実装

chino_cocoa_to_enum.rb

Count_lib_v1,v2 の後継

class Array_cycle
attr_accessor :size
def initialize size
@size = size
rewind
end
def rewind
@aa = [*0..size.-(1)].cycle
@bb = [*-size..-1].reverse.cycle
end
def seek
@seek
end
def peek
@aa.peek + @bb.peek
end
def next
@seek = @aa.next
end
def prev
@bb.next
end
end
# require_relative "./Count_lib_v2"
# require_relative "./chino_to_enum"
# require_relative "./Array_cycle"
# require_relative "./Focus"
require "Benchmark"
Benchmark.bm do|x| N = 5000
enum = 0.step(10000,1)
p "-chino-"
ch = enum.chino_to_enum
x.report :next do N.times do ch.next end end
x.report :peek do N.times do ch.peek end end
x.report :prev do N.times do ch.prev end end
x.report :seek do N.times do ch.seek end end
p "-Count_lib_v2-"
ch = Count_lib_v2.new( start: 0 , limit: 10000 , add: 1 )
x.report :next do N.times do ch.next end end
x.report :peek do N.times do ch.peek end end
x.report :prev do N.times do ch.prev end end
x.report :seek do N.times do ch.seek end end
p "-Array_cycle-"
ch = Array_cycle.new 10000
x.report :next do N.times do ch.next end end
x.report :peek do N.times do ch.peek end end
x.report :prev do N.times do ch.prev end end
x.report :seek do N.times do ch.seek end end
p "-Focus-"
ch = Focus.new 0 , 10000
x.report :next do N.times do ch.next end end
x.report :peek do N.times do ch.peek end end
x.report :prev do N.times do ch.prev end end
x.report :seek do N.times do ch.seek end end
end
# user system total real
# "-chino-"
# next 0.000000 0.000000 0.000000 ( 0.006090)
# peek 0.015000 0.000000 0.015000 ( 0.000608)
# prev 15.094000 0.063000 15.157000 ( 15.407540)
# seek 0.000000 0.000000 0.000000 ( 0.000936)
# "-Count_lib_v2-"
# next 0.000000 0.000000 0.000000 ( 0.003162)
# peek 17.172000 0.156000 17.328000 ( 17.455832)
# prev 8.812000 0.094000 8.906000 ( 9.147972)
# seek 0.000000 0.000000 0.000000 ( 0.000700)
# "-Array_cycle-"
# next 0.000000 0.000000 0.000000 ( 0.003066)
# peek 0.016000 0.000000 0.016000 ( 0.001328)
# prev 0.000000 0.000000 0.000000 ( 0.003297)
# seek 0.000000 0.000000 0.000000 ( 0.001031)
# "-Focus-"
# next 0.000000 0.000000 0.000000 ( 0.001024)
# peek 0.000000 0.000000 0.000000 ( 0.000863)
# prev 0.000000 0.000000 0.000000 ( 0.001173)
# seek 0.000000 0.000000 0.000000 ( 0.000654)
module Enumerable
def chino_to_enum
enum = Enumerator.new do |y|
each_with_index do |m,i|
y.yield enum._state = m
enum._prev_count = i
end
end
enum.extend Module.new{ attr_accessor :_prev_count , :_state }
enum._prev_count = 0
enum
end
def seek
_state
end
def prev
rewind
_prev_count.times do self.next end
peek
end
def cycle_rev
(self.to_a + self.to_a.reverse[1...-1]).cycle
end
def cocoa_to_enum
enum = chino_to_enum
def enum.next ; super
rescue StopIteration
_state
end
return enum
end
end
# p x = 0.step(2,1).cycle_rev
# p x = 0.step(2,1)
N = 5
ch = 0.step(N,1).chino_to_enum
p "-chino_to_enum-"
print"next:"; N.times { print ch.next , " " } ; puts
print"prev:"; N.times { print ch.prev , " " } ; puts
ch.rewind
print"next:"; N.-(1).times { print ch.next , " " } ; puts
print"peek:"; N.times { print ch.peek , " " } ; puts
NN = 12
ch = 0.step(N,1).cocoa_to_enum
p "-cocoa_to_enum-"
print"next:"; NN.times { print ch.next , " " } ; puts
print"prev:"; NN.times { print ch.prev , " " } ; puts
ch.rewind
print"next:"; N.-(1).times { print ch.next , " " } ; puts
print"peek:"; NN.times { print ch.peek , " " } ; puts
ch = 0.step(4,1).cycle_rev.chino_to_enum
p "-cycle_rev-"
print"next:"; NN.times { print ch.next , " " } ; puts
print"prev:"; NN.times { print ch.prev , " " } ; puts
ch.rewind
print"next:"; NN.times { print ch.next , " " } ; puts
print"peek:"; NN.times { print ch.peek , " " } ; puts
# "-chino_to_enum-"
# next:0 1 2 3 4
# prev:3 2 1 0 0
# next:0 1 2 3
# peek:4 4 4 4 4
# "-cocoa_to_enum-"
# next:0 1 2 3 4 5 5 5 5 5 5 5
# prev:5 4 3 2 1 0 0 0 0 0 0 0
# next:0 1 2 3
# peek:4 4 4 4 4 4 4 4 4 4 4 4
# "-cycle_rev-"
# next:0 1 2 3 4 3 2 1 0 1 2 3
# prev:2 1 0 1 2 3 4 3 2 1 0 0
# next:0 1 2 3 4 3 2 1 0 1 2 3
# peek:4 4 4 4 4 4 4 4 4 4 4 4
module Count_lib_v2_m
attr_reader :enum , :count , :start , :limit , :add
def initialize start: , limit: , add:
@start = start ; @limit = limit ; @add = add
@enum = @start.step(@limit,@add)
@argv = [@start , @limit , @add]
rewind
end
def fiber_yield # ovar lide
@fib = Fiber.new do
fiber_yield_sub
Fiber.yield limit while true
end # f
end
def fiber_yield_sub
enum.each_with_index do | m , i |
@count = i
Fiber.yield m
end
end
def rewind
@count = 0
@seek = 0
fiber_yield
end # df
def peek
ret = @fib.resume
count_tmp = @count
rewind
count_tmp.times do self.next end
ret
end
def seek ; @seek ; end
def next
@seek = @fib.resume
end
def prev
count_tmp = @count
rewind
count_tmp.times do self.next end
@seek
end
def take n
n.times.map do self.next end
end
end
class Count_lib_v2
include Count_lib_v2_m
end
class Count_lib_v2_rev
include Count_lib_v2_m
undef_method :prev # muzui mi ji ssou
def fiber_yield
@fib = Fiber.new do | x |
fiber_yield_sub
limit.-(1).step(start+1,-add).each.with_index @count do | m , i |
@count = i
Fiber.yield m
end
rewind
@fib.resume
end # f
end # d
end
class Count_lib_v2_cycle
include Count_lib_v2_m
undef_method :prev # muzui mi ji ssou
def fiber_yield
@fib = Fiber.new do | x |
fiber_yield_sub
rewind
@fib.resume
end # f
end # d
end
ch = Count_lib_v2.new( start: 0 , limit: 3 , add: 1 )
p "-Count_lib_v2-"
print"next:"; 5.times { print ch.next , " " } ; puts
print"prev:"; 5.times { print ch.prev , " " } ; puts
ch.rewind
print"next:"; 5.times { print ch.next , " " } ; puts
print"peek:"; 5.times { print ch.peek , " " } ; puts
ch = Count_lib_v2_rev.new( start: 0 , limit: 3 , add: 1 )
p "-Count_lib_v2_rev-"
12.times { print ch.next , " " } ; puts
#12.times { print ch.prev , " " } ; puts
ch.rewind
12.times { print ch.next , " " } ; puts
ch = Count_lib_v2_cycle.new( start: 0 , limit: 3 , add: 1 )
p "-Count_lib_v2_cycle-"
12.times { print ch.next , " " } ; puts
#12.times { print ch.prev , " " } ; puts
ch.rewind
12.times { print ch.next , " " } ; puts
p "-Count_lib_v2_cycle loop_wait -"
ch.rewind
12.times { |i|
if (3..5).include? i
print ch.peek , " " ; next
end
print ch.next , " "
} ; puts
p ch.take(15)
# "-Count_lib_v2-"
# next:0 1 2 3 3
# prev:2 1 0 0 0
# next:0 1 2 3 3
# peek:3 3 3 3 3
# "-Count_lib_v2_rev-"
# 0 1 2 3 2 1 0 1 2 3 2 1
# 0 1 2 3 2 1 0 1 2 3 2 1
# "-Count_lib_v2_cycle-"
# 0 1 2 3 0 1 2 3 0 1 2 3
# 0 1 2 3 0 1 2 3 0 1 2 3
# "-Count_lib_v2_cycle loop_wait -"
# 0 1 2 3 3 3 3 0 1 2 3 0
# [1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
module Enumerable
def chino_to_enum
fib = Enumerator.new do |y|
each_with_index do |m,i|
y.yield fib._state = m
fib._prev_count = i
end
end
fib.extend Module.new{ attr_accessor :_prev_count , :_state }
_prev_count ||= 0
fib
end
def seek
_state
end
def prev
rewind
_prev_count.times do self.next end
peek
end
end
class Focus
attr_reader :focus , :size
def initialize focus , size
@focus = focus
@size = size
end
def seek
focus
end
def peek
(focus+1) % size
end
def next
@focus = (focus+1) % size
end
def prev
@focus = (focus-1) % size
end
end
class Focus_Array
attr_reader :focus , :ar
def initialize ar
@ar= ar
@focus = 0
end
def size
ar.size
end
def peek_num
focus
end
def seek
ar[ focus ]
end
def peek
ar[ (focus+1) % ar.size ]
end
def next
ar[ @focus = (focus+1) % ar.size ]
end
def prev
ar[ @focus = (focus-1) % ar.size ]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment