第5章の練習,投票


アルゴリズムのない問題は?

  1. 整数を素因数分解する。
  2. 一般の方程式の整数解を求める
  3. 将棋の必勝手を求める
  4. 数独パズルを解く
  5. 路線図の最短経路を求める

100番目のフィボナッチ数 fib(100)は?

  1. 偶数
  2. 奇数

スピード競争

load("./bench.rb")
load("./fib.rb")
for k in 10..24
  run("fibr",k)
  run("fibl",k)
end
command("set logscale y")
for k in 10..32
  run("fibr",k)
end
reset()
command("unset logscale")
for m in 1..10
  run("fibl6",10000*m)
end

進捗状態の確認

  1. fibl6の表示までできた時点で投票してください.
  2. Y軸を対数スケールにしてfibrの表示ができた
  3. fibrとfiblの表示ができた
  4. まだ

行列の固有値は

  1. 0
  2. ±1
  3. ±√2
  4. (1±√3)/2
  5. (1±√5)/2
手計算で答えることを想定していますが,Mathematicaが使える人は,
A ={{1,1},{1,0}};
MatrixForm[%]
Eigenvalues[A]
で計算することもできます.

国語辞典で先にくるのは?

  1. しょうほう
  2. しようほう
  3. じょうほ
  4. じょうほう
  5. ショー

単純整列法

simplesort.rb
def simplesort(a)
  for i in 0..(a.length()-1)
    k = min_index(a,i)
    v = a[i]
    a[i] = a[k]
    a[k] = v
  end
  a
end

人形の並び替え

def index_to_x(i)
  i * 30 + 60
end

def index_to_y(i)
  400
end

def person16()
  a = Array.new(16)
  for i in 0..15
    a[i] = Person.new()
    a[i].x = index_to_x(i)
    a[i].y = index_to_y(i)
    a[i].height = rand(60) + 40
  end
  a
end
tmp = a[i]
a[i] = a[k]
a[k].move(index_to_x(i), index_to_y(i)) 
a[k] = tmp
tmp.move(index_to_x(k), index_to_y(k)) 

単純整列法のアニメーション


animated_simplesort.rb

include(Komaba::MiniStar)

def min_index(a, i)
  min = i 
  for j in i..(a.length()-1)
    if a[j] < a[min]
      min = j
    end
  end
  min
end

def simplesort(a)
  for i in 0..(a.length()-1)
    k = min_index(a, i)
    a[k].flash(0.5)
    tmp = a[i]
    a[i] = a[k]
    a[k].move(index_to_x(i), index_to_y(i)) 
    a[k] = tmp
    tmp.move(index_to_x(k), index_to_y(k)) 
  end
  a
end

def index_to_x(i)
  i * 30 + 60
end

def index_to_y(i)
  400
end

def person16()
  a = Array.new(16)
  for i in 0..15
    a[i] = Person.new()
    a[i].x = index_to_x(i)
    a[i].y = index_to_y(i)
    a[i].height = rand(60) + 40
  end
  a
end
実行
a=person16()
simplesort(a)
消す 
for i in 0 .. (a.length()-1)
    a[i].hide()
end

併合並列法

def is_even(x)
  x%2 == 0
end
def merge(a,b)
  c = Array.new(a.length()+b.length())
  ia=0	
  ib=0
  ic=0
  while ia < a.length() && ib < b.length()
    if a[ia] < b[ib]
      c[ic] = a[ia]
      ia = ia + 1
      ic = ic + 1
    else
      c[ic] = b[ib]
      ib = ib + 1
      ic = ic + 1
    end
  end
  if ia < a.length()
    for i in ia..(a.length() - 1)
      c[ic] = a[i]
      ic = ic + 1
    end
  else
    if ib < b.length()
      for i in ib..(b.length() - 1)
        c[ic] = b[i]
        ic = ic + 1
      end
    end
  end
  c
end

def mergesort(a)
  n = a.length()
  from = Array.new(n)
  for i in 0..(n-1)
    from[i] = [ (a[i]) ]
  end
  while n > 1
    to = Array.new((n+1)/2)
    for i in 0..(n/2-1)
      to[i] = merge(from[i*2], from[i*2+1])
    end
    if !is_even(n)
      to[(n+1)/2-1]=from[n-1]
    end
    from=to
    n=(n+1)/2
  end
  from[0]
end

併合並列法(アニメーション)

animated_mergesort.rb
include(Komaba::MiniStar)

def mergesort(a)
  n = a.length()
  from = Array.new(n)
  for i in 0..(n-1)
    from[i] = [a[i]]
  end
  while n > 1
    to = Array.new((n+1)/2)
    for i in 0..(n/2-1)
      to[i] = merge(from[i*2], from[i*2+1])
    end
    if !is_even(n)
      to[(n+1)/2-1] = from[n-1]
    end
    from = to
    n = (n+1)/2
  end
  from[0]
end

def merge(a, b)
  for i in 0..(a.length() - 1)
    a[i].flash(0.5, [1, 0, 0])
  end
  for i in 0..(b.length() - 1)
    b[i].flash(0.5, [0, 0, 1])
  end
  c = Array.new(a.length() + b.length())
  ia = 0
  ib = 0
  ic = 0
  while ia < a.length() && ib < b.length()
    if a[ia] < b[ib]
      c[ic] = a[ia]
      move_smaller(c[ic], ic - ia)
      ia = ia + 1
      ic = ic + 1
    else
      c[ic] = b[ib]
      move_smaller(c[ic], ic - (a.length() + ib))
      ib = ib + 1
      ic = ic + 1
    end
  end
  if ia < a.length()
    for i in ia..(a.length() - 1)
      c[ic] = a[i]
      move_smaller(c[ic], ic - i)
      ic = ic + 1
    end
  else
    if ib < b.length()
      for i in ib..(b.length() - 1)
        c[ic] = b[i]
        move_smaller(c[ic], ic - (a.length() + i))
        ic = ic + 1
      end
    end
  end
  c
end

def is_even(n)
  n % 2 == 0
end

def index_to_x(i)
  i * 30 + 60
end

def next_y(person)
  if person.y == 400
    200
  else
    400
  end
end

def move_smaller(person, dx)
  person.move(person.x + dx * 30, next_y(person))
end

def person16()
  a = Array.new(16)
  for i in 0..15
    a[i] = Person.new()
    a[i].x = index_to_x(i)
    a[i].y = 400
    a[i].height = rand(60) + 40
  end
  a
end
実行
a=person16()
mergesort(a)
消す 
for i in 0 .. (a.length()-1)
    a[i].hide()
end

併合整列法(再帰)

mergesort_rec.rb
def mergesort(a)
  submergesort(a,0,a.length())
end

def submergesort(a,i,n)
  if n<2
    if n==0
      [ ]
    else
      [ (a[i]) ]
    end
  else
    merge(submergesort(a,i,n/2),submergesort(a,i+n/2,n-n/2))
  end
end

併合整列法(再帰)アニメーション

animated_mergesort_rec.rb
include(Komaba::MiniStar)

def merge(a, b)
  for i in 0..(a.length() - 1)
    a[i].flash(0.5, [1, 0, 0])
  end
  for i in 0..(b.length() - 1)
    b[i].flash(0.5, [0, 0, 1])
  end
  c = Array.new(a.length() + b.length())
  ia = 0
  ib = 0
  ic = 0
  while ia < a.length() && ib < b.length()
    if a[ia] < b[ib]
      c[ic] = a[ia]
      move_smaller(c[ic], ic - ia)
      ia = ia + 1
      ic = ic + 1
    else
      c[ic] = b[ib]
      move_smaller(c[ic], ic - (a.length() + ib))
      ib = ib + 1
      ic = ic + 1
    end
  end
  if ia < a.length()
    for i in ia..(a.length() - 1)
      c[ic] = a[i]
      move_smaller(c[ic], ic - i)
      ic = ic + 1
    end
  else
    if ib < b.length()
      for i in ib..(b.length() - 1)
        c[ic] = b[i]
        move_smaller(c[ic], ic - (a.length() + i))
        ic = ic + 1
      end
    end
  end
  c
end

def mergesort(a)
  submergesort(a,0,a.length())
end

def submergesort(a,i,n)
  if n<2
    if n==0
      []
    else
      [a[i]]
    end
  else
    merge(submergesort(a,i,n/2),submergesort(a,i+n/2,n-n/2))
  end
end

def index_to_x(i)
  i * 30 + 60
end

def next_y(person)
  if person.y == 400
    200
  else
    400
  end
end

def move_smaller(person, dx)
  person.move(person.x + dx * 30, next_y(person))
end

def person16()
  a = Array.new(16)
  for i in 0..15
    a[i] = Person.new()
    a[i].x = index_to_x(i)
    a[i].y = 400
    a[i].height = rand(60) + 40
  end
  a
end
実行
a=person16()
mergesort(a)
消す 
for i in 0 .. (a.length()-1)
    a[i].hide()
end


クイックソート

qsort.rb
def quick_sort(a)
  qsort(a, 0, a.length()-1)
end

def qsort(a, from, to)  
  if from < to
    pivot = (from + to) / 2
    med = a[pivot]
    l = from
    r = to  
    while l <= r do
      while a[l] < med
        l = l + 1
      end
      while a[r] > med
        r = r - 1
      end
      if l <= r
        tmp = a[l]
        a[l] = a[r]
        a[r] = tmp
        l = l + 1
        r = r - 1
      end
    end
    qsort(a, from, r)
    qsort(a, l, to)
  end
  a
end

クイックソート(アニメーション)

include(Komaba::MiniStar)

def quick_sort(a)
  qsort(a, 0, a.length()-1)
end

def qsort(a, from, to)  
  if from < to
    pivot = (from + to) / 2
    med = a[pivot]
    med.flash(1.5)
    l = from
    r = to  
while l <= r do
      while a[l] < med
        l = l + 1
      end
      while a[r] > med
        r = r - 1
      end
      if l <= r
        tmp = a[l]
        a[l] = a[r]
        a[r].move(index_to_x(l), index_to_y(l)) 
        a[r] = tmp
        tmp.move(index_to_x(r), index_to_y(r))
        l = l + 1
        r = r - 1
      end
    end
    qsort(a, from, r)
    qsort(a, l, to)
  end
  a
end
def index_to_x(i)
  i * 30 + 60
end

def index_to_y(j)
  400
end

def person16()
  a = Array.new(16)
  for i in 0..15
    a[i] = Person.new()
    a[i].x = index_to_x(i)
    a[i].y = index_to_y(i)
    a[i].height = rand(60) + 40
  end
  a
end
実行
a=person16()
quick_sort(a)
消す 
for i in 0 .. (a.length()-1)
    a[i].hide()
end

◆アニメはわかりやすかったか?

  1. わかりやすかった
  2. 何とか理解できた
  3. 全然わからなかった

練習: アルゴリズムによる速度差の実測

整列の複数のアルゴリズムに対応したプログラムを作り,速度の違いを調べる ランダムな列を作り,それを整列させてみよ.列の長さで時間がどう変化するかをグラフを描いてみよ グラフから,実行時間を予測する式を推定せよ
load("./randoms.rb ")   # randoms(id,size,max)
load("./bench.rb")        # run(function_name, x, v)
load("./simplesort.rb")  # simplesort(a)
load("./mergesort.rb")  # mergesort(a)
def min_index(a, i)
  min = i 
  for j in i..(a.length()-1)
    if a[j] < a[min]
      min = j
    end
  end
  min
end

def compare_sort(max, step)
  for i in 1..(max/step)
    x=i*step
    a=randoms(i,x,1)
    run("simplesort", x, a)
    a=randoms(i,x,1)
    run("mergesort", x, a)
  end
end
実行例
compare_sort(10000,100)