CodeKata Two -- Karate Chop

コード=カタ 二分探索を極める。


A binary chop (binary searchのコト),


それは,ソートされた配列から,探したい値のインデックスを求める単調な方法だ。
探したい値が,全体を二分したグループのどちらにあるかに着目する。
この二分する作業を繰り返し,探している値を見つけるか,
配列の中を探し終えたときに,処理が止まる。
効率はまずまずだ。


【問題】
このKataは直球勝負だ。
テクニックや言語は君に任せるから,二分探索を実装してほしい。
そして次の日,まったく違ったやり方で,再び,実装してもらいたい。
こんなことを,その次の日も,そのまた次の日も繰り返す。
合計,5種類の二分探索を実装してみてくれ。
例えば,ひとつは典型的な繰り返し方式のものだったり,
再帰的だったり,処理が関数に切り分けられていのものだろう。


【目的】
1.アルゴリズムを組む中で出会う,エラーの一つ一つに注目してほしい。
二分探索はエラーの宝庫なんだ。多くのバリエーションを作成していくうちに,
エラーに遭遇することが減っていくのを実感するだろう。


2.作ったバリエーションを見比べて見よう。どれが一番実用的か?
作ってて楽しかったか?完成まで大変だったか?
そして,何故そうっだったかを考えよう。


3.実際,二分探索について,5種類のオリジナルなやり方を見出すのは難しい。
どのようにして達成したか,柔軟な発想ができたかを振り返ろう。


【仕様】
二分探索メソッドを作成する。引数は,探したい値と,対象となる配列だ。
戻り値は,探したい値のインデックスまたは-1(見つからなかったとき)。


chop(int, array_of_int) -> int


配列の数は多くないと思っていい。計算時間やメモリ容量は,このKataでは
気にしなくていい。

【試験値】
def test_chop
    assert_equal(-1, chop(3, []))
    assert_equal(-1, chop(3, [1]))
    assert_equal(0,  chop(1, [1]))
    #
    assert_equal(0,  chop(1, [1, 3, 5]))
    assert_equal(1,  chop(3, [1, 3, 5]))
    assert_equal(2,  chop(5, [1, 3, 5]))
    assert_equal(-1, chop(0, [1, 3, 5]))
    assert_equal(-1, chop(2, [1, 3, 5]))
    assert_equal(-1, chop(4, [1, 3, 5]))
    assert_equal(-1, chop(6, [1, 3, 5]))
    #
    assert_equal(0,  chop(1, [1, 3, 5, 7]))
    assert_equal(1,  chop(3, [1, 3, 5, 7]))
    assert_equal(2,  chop(5, [1, 3, 5, 7]))
    assert_equal(3,  chop(7, [1, 3, 5, 7]))
    assert_equal(-1, chop(0, [1, 3, 5, 7]))
    assert_equal(-1, chop(2, [1, 3, 5, 7]))
    assert_equal(-1, chop(4, [1, 3, 5, 7]))
    assert_equal(-1, chop(6, [1, 3, 5, 7]))
    assert_equal(-1, chop(8, [1, 3, 5, 7]))
end

【Ans.1】 基本形。Javaです。

	private int chop(int target, int[] array){
		if(array.length==0){		
			return -1;
		}
		int begin = 0;
		int end   = array.length - 1;
		
		while(begin <= end){
			int mean  = (begin+end)/2;
			if( target < array[mean]){
				end = mean -1;
			}else if(target > array[mean]) {
				begin = mean + 1;         
			}else{
				return mean;
			}
		}
		return -1;
	}

【Ans.1.1】 基本形。Rubyです。

def chop(target, array)
	rem = 0
	while array.size >= 1
		mid = ((array.size-1)/2).to_i
		case target <=> array[mid]
			when 1
				array = array[mid+1,array.size]
				rem += mid+1
			when 0
				return mid+rem
			when -1
				array = array[0,mid]
		end
	end
	return -1
end