Last active
August 29, 2015 14:23
-
-
Save Cartman0/8789a2675b889ef5e74c to your computer and use it in GitHub Desktop.
BinarySearch を可視化
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="description" content=""> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Visualize Binary Search(JS)</title> | |
<style> | |
@import url(http://fonts.googleapis.com/earlyaccess/notosansjapanese.css); | |
html, body{ | |
font-size: 20px; | |
font-family: 'Noto Sans Japanese', sans-serif; | |
text-align: center; | |
background-color: #fafafa; | |
} | |
input[type="number"]{ | |
width: 5rem; | |
} | |
textarea { | |
max-width: 100%; | |
width: 90%; | |
margin: 1rem auto; | |
box-sizing: border-box; | |
} | |
span.span{ | |
display: inline-block; | |
box-sizing: border-box; | |
width: calc(90% / 3); | |
} | |
span.left{ | |
color: rgba(50, 50, 200, 0.7); | |
} | |
span.middle{ | |
color: rgba(50, 200, 50, 0.7); | |
} | |
span.right{ | |
color: rgba(200, 50, 50, 0.7); | |
} | |
#flex-box{ | |
display: flex; | |
display: -webkit-flex; | |
flex-direction: row; | |
flex-wrap: wrap; | |
margin: 1rem; | |
} | |
.box { | |
width: 10%; | |
border: 1px solid #333; | |
background-color: rgba(200, 200, 200, 0.7); | |
box-sizing: border-box; | |
transition: opacity 2.4s ease; | |
opacity: 1; | |
} | |
.box:hover { | |
background-color: rgba(200, 200, 200, 0.4); | |
} | |
.start { | |
background-color: rgba(50, 50, 200, 0.7); | |
} | |
.start:hover { | |
background-color: rgba(50, 50, 200, 0.4); | |
} | |
.mid { | |
background-color: rgba(50, 200, 50, 0.7); | |
transition: transform 2.4s ease; | |
} | |
.mid:hover { | |
background-color: rgba(50, 200, 50, 0.4); | |
} | |
.end { | |
background-color: rgba(200, 50, 50, 0.7); | |
} | |
.end:hover { | |
background-color: rgba(200, 50, 50, 0.4); | |
} | |
.fadeOut{ | |
box-sizing: border-box; | |
width: 10%; | |
opacity: 0.1; | |
} | |
</style> | |
</head> | |
<body> | |
<header> | |
<h1>Visualize Binary Search</h1> | |
</header> | |
<main> | |
<p>データを入力して下さい。区切り文字は、半角スペース( )、 カンマ( , )、スラッシュ( / )、 縦線( | )です。</p> | |
<div> | |
<label for="target">Min:</label> | |
<input type="number" id ="set-val-min" value="1" placeholder="1" require> | |
<label for="target">Max:</label> | |
<input type="number" id ="set-val-max" value="100" placeholder="100" require> | |
<input type="button" value="set" id="btn-set"/> | |
</div> | |
<textarea name="" id="textarea" value="" cols="30" rows="20" placeholder="例:2 3 4 1 100" require></textarea> | |
<div> | |
<label for="target">探索値:</label> | |
<input type="number" id ="target" value="" placeholder="100" require> | |
<input type="button" value="探索!" id="button" disabled/> | |
</div> | |
<h2 id="status"></h2> | |
<div> | |
<span class="span left">left</span> <span class="span middle">middle</span> <span class="span right">right</span> | |
</div> | |
<p id="search">探索回数:<span id="search-num">0</span></p> | |
<div id="flex-box"></div> | |
</main> | |
<!-- jquery <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script> --> | |
<script> | |
(function(){ | |
//テキストエリアに 1-100入力 | |
var textarea = document.getElementById('textarea'); | |
InitialInputTextarea(textarea, 1, 100); | |
//テキストエリアに値をセット | |
var btn_set = document.getElementById('btn-set'); | |
var in_min = document.getElementById('set-val-min'); | |
var in_max = document.getElementById('set-val-max'); | |
abledDisbledBtn(in_min, in_max, btn_set); | |
btn_set.onclick = function(){ | |
var min = in_min.value; | |
var max = document.getElementById('set-val-max').value; | |
InitialInputTextarea(textarea, min, max); | |
} | |
//テキストボックス・テキストボックスの入力確認 | |
var btn = document.getElementById('button'); | |
var in_target = document.getElementById("target"); | |
abledDisbledBtn(textarea, in_target, btn); | |
//ボタンがクリックされたら | |
btn.onclick = function(){ | |
var strs = textarea.value; | |
var search_num = 0; | |
//文字列から数字配列へ | |
var A = strs2numArray(strs); | |
//昇順ソート | |
A.sort(compareNumbers); | |
function compareNumbers(a, b) { | |
return a - b; | |
} | |
/* A配列を並べる */ | |
var flex_box = document.getElementById('flex-box'); | |
// clear | |
cleardiv(flex_box); | |
for (var i in A){ | |
var box = document.createElement('div'); | |
box.className = "box"; | |
box.innerHTML = A[i]; | |
flex_box.appendChild(box); | |
} | |
//目標値取得 | |
var target = Number(in_target.value); | |
//二分探索 | |
var binSearch_result = binary_search(A, 0, A.length-1, target); | |
//BinarySearchアニメーション | |
animateBinarySearch(binSearch_result, flex_box, document.getElementById('search')); | |
// status表示 | |
var status = document.getElementById('status'); | |
printStatus(status, binSearch_result); | |
} | |
/************************* function *****************************************/ | |
//テキストエリアに 1-100入力 | |
function InitialInputTextarea(textarea_obj, min, max) { | |
var str = ""; | |
for(var i = min; i <= max; i++){ | |
str += (i + " "); | |
} | |
textarea_obj.value = str; | |
} | |
// 入力されていればボタンを有効に | |
function abledDisbledBtn(textarea_obj, input_obj, btn_obj){ | |
input_obj.onchange = checkInputValue; | |
textarea_obj.onchange = checkInputValue; | |
function checkInputValue(){ | |
if ( (textarea_obj.value === '') || (input_obj.value === '') ){ | |
//ボタン無効 | |
btn_obj.disabled = "true"; | |
}else{ | |
//ボタン有効 | |
btn_obj.disabled = ""; | |
} | |
} | |
} | |
function strs2numArray(strs){ | |
var str_array = strs.replace(/[\,/\|\s]+/g, '<>').split('<>'); | |
var num_array = new Array(); | |
for(var i = 0; i < str_array.length; i++){ | |
if(str_array[i] != ""){ | |
num_array.push(Number(str_array[i])); | |
} | |
} | |
return num_array; | |
} | |
function binary_search(a, start_idx, end_idx, target){ | |
var start = start_idx; | |
var end = end_idx; | |
var timerid; | |
var idx_array = new Array(); | |
while ((end - start) >= 0){ | |
var mid = Math.floor((end + start) / 2); | |
idx_array.push( | |
{ | |
start: start, | |
mid: mid, | |
end: end | |
} | |
); | |
if(a[mid] === target){ | |
return { | |
flag: true, | |
index: mid, | |
array: idx_array, | |
}; | |
}else if(a[mid] > target){ | |
end = mid - 1; | |
}else { | |
start = mid + 1; | |
} | |
} | |
return { | |
flag: false, | |
index: -1, | |
array: idx_array, | |
}; | |
} | |
function cleardiv(boxes){ | |
var child; | |
while (child = boxes.firstChild){ | |
boxes.removeChild(child); | |
} | |
} | |
function animateBinarySearch(bin_s, boxes, base_move){ | |
var i = 0; | |
var timerid; | |
//探索回数 | |
var search_num = document.getElementById('search-num'); | |
draw(); | |
function draw(){ | |
if(i >= bin_s.array.length){ | |
clearTimeout(timerid); | |
return; | |
} | |
//探索回数表示 | |
search_num.innerHTML = i + 1; | |
//見なくなった left 部分を除去 | |
for(var s = 0; s < bin_s.array[i].start; s++){ | |
boxes.childNodes[s].className = "fadeOut"; | |
} | |
//見なくなった right 部分を除去 | |
for (var e = bin_s.array[i].end + 1; e < boxes.childNodes.length; e++){ | |
boxes.childNodes[e].className = "fadeOut"; | |
} | |
//start の要素に着色 | |
boxes.childNodes[bin_s.array[i].start].className = "box start"; | |
//end の要素に着色 | |
boxes.childNodes[bin_s.array[i].end].className = "box end"; | |
//mid の要素に着色 | |
boxes.childNodes[bin_s.array[i].mid].className = "box mid"; | |
// 見つけた値を移動 | |
if(i === (bin_s.array.length - 1)){ | |
var goal = boxes.childNodes[bin_s.array[i].mid]; | |
var x = (base_move.offsetLeft + base_move.offsetWidth/2) - goal.offsetLeft; | |
var y = (base_move.offsetTop + base_move.offsetHeight/2) - goal.offsetTop; | |
goal.style.transform = 'translateX(-50%) translateY(-50%) translateY(2rem)' + 'translateX('+ x +'px) ' + 'translateY('+ y +'px)'; | |
} | |
i++; | |
timerid = setTimeout( draw, 2500); | |
} | |
} | |
// Status表示 | |
function printStatus(status_obj, binSerach_result){ | |
if (binSerach_result.flag){ | |
status_obj.style.color = '#33ee33'; | |
status_obj.innerHTML = 'Success'; | |
}else{ | |
status_obj.style.color = '#ee3333'; | |
status_obj.innerHTML = 'Failed'; | |
} | |
} | |
})(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment