M.Hiroi's Home Page

お気楽 Ruby プログラミング入門

付録

[ PrevPage | R u b y | NextPage ]

Enumerator

irb> class Foo
irb>   def each
irb>     yield 1
irb>     yield 2
irb>     yield 3
irb>   end
irb> end
=> :each
irb> a = Foo.new
=> #<Foo: ... >
irb> a.map {|x| x * x}
(irb):?:in `<main>': undefined method `map' for #<Foo:...> (NoMethodError)
・・・省略・・・

irb> e = a.to_enum
=> #<Enumerator: ...>
irb> e.map {|x| x * x}
=> [1, 4, 9]
irb> e.next
=> 1
irb> e.next
=> 2
irb> e.next
=> 3
irb> e.next
(irb):?:in `next': iteration reached an end (StopIteration)
・・・省略・・・

irb> e.rewind
=> #<Enumerator: ...>
irb> e.peek
=> 1
irb> e.peek
=> 1
irb> e.peek_values
=> [1]
irb> e.next_values
=> [1]
irb> e.next_values
=> [2]
irb> [1,2,3,4,5].to_enum.with_index{|k, i| print i, " ", k, "\n"}
0 1
1 2
2 3
3 4
4 5
=> [1, 2, 3, 4, 5]
irb> [1,2,3,4,5].to_enum.with_index(1){|k, i| print i, " ", k, "\n"} 
1 1
2 2
3 3
4 4
5 5
=> [1, 2, 3, 4, 5]
irb> [1,2,3,4,5].each_with_index{|k, i| print i, " ", k, "\n"}
0 1
1 2
2 3
3 4
4 5
=> [1, 2, 3, 4, 5]
irb> ints = Enumerator.new(Float::INFINITY) {|y|
irb>   n = 1
irb>   loop {
irb>     y << n
irb>     n += 1
irb>   }
irb> }
=> #<Enumerator: ...>
irb> ints.next
=> 1
irb> ints.next
=> 2
irb> ints.next
=> 3
irb> ints.next
=> 4
irb> ints.next
=> 5
irb> ints.rewind
=> #<Enumerator: ...>
irb> ints.next
=> 1
irb> ints.next
=> 2
irb> ints.next
=> 3
irb> ints.size
=> Infinity

●参考 URL


Enumerator::Lazy

irb> intslazy = ints.lazy
=> #<Enumerator::Lazy: ...>
irb> intslazy.next
=> 1
irb> intslazy.next
=> 2
irb> intslazy.next
=> 3
irb> ints.lazy.drop(100)
=> #<Enumerator::Lazy: ...>
irb> ints.lazy.drop(100).first
=> 101
irb> ints.lazy.drop(100).first(10)
=> [101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
irb> ints.lazy.map {|x| x * 2}
=> #<Enumerator::Lazy: ...>
irb> ints.lazy.map {|x| x * 2}.take(10).force
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
irb> ints.lazy.map {|x| x * 2}.first(10)
=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

●簡単な例題

リスト : 無限数列の生成

def iterate(a, &func)
  Enumerator.new(Float::INFINITY) {|y|
    n = a
    loop {
      y << n
      n = func.call(n)
    }
  }.lazy
end

def tabulate(a = 0, &func)
  Enumerator.new(Float::INFINITY) {|y|
    n = a
    loop {
      y << func.call(n)
      n += 1
    }
  }.lazy
end
irb> iterate(1, &:itself).first(10)
=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
irb> iterate(2, &:itself).first(10)
=> [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
irb> iterate(1){|x| x + 1}.first(10)
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb> iterate(1){|x| x + 2}.first(10)
=> [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
irb> iterate([0, 1]){|x, y| [y, y + x]}.first(10)
=> [[0, 1], [1, 1], [1, 2], [2, 3], [3, 5], [5, 8], [8, 13], [13, 21], [21, 34], [34, 55]]
irb> iterate([0, 1]){|x, y| [y, y + x]}.map{|x| x[0]}.first(10)    # フィボナッチ数
=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
irb> iterate([2, 1]){|x, y| [y, y + x]}.map{|x| x[0]}.first(10)    # リュカ数
=> [2, 1, 3, 4, 7, 11, 18, 29, 47, 76]
irb> iterate([0, 0, 1]){|x, y, z| [y, z, z + y + x]}.map{|x| x[0]}.first(20)  # トリボナッチ数
=> [0, 0, 1, 1, 2, 4, 7, 13, 24, 44, 81, 149, 274, 504, 927, 1705, 3136, 5768, 10609, 19513]

irb> tabulate(&:itself).first(10)
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
irb> tabulate(10, &:itself).first(10)
=> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
irb> tabulate(1){|x| x * (x + 1) / 2}.first(10)     # 三角数
=> [1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
irb> tabulate(1){|x| x * x}.first(10)               # 四角数
=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
irb> tabulate(1){|x| x * (3 * x - 1) / 2}.first(10) # 五角数
=> [1, 5, 12, 22, 35, 51, 70, 92, 117, 145]

irb> def to_fizzbuzz(n)
irb>   if n % 15 == 0
irb>     "FizzBuzz"
irb>   elsif n % 3 == 0
irb>     "Fizz"
irb>   elsif n % 5 == 0
irb>     "Buzz"
irb>   else
irb>     n.to_s
irb>   end
irb> end
=> :to_fizzbuzz
irb> tabulate(1){|x| to_fizzbuzz(x)}.first(100)
=> ["1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", 
"13", "14", "FizzBuzz", "16", "17", "Fizz", "19", "Buzz", "Fizz", "22", "23", "Fizz", 
"Buzz", "26", "Fizz", "28", "29", "FizzBuzz", "31", "32", "Fizz", "34", "Buzz", 
"Fizz", "37", "38", "Fizz", "Buzz", "41", "Fizz", "43", "44", "FizzBuzz", "46", "47", 
"Fizz", "49", "Buzz", "Fizz", "52", "53", "Fizz", "Buzz", "56", "Fizz", "58", "59", 
"FizzBuzz", "61", "62", "Fizz", "64", "Buzz", "Fizz", "67", "68", "Fizz", "Buzz", 
"71", "Fizz", "73", "74", "FizzBuzz", "76", "77", "Fizz", "79", "Buzz", "Fizz", "82", 
"83", "Fizz", "Buzz", "86", "Fizz", "88", "89", "FizzBuzz", "91", "92", "Fizz", "94", 
"Buzz", "Fizz", "97", "98", "Fizz", "Buzz"]

irb> def newton(n)
irb>   iterate(n) {|x| (x + n / x) / 2.0}
irb> end
=> :newton
irb> newton(2).first(10)
=> [2, 1.5, 1.4166666666666665, 1.4142156862745097, 1.4142135623746899, 
1.414213562373095, 1.414213562373095, 1.414213562373095, 1.414213562373095, 
1.414213562373095]
irb> newton(3).first(10)
=> [3, 2.0, 1.75, 1.7321428571428572, 1.7320508100147274, 1.7320508075688772, 
1.7320508075688772, 1.7320508075688772, 1.7320508075688772, 1.7320508075688772]
リスト : 素数列 (myprime.rb)

class Myprime
  @@primes = [2, 3, 5]    # 求めた素数を格納

  # 次の素数を求める
  def Myprime.next_prime(n)
    while true
      for p in @@primes
        return n if p * p > n
        break if n % p == 0
      end
      n += 2
    end
  end

  # 素数列の生成
  def Myprime.make
    Enumerator.new(Float::INFINITY) {|y|
      n = 0
      while true
        if n == @@primes.size
          @@primes.push Myprime.next_prime(@@primes[-1] + 2)
        end
        y << @@primes[n]
        n += 1
      end
    }.lazy
  end
end
irb> load "myprime.rb"
=> true
irb> ps = Myprime.make
=> #<Enumerator::Lazy: ...>
irb> ps.first(25)
=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 
79, 83, 89, 97]
irb> ps.first(100)
=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 
79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 
173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 
269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 
373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 
467, 479, 487, 491, 499, 503, 509, 521, 523, 541]
irb> ps.drop(1000).first(10)
=> [7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017]

●参考 URL


Fiber

irb(main)> co = Fiber.new {
irb(main)>   for x in 1 .. 4
irb(main)>     Fiber.yield x
irb(main)>   end
irb(main)>   5
irb(main)> }
=> #<Fiber:0x000055e61811b3f0 (irb):? (created)>
irb> co.resume
=> 1
irb> co.resume
=> 2
irb> co.resume
=> 3
irb> co.resume
=> 4
irb> co.resume
=> 5
irb> co.resume
(irb):?:in `resume': attempt to resume a terminated fiber (FiberError)
・・・省略・・・

●簡単な例題

リスト : 複数のコルーチン

def print_code(code)
  loop {
    print code
    Fiber.yield true
  }
end

def test_a(n)
  xs = ["h", "e", "y", "!", " "].map {|x| Fiber.new {print_code(x)}}
  n.times {
    xs.each {|co| co.resume}
  }
end
irb> test_a(5)
hey! hey! hey! hey! hey! => 5
irb> test_a(10)
hey! hey! hey! hey! hey! hey! hey! hey! hey! hey! => 10
リスト : 順列の生成

def perm_sub(xs, n)
  if xs.size == n
    Fiber.yield []
  else
    co = Fiber.new { perm_sub(xs, n + 1) }
    while ys = co.resume
      for x in xs
        if not ys.member? x
          Fiber.yield(ys + [x])
        end
      end
    end
  end
end

def permutation(xs)
  Fiber.new { perm_sub(xs, 0) }
end
irb> co = permutation([1,2,3])
=> #<Fiber:0x0000563306296ac8 sample_fiber.rb:? (created)>
irb> while xs = co.resume
irb>   print xs, "\n"
irb> end
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
=> nil
リスト : エラトステネスの篩

# n から始まる整数列
def integers(n)
  Fiber.new {
    loop {
      Fiber.yield n
      n += 1
    }
  }
end

# フィルター
def filter(src)
  Fiber.new {
    while m = src.resume
      Fiber.yield(m) if yield(m)
    end
  }
end

def sieve(x)
  nums = integers(2)
  x.times {
    n = nums.resume
    print n, " "
    nums = filter(nums) {|x| x % n != 0}
  }
end
irb> sieve 25
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 => 25
irb> sieve 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 
109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 
229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 
353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 
479 487 491 499 503 509 521 523 541 => 100

Rational

irb> Rational(1, 3)
=> (1/3)
irb> Rational("1/3")
=> (1/3)
irb> Rational(0.1)
=> (3602879701896397/36028797018963968)
irb> Rational("0.1")
=> (1/10)
irb> Rational(1e-3)
=> (1152921504606847/1152921504606846976)
irb> Rational("1e-3")
=> (1/1000)
irb> a = Rational(1, 2)
=> (1/2)
irb> b = Rational(1, 3)
=> (1/3)
irb> a + b
=> (5/6)
irb> a - b
=> (1/6)
irb> b - a
=> (-1/6)
irb> a * b
=> (1/6)
irb> a / b
=> (3/2)
irb> b / a
=> (2/3)
irb> a ** 2
=> (1/4)
irb> a ** 10
=> (1/1024)
irb> 2 ** a
=> 1.4142135623730951
irb> 8 ** b
=> 2.0
irb> a < b
=> false
irb> a > b
=> true
irb> a == b
=> false
irb> a != b
=> true
irb> a == a
=> true
irb> a <=> b
=> 1
irb> b <=> a
=> -1
irb> b <=> b
=> 0

Complex

irb> Complex(1, 2)
=> (1+2i)
irb> Complex.rect(3, 4)
=> (3+4i)
irb> Complex(1)
=> (1+0i)
irb> Complex("1+2i")
=> (1+2i)
irb> Complex("1.0+2.0i")
=> (1.0+2.0i)
irb> Complex::I
=> (0+1i)
irb> a = Complex(1.2, 3.4)
=> (1.2+3.4i)
irb> a.real
=> 1.2
irb> a.imag
=> 3.4
irb> a.conjugate
=> (1.2-3.4i)
irb> a.conj
=> (1.2-3.4i)
irb> b = Complex(1, 1)
=> (1+1i)
irb> b.abs
=> 1.4142135623730951
irb> b.arg
=> 0.7853981633974483
irb> Complex.polar(b.abs, b.arg)
=> (1.0000000000000002+1.0i)
irb> Complex(1.0, 0.0).arg
=> 0.0
irb> Complex(1.0, 1.0).arg
=> 0.7853981633974483
irb> Complex(0.0, 1.0).arg
=> 1.5707963267948966
irb> Complex(-1.0, 1.0).arg
=> 2.356194490192345
irb> Complex(-1.0, 0.0).arg
=> 3.141592653589793
irb> Complex(1.0, -1.0).arg
=> -0.7853981633974483
irb> Complex(0.0, -1.0).arg
=> -1.5707963267948966
irb> Complex(-1.0, -1.0).arg
=> -2.356194490192345
irb> Complex(-1.0, -0.0).arg
=> -3.141592653589793
irb> 1.0.arg
=> 0
irb> -1.0.arg
=> 3.141592653589793
irb> 0.0.arg
=> 0
irb> -0.0.arg
=> 3.141592653589793
irb> a = Complex(1.0, 2.0)
=> (1.0+2.0i)
irb> b = Complex(3.0, 4.0)
=> (3.0+4.0i)
irb> a + b
=> (4.0+6.0i)
irb> a - b
=> (-2.0-2.0i)
irb> a * b
=> (-5.0+10.0i)
irb> a / b
=> (0.44+0.08i)
irb> a ** 2
=> (-3.0+4.0i)
irb> a * a
=> (-3.0+4.0i)
irb> a ** 3
=> (-11.0-2.0i)
irb> a * a * a
=> (-11.0-2.0i)
irb> a == a
=> true
irb> a == b
=> false
irb> a != b
=> true
irb> Float::INFINITY
=> Infinity
irb> Float::NAN
=> NaN
irb> a = Complex(1e300, 1e300)
=> (1.0e+300+1.0e+300i)
irb> a.finite?
=> true
irb> a.infinite?
=> nil
irb> b = a * a
=> (NaN+Infinity*i)
irb> b.finite?
=> false
irb> b.infinite?
=> 1
irb> b.real.nan?
=> true
irb> b.real.nan?
=> true
irb> b.imag.infinite?
=> 1

整数のビット演算

irb> printf "%04b\n", 0b0101 & 0b0011
0001
=> nil
irb> printf "%04b\n", 0b0101 | 0b0011
0111
=> nil
irb> printf "%04b\n", 0b0101 ^ 0b0011
0110
=> nil
irb> ~1
=> -2
irb> ~0
=> -1
irb> 1 << 8
=> 256
irb> 1 << 16
=> 65536
irb> 256 >> 8
=> 1
irb> 65536 >> 8
=> 256
irb> -256 >> 8
=> -1
irb> for i in 0..5
irb>   print 0b010101[i], " "
irb> end
1 0 1 0 1 0 => 0..5
irb> printf "%b\n", 0b11001101[3, 1]
1
=> nil
irb> printf "%b\n", 0b11001101[3...7]
1001
=> nil
irb> printf "%b\n", 0b11001101[3..7]
11001
=> nil
irb> 0b11001101.allbits?(0b1101)
=> true
irb> 0b11001100.allbits?(0b1101)
=> false
irb> 0b11001101.anybits?(0b1100)
=> true
irb> 0b11000000.anybits?(0b1100)
=> false
irb> 0x100.bit_length
=> 9
irb> 0x800.bit_length
=> 12
irb> 0xffff.bit_length
=> 16
irb> 0.bit_length
=> 0

初版 2017 年 1 月 22 日
改訂 2023 年 1 月 28 日

Copyright (C) 2017-2023 Makoto Hiroi
All rights reserved.

[ PrevPage | R u b y | NextPage ]