学生向けプログラミング入門

学生向けにプログラミングを解説。Java、C++、Ruby、PHP、データベース

Rubyプログラミング入門その11 メソッドが複数あるプログラム

<<前  [TOP]  次>>


メソッドとは、ある特定の一連の処理をまとめたプログラムの構造の1つです。

  • メソッドは何個でも自由に記述できます。
  • メソッドを記述する順序は処理の順序とは全く関係ありません。
  • メソッドの名前は自由に付けることができます。


    メモ帳を開いて次のプログラムを作ってみましょう。


    【sort3.rb】

    # sort3.rb
    
    def main(array)
    
    	sort(array)
    
    	for i in 0..(array.length-1) do
    		puts (i+1).to_s + ':' + array[i].to_s
    	end
    
    	
    end
    
    def sort(array)
    	for i in 0..(array.length-1) do
    		maxN( array, i )
    	end
    end
    
    def maxN( array, n )
    
    	max = array[n]
    	maxIndex = n
    
    	for  j in (n+1)..array.length do
    		if ( array[j].to_i > max.to_i ) then
    			max = array[j]
    			maxIndex = j
    		else
    			max = array[n]
    			maxIndex = n	
    		end
    
    		array[maxIndex] = array[n]
    		array[n] = max
    	
    	end
    
    end
    
    data = [10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82]
    main(data)
    



    このプログラムでは、メソッドが三つあります。
    一つめはsort( )、二つめはmaxN( )、もう一つはmain( )です。


    メソッド名の後の括弧( )の中に引数を入れます。
    引数はメソッドの呼び出しの時に入れる引数とイコールの関係を持っています。


    ではプログラムを見ながら説明します。


    mainメソッドの中に次の記述があると思います。

    sort(array)
    

    これがメソッドの呼び出しです。
    このようにメソッドを呼び出すには、メソッド名とその括弧( )の中に与えたい引数を記述するだけで良いのです。
    sort(array)が処理されると、そのメソッドが処理されます。

    def sort(array)
    	for i in 0..(array.length-1) do
    		maxN( array, i )
    	end
    end
    

    このメソッドの中では、dataがarrayとなって処理されるのです。
    このメソッドではすぐfor文でループすることになります。
    ループするごとに今度はmaxNメソッドが呼び出されています。
    引数はarrayと i です。
    次にmaxNメソッドに処理が移り、一番大きな数字を探して前の方と入れ替える作業をします。
    それらの作業を受けて、mainメソッドで出力する作業を行っています。


    出力結果を確認してみましょう。
    f:id:MrRadiology:20180116153841p:plain


    メモ帳を開いて次のプログラムを作ってみましょう。


    【sort4.rb】

    # sort4.rb
    
    def main( array )
    	sort( array )
    
    	for i in 0..(array.length-1) do
    		puts (i+1).to_s + ':' + array[i].to_s
    	end
    end
    
    def sort( array )
    	tmp=0
    
    	for i in 0..(array.length-1) do
    
    		for j in 0..(array.length-(i+1)) do
    
    			if (array[j].to_i < array[j+1].to_i) then
    				tmp = array[j]
    				array[j] = array[j+1]
    				array[j+1] = tmp
    			end
    		end
    
    	end
    end
    
    data =[10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82]
    main(data)
    



    このプログラムは、sort2.rbをmainメソッドとsortメソッドに分けて書き直したプログラムです。
    作業ごとにメソッドを分けるのは、プログラムが見やすくなるというメリットがあります。


    出力結果です。
    f:id:MrRadiology:20180116155708p:plain


    メモ帳を開いて次のプログラムを作ってみましょう。


    【sort5.rb】

    # sort5.rb
    
    def main( array, tmp0 )
    
    	sort( array, tmp0 )
    
    	for i in 0..array.length-1 do
    		puts (i+1).to_s + ':' + array[i].to_s
    	end
    end
    
    def sort( array, tmp0 )
    	sort2( array, 0, array.length-1, tmp0 )
    end
    
    def sort2( array, min, max, tmp0 )
    	if ( (max - min) < 5 ) then
    
    		sort3( array, min, max )
    		return
    	end
    
    	if ( tmp0.nil? ) then 
    		tmp0 = Array.new(array.length)
    	end
    
    	m = average( array, min, max )
    	largeCount=0
    	smallCount=0
    
    	for i in min..max do 
    		if ( array[i].to_f > m.to_f ) then
    			tmp0[ min+largeCount ] = array[i]
    			largeCount += 1
    				
    		else
    			tmp0[ max-smallCount ] = array[i]
    			smallCount += 1
    		end
    	end
    	for i in min..max do
    		array[i] = tmp0[i]
    	end
    
    	sort3( array, min, min+largeCount-1 )
    
    	sort3( array, max-smallCount+1, max-1 )
    
    end
    
    def sort3( array, min, max ) 
    
    	for i in min..max-1 do 
    		for j in min..(max-(i-min)) do
    			if ( array[j] < array[j+1] ) then
    				tmp = array[j]
    				array[j] = array[j+1]
    				array[j+1] = tmp
    			end
    		end
    	end
    end
    
    def average( array, min, max )
    
    	sum = 0.0
    
    	for i in min..max do
    		sum += array[i]
    	end
    	return (sum/( max - min + 1)).to_f
    end
    
    data = [10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82]
    
    tmp = nil
    main(data, tmp)
    



    tmp = nilはこのあとtmp配列を使えるように定義しています。
    作業領域用データを作成しています。
    nilの意味は何もないという意味です。


    まずmain( )からsort()に入ります。
    sort() では、sort2( array, 0, array.length-1, tmp0 )という様にして引数を4つ与えているだけの処理を行っています。
    これにより、 sort2()に入ります。
    ここで、min=0,max=14に置き換わります。(今回のプログラムのみ。与えられるdataの数によって異なります。)


    min=0,max=14なので、最初はif( ( max - min ) < 5 ) の条件に当てはまらず、if ( tmp0.nil? )が呼び出され、tmp0 = Array.new(array.length)となります。
    tmp0.nil? は、tmp0がnilの場合tureを返します。


    ここで、tmp0 = Array.new(array.length)について説明します。
    new演算子は新しくメモリーを確保するときに用います。
    プログラムで配列や変数を扱うときには必ずメモリーを確保しなければなりません。
    dataでは、直接配列に数字を代入しているので、自動的にメモリが確保されています。
    しかしtmpではnilを代入していますから、この時点でメモリはまだ確保されていません。
    自分でメモリを確保する必要があります。
    配列のメモリの確保の仕方は次のように行います。

    変数名 = Array.new(確保メモリ数)
    

    次に、m = average( array, min, max )より、average()が呼び出され、i=0〜14まで繰り返します。
    データの平均が出てreturnします。
    ここで、m = 平均値となります。


    returnについて説明します。
    averageの型がfloatになっているのに注目してください。
    return文を使ってfloat型の戻り値を返しています。
    今回の場合は、return (sum/( max - min + 1)).to_fという記述がこの処理にあたります。
    戻り値として(sum/( max - min + 1)).to_fというfloat型の値を返しています。


    次の記述を見てください。

    if ( array[i].to_f > m.to_f ) then
    	tmp0[ min+largeCount ] = array[i]
    	largeCount += 1
    				
    else
    	tmp0[ max-smallCount ] = array[i]
    	smallCount += 1
    end
    

    これにより平均値より大きいものはtmp0[0]から順に入っていき、小さいものはtmp0[14]からtmp0[13],tmp0[12]・・と入っていきます。
    0〜14まで調べると次に進みます。

    for i in min..max do
    	array[i] = tmp0[i]
    end
    

    これにより配列tmp0の値が配列arrayに代入されます。


    sort3( array, min, min+largeCount-1 )によりmin=0,max=largeCount-1(たぶん7)となりまた再びsort3( array, max-smallCount+1, max-1 )に入ります。
    同時にsort3( array, max-smallCount+1, max-1 )によりmin=max-smallCount+1(たぶん8)、max-1=14となり sort3() に入ります。
    この時点で、2つのブロックに分けられました。
    そして、この2つに分けられたブロックのそれぞれの平均値が出され、それよりも大きいもの、小さいものに分けられます。
    この時点で4つのグループに分けられます。
    そのとき、if ( (max - min) < 5 )の条件に当てはまり、sort3()に入って並び替えされます。


    この並び替えの特徴は、ブロックで分けることによりsort3で処理される並び替えの動作が少なくなることにあります。
    ちょっと複雑ですが、並び替えは今までのプログラムより早くできます。


    出力結果です。
    f:id:MrRadiology:20180117103558p:plain


    メモ帳を開いて次のプログラムを作ってみましょう。


    【sort6.rb】

    # sort6.rb
    
    def main( array, tmp0 )
    
    	sort( array, tmp0 )
    
    	for i in 0..array.length-1 do
    		puts (i+1).to_s + ':' + array[i].to_s
    	end
    end
    
    def sort( array, tmp0 )
    	sort2( array, 0, array.length-1, tmp0 )
    end
    
    def sort2( array, min, max, tmp0 )
    	if ( (max - min).to_i < 5 ) then
    
    		sort3( array, min, max )
    		return
    	end
    
    	if ( tmp0.nil? ) then 
    		tmp0 = Array.new(array.length)
    
    		size = max - min + 1
    		half = size/2 + size%2
    	
    		sort3( array, min, min+half-1 )
    		sort3( array, min+half, max )
    
    		counter1 = 0
    		counter2 = 0
    
    
    		for i in min..max do
    			if ( counter1 > (half-1) ) then
    				tmp0[i] = array[ min+half+counter2 ]
    				counter2 += 1
    			elsif ( counter2.to_i > (max-min-half).to_i ) then
    				tmp0[i] = array[ min+counter1 ]
    				counter1 += 1
    			elsif ((array[min+counter1]).to_i > (array[ min+half+counter2]).to_i) then
    				tmp0[i] = array[ min+counter1 ]
    				counter1 += 1
    			else
    				tmp0[i] = array[ min+half+counter2 ]
    				counter2 += 1
    			end
    		end
    	end
    
    	for i in min..max do
    		array[i] = tmp0[i]
    	end
    
    end
    
    def sort3( array, min, max ) 
    
    	for i in min..max-1 do 
    		for j in min..(max-(i-min)) do
    			if ( array[j].to_i < array[j+1] .to_i) then
    				tmp = array[j]
    				array[j] = array[j+1]
    				array[j+1] = tmp
    			end
    		end
    	end
    end
    
    data = [10, 75, 24, 32, 98, 72, 88, 43, 60, 35, 54, 62, 2, 12, 82]
    
    tmp = nil
    main(data, tmp)
    



    tmp = nilで作業領域用データtmpを作ります。
    まずmain()からsort()にはいります。


    sort() でsort2()に入ります。
    ここで、min=0,max=14に置き換わります。


    最初はtmp = nilなのでif ( tmp0.nil? )がtureになります。
    size=15,half=8となり、sort3( array, min, min+half-1 )でmin=0,max=7,sort( array, min+half, max )でmin=8,max=14となり、それぞれsort3()に入ります。


    sort3( array, min, min+half-1 )では、min=0,max=7なので、またmin=0,max=3とmin=4,max=7の2つに分けられます。
    sort3( array, min+half, max )では、min=8,max=14なので、min=8,max=11とmin=12,max=14の2つに分けられます。
    それぞれ再びsort3() に入ります。
    ここで、配列は次の4つの組に分けられています。


    1組 10, 75, 24, 32
    2組 98, 72, 88, 43
    3組 60, 35, 54, 62
    4組 2, 12, 82


    return文 でループは終わります。


    ここのreturn文は戻り値を返すためではなく、この処理を終わらせる意味を持っています。
    このreturn文がないと、このメソッドの繰り返しループが永遠に繰り返されてしまい、最終的にはメモリを食い尽くしてしまう恐れがあります。
    このreturn文があることで、sort3( array, min, min+half-1 )とsort3( array, min+half, max )のそれぞれの場所まで戻ります。
    同じメソッドを繰り返して使うときは、最後の処理の時にreturn文をつけなければうまく動かなくなりますので気をつけてください。


    ソートされた4組はループに入る前まで戻され、min=0,max=7, とmin=8,max=14の2組がそれぞれsort3()にはいります。


    出力結果です。
    f:id:MrRadiology:20180117113232p:plain


    <<前  [TOP]  次>>