M.Hiroi's Home Page
http://www.geocities.jp/m_hiroi/

Ruby Programming

Ruby Junk Scripts

[ PrevPage | R u b y | NextPage ]

階乗

階乗を求めるプログラムです。

階乗の定義

0! = 1
n! = n * (n - 1)!

●プログラム

#
# fact.rb : 階乗の計算
#

# 再帰
def fact(n)
  return 1 if n == 0
  n * fact( n - 1 )
end

# 末尾再帰
def facti(n, a = 1)
  return a if n == 0
  facti(n - 1, a * n)
end

# 繰り返し
def fact_(n)
  m = 1
  for x in 2 .. n
    m *= x
  end
  m
end

# テスト
if __FILE__ == $0
  for x in 1 ... 20
    printf("%2d: %d\n", x, fact(x))
  end
end

●実行例

 1: 1
 2: 2
 3: 6
 4: 24
 5: 120
 6: 720
 7: 5040
 8: 40320
 9: 362880
10: 3628800
11: 39916800
12: 479001600
13: 6227020800
14: 87178291200
15: 1307674368000
16: 20922789888000
17: 355687428096000
18: 6402373705728000
19: 121645100408832000

累乗

x y (y は整数) を求めるプログラムです。

●プログラム

#
# power.rb : 累乗
#
def power(x, y)
  return 1 if y == 0
  a = power(x, y / 2)
  if y & 1 == 1
    a * a * x
  else
    a * a
  end
end

# テスト
if __FILE__ == $0
  20.times do |x|
    printf("%d, %d\n", x, power(2, x))
  end
end

●実行例

0, 1
1, 2
2, 4
3, 8
4, 16
5, 32
6, 64
7, 128
8, 256
9, 512
10, 1024
11, 2048
12, 4096
13, 8192
14, 16384
15, 32768
16, 65536
17, 131072
18, 262144
19, 524288

フィボナッチ関数

フィボナッチ関数のプログラムです。

フィボナッチ関数の定義

            ┌ 1                      n = 0
fibo(n) = ─┤ 1                      n = 1
            └ fibo(n-1) + fibo(n-2)  n > 1

1, 1, 2, 3, 5, 8, 13 .... という直前の 2 項を足していく数列

●プログラム

#
# fibo.rb : フィボナッチ関数
#

# 二重再帰
def fibo(n)
  return 1 if n == 0 || n == 1
  fibo(n - 1) + fibo(n - 2)
end

# 末尾再帰
def fiboi(n, a = 1, b = 0)
  return a if n == 0
  fiboi(n - 1, a + b, a)
end

# 繰り返し
def fibo_(n)
  a = 1
  b = 0
  n.times do
    c = a + b
    b = a
    a = c
  end
  a
end

# テスト
if __FILE__ == $0
  for x in 0 ... 20
    printf("%2d: %d\n", fibo(x))
  end
end

●実行例

 0: 1
 1: 1
 2: 2
 3: 3
 4: 5
 5: 8
 6: 13
 7: 21
 8: 34
 9: 55
10: 89
11: 144
12: 233
13: 377
14: 610
15: 987
16: 1597
17: 2584
18: 4181
19: 6765

最大公約数と最小公倍数

負でない整数 a と b の最大公約数を「ユークリッド (Euclid) の互除法」で求めます。

[ユークリッドの互除法]

負でない整数 a と b (a > b) で、a を b で割った余りを r とする。このとき、a と b の最大公約数は b と r の最大公約数に等しい。

a と b の最小公倍数は a * b / gcd(a, b) で求めることができます。

●プログラム

# 最大公約数
def gcd(a, b)
  return a if b == 0
  gcd(b, a % b)
end

# 繰り返し版
def gcd_(a, b)
  while b > 0
    c = a % b
    a = b
    b = c
  end
  a
end

# 最小公倍数
def lcm(a, b)
  a * b / gcd(a, b)
end

Ruby の場合、gcd() と lcm() はクラス rational に定義されています。

●実行例

gcd(42, 30) => 6
lcm(14, 35) => 70

素数

素数を求めるプログラムです。

●参考文献

●プログラム1

#
# prime.rb : 素数を求める(単純版)
#

# 素数の判定
def prime?(n, primes)
  for x in primes
    break if x * x > n
    return false if n % x == 0
  end
  true
end

# 素数を求める
def prime(n)
  primes = [2]
  x = 3
  while x <= n
    primes << x if prime?(x, primes)
    x += 2
  end
  primes
end

# テスト
if __FILE__ == $0
  p prime(100)
end

●実行例

[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]

●プログラム2

#
# sieve.rb : エラトステネスのふるい
#

# 2 * n + 3 までの奇数を調べる
def sieve(n)
  flag = Array.new(n + 1, true)
  printf("%8d", 2)
  count = 1
  for x in 0 .. n
    if flag[x]
      p = 2 * x + 3
      printf("%8d", p)    # 素数
      y = x + p
      while y <= n
        flag[y] = false   # p の倍数を削除
        y += p
      end
      count += 1
    end
  end
  printf("\n%d\n", count)
end

# テスト
if __FILE__ == $0
  sieve(50)
end

●実行例

       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
27

順列

1 から n までの整数値から m 個を取り出す順列をすべて求めるプログラムです。

●プログラム

#
# perm.rb : 順列の生成
#

# 表示
def print_perm(a)
  a.each do |x| print x, " " end
  print "\n"
end

# 単純な再帰
def perm(n, m, a = [])
  if a.size == m
    print_perm(a)
  else
    for x in 1 .. n
      unless a.member?(x)
        a << x
        perm(n, m, a)
        a.pop
      end
    end
  end
end

# 手続きオブジェクトを渡す
def perm1(n, m, f, a = [])
  if a.size == m
    f.call(a)
  else
    for x in 1 .. n
      unless a.member?(x)
        a << x
        perm1(n, m, f, a)
        a.pop
      end
    end
  end
end

# ブロックを渡す方法 (1)
def perm2(n, m, a = [], &block)
  if a.size == m
    yield a
  else
    for x in 1 .. n
      unless a.member?(x)
        a << x
        perm2(n, m, a, &block)
        a.pop
      end
    end
  end
end

# ブロックを渡す方法 (2)
def perm3(n, m)
  if m == 0
    yield []
  else
    perm3(n, m - 1) do |a|
      for x in 1 .. n
        yield a + [x] unless a.member?(x)
      end
    end
  end
end

# テスト
if __FILE__ == $0
  # perm(4, 3)
  # perm1(4, 3, Proc.new {|a| print_perm(a)})
  # perm2(4, 3) do |a| print_perm(a) end
  perm3(4, 3) do |a| print_perm(a) end
end

●実行例

1 2 3 
1 2 4 
1 3 2 
1 3 4 
1 4 2 
1 4 3 
2 1 3 
2 1 4 
2 3 1 
2 3 4 
2 4 1 
2 4 3 
3 1 2 
3 1 4 
3 2 1 
3 2 4 
3 4 1 
3 4 2 
4 1 2 
4 1 3 
4 2 1 
4 2 3 
4 3 1 
4 3 2 

組み合わせ

組み合わせの数を求めるプログラムと、1 から n までの整数値から m 個を選ぶ組み合わせをすべて求めるプログラムです。

●プログラム

#
# comb.rb : 組み合わせ
#

# 組み合わせの数
def comb(n, r)
  return 1 if n == r || r == 0
  comb(n, r - 1) * (n - r + 1) / r
end

# パスカルの三角形
def pascal(n)
  for i in 0 .. n
    for j in 0 .. i
      print comb(i, j), " "
    end
    print "\n"
  end
end

# 組み合わせの表示
def print_comb(a)
  a.each do |x| print x, " " end
  print "\n"
end

# 単純な再帰
def comb1(n, m, a = [])
  if m == 0 || n == m
    b = ((1 .. m).to_a).reverse!
    print_comb(a + b)
  else
    comb1(n - 1, m, a)
    a << n
    comb1(n - 1, m - 1, a)
    a.pop
  end
end

# 組み合わせをビットで表す
def comb2(n, m, a = 0)
  if m == 0 || m == n
    printf("%b\n", a | ((1 << m) - 1))
  else
    comb2(n - 1, m, a)
    comb2(n - 1, m - 1, a | (1 << (n - 1)))
  end
end

# ブロックを渡す方法
def comb3(n, m)
  if m == 0
    yield []
  elsif n == m
    yield((1 .. m).to_a)
  else
    comb3(n - 1, m) do |a|
      yield a
    end
    comb3(n - 1, m - 1) do |a|
      yield a + [n]
    end
  end
end

# テスト
if __FILE__ == $0
  pascal(10)
  comb2(5, 3)
  comb3(5, 3) do |a| print_comb(a) end
end

●実行例

1 
1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
1 5 10 10 5 1 
1 6 15 20 15 6 1 
1 7 21 35 35 21 7 1 
1 8 28 56 70 56 28 8 1 
1 9 36 84 126 126 84 36 9 1 
1 10 45 120 210 252 210 120 45 10 1 
111
1011
1101
1110
10011
10101
10110
11001
11010
11100
1 2 3 
1 2 4 
1 3 4 
2 3 4 
1 2 5 
1 3 5 
2 3 5 
1 4 5 
2 4 5 
3 4 5 

ハノイの塔

ハノイの塔は、棒に刺さっている大きさが異なる複数の円盤を、次の規則に従ってほかの棒に移動させるパズルです。

  1. 一回に一枚の円盤しか移動できない。
  2. 小さな円盤の上に大きな円盤を置くことはできない。
  3. 最初すべての円盤は一本の棒に刺さっていて、各円盤はそれより大きな円盤の上に置かれている。

ハノイの塔は、再帰を使えば簡単に解ける問題です。

●プログラム

#
# hanoi.rb : ハノイの塔
#

def hanoi(n, from, to, via)
  hanoi(n - 1, from, via, to) if n > 1
  printf("disk %d : %c -> %c\n", n, from, to)
  hanoi(n - 1, via, to, from) if n > 1
end

hanoi(3, ?a, ?b, ?c)

●実行結果

disk 1 : a -> b
disk 2 : a -> c
disk 1 : b -> c
disk 3 : a -> b
disk 1 : c -> a
disk 2 : c -> b
disk 1 : a -> b

マスターマインド

マスターマインド (master mind) は異なる 4 つの数字を当てるゲームです。コンピュータは 0 から 9 までの中から重複しないように数字を 4 つ選びます。私たちは数字だけではなく、その位置も当てなくてはいけません。数字は合っているが位置が間違っている個数を cows で表し、数字も位置も合っている個数を bulls で表します。つまり、bulls が 4 になると正解というわけです。ゲームの進行状況を下図に示します。

   6 2 8 1
------------------------------
1. 0 1 2 3 : bulls 0 : cows 2
2. 1 0 4 5 : bulls 0 : cows 1 
3. 2 3 5 6 : bulls 0 : cows 2 
4. 3 2 7 4 : bulls 1 : cows 0 
5. 3 6 0 8 : bulls 0 : cows 2 
6. 6 2 8 1 : bulls 4 : cows 0  ***** 正解 *****

    図 : マスターマインドの動作例

コンピュータが決めた数字は 6 2 8 1 です。プレーヤーは、最初に 0 1 2 3 を入力しました。0 と 3 は 6 2 8 1 に含まれていません。1 と 2 は 6 2 8 1 の中にあるのですが、位置が異なっているので、cows が 2 となります。この場合の bulls は 0 です。あとは bulls が 4 になるように数字を選んで入力していきます。4 番目の入力では、2 の位置が合っているので bulls は 1 となります。この例では 6 回で正解となりました。

●プログラム1

#
# mastermind.rb : マスターマインド
#
#                 Copyright (C) 2006 Makoto Hiroi
#

# 定数の定義
N = 4

# 問題の生成
def make_code
  a = []
  while a.size < N
    n = rand(10)
    a << n unless a.member?(n)
  end
  a
end

# bulls を数える
def count_bulls(a, b)
  bulls = 0
  for x in 0 ... N
    bulls += 1 if a[x] == b[x]
  end
  bulls
end

# 同じ数字を数える
def count_same_number(a, b)
  same = 0
  a.each do |x|
    same += 1 if b.member?(x)
  end
  same
end

# 入力データのチェック
def check_code(a)
  if a.size != N
    print "数字を 4 つ入力してください\n"
    false
  else
    flag = Array.new(10, false)
    a.each do |x|
      if x < 0 || x > 9
        print "0 - 9 の数字を入力してください\n"
        return false
      elsif flag[x]
        print "異なる数字を入力してください\n"
        return false
      end
      flag[x] = true
    end
    true
  end
end

# データの入力
def input_code
  loop do
    print "> "
    a = gets.split.map do |x|
      x.to_i
    end
    return a if check_code(a)
  end
end

# ゲーム
def mastermind(n)
  printf("***** Master Mind *****\n")
  printf("%d 回で当ててください\n", n)
  a = make_code
  n.times do |i|
    b = input_code
    bulls = count_bulls(a, b)
    cows = count_same_number(a, b) - bulls
    if bulls == N
      printf("おめでとう! %d 回で当てました", i + 1)
      return
    end
    printf("%2d: bulls = %d, cows = %d\n", i + 1, bulls, cows)
  end
  printf("残念、正解は %s でした\n", a.to_s)
end

# 実行
mastermind(10)

●プログラム2

マスターマインドを解くプログラムです。

#
# mastermind1.rb : mastermind の解法
#
#                  Copyright (C) 2006 Makoto Hiroi
#

# 定数の定義
N = 4

# 質問したコードと結果を格納する
class Query
  def initialize(bulls, cows, code)
    @bulls = bulls
    @cows = cows
    @code = code
  end
  
  def check(a)
    b = count_bulls(a, @code)
    c = count_same_number(a, @code) - b
    b == @bulls && c == @cows
  end
end

# 問題の生成
def make_code
  a = []
  while a.size < N
    n = rand(10)
    a << n unless a.member?(n)
  end
  a
end

# bulls を数える
def count_bulls(a, b)
  bulls = 0
  for x in 0 ... N
    bulls += 1 if a[x] == b[x]
  end
  bulls
end

# 同じ数字を数える
def count_same_number(a, b)
  same = 0
  a.each do |x|
    same += 1 if b.member?(x)
  end
  same
end

# 今まで質問したコードと矛盾しないか
def check_query(query, a)
  query.each do |q|
    return false unless q.check(a)
  end
  true
end

# 順列の生成
def perm(n, m)
  if m == 0
    yield []
  else
    perm(n, m - 1) do |a|
      for x in 0 ... n
        yield a + [x] unless a.member?(x)
      end
    end
  end
end

# マスターマインドの解法
def solve
  query = []
  collect = make_code

  perm(10, 4) do |code|
    if check_query(query, code)
      bulls = count_bulls(code, collect)
      cows = count_same_number(code, collect) - bulls
      printf("%d: %s, bulls %d, cows %d\n",
             query.size + 1, code.to_s, bulls, cows)
      if bulls == N
        print "Good Job!\n"
        return
      end
      query << Query.new(bulls, cows, code)
    end
  end
end

# 実行
solve

●実行例

1: 0123, bulls 1, cows 0
2: 0456, bulls 0, cows 1
3: 4178, bulls 1, cows 1
4: 4729, bulls 0, cows 1
5: 5873, bulls 0, cows 2
6: 8195, bulls 2, cows 2
7: 9185, bulls 4, cows 0
Good Job!

連結リスト

連結リスト (Linked List) はデータを一方向につなげたデータ構造です。リストを操作するプログラミング言語では Lisp が有名ですが、Lisp で扱うリストが連結リストです。下図に連結リストの構造を示します。

(1)変数
  ┌─┐    ┌─┬─┐  ┌─┬─┐  ┌─┬─┐  
  │・┼─→│10│・┼→│20│・┼→│30│/│ /:終端(nil)  
  └─┘    └─┴─┘  └─┴─┘  └─┴─┘  

(2)ヘッダセル
  ┌─┬─┐    ┌─┬─┐  ┌─┬─┐  ┌─┬─┐  
  │  │・┼─→│10│・┼→│20│・┼→│30│/│ /:終端(nil)  
  └─┴─┘    └─┴─┘  └─┴─┘  └─┴─┘  

                  図 : 連結リストの構造

連結リストはセル (cell) というデータを繋げて作ります。セルにはデータを格納する場所と、次のセルを指し示す場所から構成されます。図でいうと、箱がひとつのセルを表していて、左側にデータを格納し、右側に次のセルへの参照を格納します。リストの終わりを示すため、最後のセルの右側には特別な値(たとえば nil)を格納します。そして、図 (1) のように先頭セルへの参照を変数に格納しておけば、この変数を使って連結リストにアクセスすることができます。また、図 (2) のようにヘッダセルを用意する方法もあります。

●プログラム

#
# list.rb : 連結リスト
#
#           Copyright (C) 2006 Makoto Hiroi
#

# セルの定義
class Cell
  attr_accessor :data, :link
  def initialize(data, link = nil)
    @data = data
    @link = link
  end
end

# 連結リスト
class List
  include Enumerable
  
  def initialize
    @root = Cell.new(nil)   # Header Cell をセット
  end
  
  # n 番目にデータを挿入する
  def insert(n, data)
    cp = @root
    while cp
      if n == 0
        cp.link = Cell.new(data, cp.link)
        return data
      end
      n -= 1
      cp = cp.link
    end
  end
  
  # n 番目のデータを求める
  def at(n)
    cp = @root.link
    while cp
      return cp.data if n == 0
      n -= 1
      cp = cp.link
    end
  end
  
  # n 番目のデータを削除する
  def delete(n)
    cp = @root
    while cp.link
      if n == 0
        data = cp.link.data
        cp.link = cp.link.link
        return data
      end
      n -= 1
      cp = cp.link
    end
  end
  
  # Enumerable 用
  def each
    cp = @root.link
    while cp
      yield cp.data
      cp = cp.link
    end
  end
  
  # 文字列に変換
  def to_s
    str = "("
    each do |x|
      str << x.to_s
      str << ","
    end
    if str[-1] == ?,
      str[-1] = ?)
    else
      str << ")"
    end
    str
  end
end

# ソート済み連結リスト
class SortedList < List
  def insert(data)
    cp = @root
    while cp.link
      break if data < cp.link.data
      cp = cp.link
    end
    cp.link = Cell.new(data, cp.link)
  end
end

# 自己組織化探索 (self-organizing search)
class SOList < List
  def find
    cp = @root
    while cp.link
      if yield cp.link.data
        # セルを先頭へ移動する (Move To Front)
        cp1 = cp.link
        cp.link = cp1.link
        cp1.link = @root.link
        @root.link = cp1
        return cp1.data
      end
      cp = cp.link
    end
  end
end

# 連結リストによるスタックの実装
class Stack
  attr_reader :size
  def initialize
    @size = 0
    @buff = List.new
  end
  
  # データを追加する
  def push(data)
    @size += 1
    @buff.insert(0, data)
  end
  
  # データを取り出す
  def pop
    @size -= 1
    @buff.delete(0)
  end
  
  # スタックは空か?
  def empty?
    @size == 0
  end
end

# 循環リストによるキューの実装
class Queue
  attr_reader :size
  def initialize
    @size = 0
    @rear = nil
  end
  
  # データを追加する
  def enqueue(data)
    if @rear
      cp = Cell.new(data, @rear.link)
      @rear.link = cp
      @rear = cp
    else
      @rear = Cell.new(data)
      @rear.link = @rear     # 循環リスト
    end
    @size += 1
    data
  end
  
  # データを取り出す
  def dequeue
    if @rear
      front = @rear.link     # @rear.link が front
      if front == @rear
        @rear = nil          # 最後の一つ
      else
        @rear.link = front.link
      end
      @size -= 1
      front.data
    end
  end
  
  # キューは空か?
  def empty?
    @size == 0
  end
end

# テスト
if __FILE__ == $0
  # スタックの動作
  a = Stack.new
  5.times do |x|
    print "push ", a.push(x), "\n"
  end
  while !a.empty?
    print "pop ", a.pop, "\n"
  end

  # キューの動作
  b = Queue.new
  5.times do |x|
    print "enqueue ", b.enqueue(x), "\n"
  end
  while !b.empty?
    print "dequeue ", b.dequeue, "\n"
  end
end

●実行例

push 0
push 1
push 2
push 3
push 4
pop 4
pop 3
pop 2
pop 1
pop 0
enqueue 0
enqueue 1
enqueue 2
enqueue 3
enqueue 4
dequeue 0
dequeue 1
dequeue 2
dequeue 3
dequeue 4

双方向リスト

双方向リストは、直後のセルだけでなく直前のセルへの参照を持たせたデータ構造です。双方向リストは「重連結リスト (doubly-linked list) 」と呼ばれることもあります。双方向リストを使う場合、ヘッダセルを用意してリストを環状に構成することが多いです。

        ヘッダセル
      ┌─┬─┬─┐
┌←─┼・│  │・│←───────────────────┐
│┌→│・│  │・┼─→─────────────────┐│
││  └─┴─┴─┘                                      ││
││                                                      ││
││       data              data              data       ││
││  ┌─┬─┬─┐    ┌─┬─┬─┐    ┌─┬─┬─┐  ││
│└←┼・│A│・│←─┼・│B│・│←─┼・│C│・│←┘│
└─→│・│  │・┼─→│・│  │・┼─→│・│  │・┼─→┘
      └─┴─┴─┘    └─┴─┴─┘    └─┴─┴─┘
       prev    link      prev    link      prev    link

                      図 : 双方向リスト

連結リストは後ろ方向にしかセルをたどることができませんが、双方向リストでは前後どちらの方向へもセルをたどることができます。セルを削除する場合も、前後のセルがわかるので簡単に削除することができます。

●プログラム

#
# dlist.rb : 双方向リスト
#
#            Copyright (C) 2006 Makoto Hiroi
#
class DCell
  attr_accessor :data, :link, :prev
  def initialize(data, link = nil, prev = nil)
    @data = data
    @link = link
    @prev = prev
  end
end

class DList
  include Enumerable
  
  def initialize
    @head = DCell.new(nil)  # Header Cell
    @head.link = @head
    @head.prev = @head
  end
  
  private
  # n 番目のセルを求める
  def _at(n)
    if n >= 0
      cp = @head.link
      while cp != @head
        return cp if n == 0
        n -= 1
        cp = cp.link
      end
    else
      cp = @head.prev
      while cp != @head
        n += 1
        return cp if n == 0
        cp = cp.prev
      end
    end
  end
  
  public
  # n 番目の要素を求める
  def at(n)
    cp = _at(n)
    cp.data if cp
  end
  
  # n 番目のデータを削除
  def delete(n)
    cp = _at(n)
    if cp
      # p <--> cp <--> q
      p = cp.prev
      q = cp.link
      p.link = q
      q.prev = p
      cp.data
    end
  end
  
  # n 番目にデータを挿入する
  def insert(n, data)
    q = @head
    if n >= 0
      begin
        if n == 0
          #  q <--> cp <--> p
          p = q.link
          cp = DCell.new(data, p, q)
          q.link = cp
          p.prev = cp
          return data
        end
        n -= 1
        q = q.link
      end while q != @head
    else
      begin
        n += 1
        if n == 0
          #  p <--> cp <--> q
          p = q.prev
          cp = DCell.new(data, q, p)
          q.prev = cp
          p.link = cp
          return data
        end
        q = q.prev
      end while q != @head
    end
  end
  
  # Enumerable 用
  def each
    cp = @head.link
    while cp != @head
      yield cp.data
      cp = cp.link
    end
  end
  
  # 文字列に変換
  def to_s
    if @head.link != @head
      str = "("
      each do |x|
        str << x.to_s
        str << ","
      end
      str[-1] = ?)
    else
      str = "()"
    end
    str
  end
end

# デキューの実装
class Dequeue
  attr_reader :size
  def initialize
    @size = 0
    @buff = DList.new
  end
  
  # Array の仕様に合わせる
  # 最後尾にデータを追加
  def push(data)
    @size += 1
    @buff.insert(-1, data)
  end
  
  # 最後尾からデータを削除
  def pop
    if @size > 0
      @size -= 1
      @buff.delete(-1)
    end
  end
  
  # 先頭にデータを追加
  def unshift(data)
    @size += 1
    @buff.insert(0, data)
  end
  
  # 先頭からデータを削除
  def shift
    if @size > 0
      @size -= 1
      @buff.delete(0)
    end
  end
  
  # デキューは空か?
  def empty?
    @size == 0
  end
end

# テスト
if __FILE__ == $0
  a = DList.new
  b = DList.new
  10.times do |x|
    a.insert(0, x)
    b.insert(-1, x)
  end
  puts a
  puts b

  c = Dequeue.new
  10.times do |x|
    print "push: ", c.push(x), "\n"
  end
  5.times do
    print "shift :", c.shift, "\n"
  end
  5.times do
    print "pop :", c.pop, "\n"
  end
end

●実行例

(9,8,7,6,5,4,3,2,1,0)
(0,1,2,3,4,5,6,7,8,9)

push: 0
push: 1
push: 2
push: 3
push: 4
push: 5
push: 6
push: 7
push: 8
push: 9
shift :0
shift :1
shift :2
shift :3
shift :4
pop :9
pop :8
pop :7
pop :6
pop :5

Copyright (C) 2006 Makoto Hiroi
All rights reserved.

[ PrevPage | R u b y | NextPage ]