Skip to content

Instantly share code, notes, and snippets.

@Cartman0
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Cartman0/8789a2675b889ef5e74c to your computer and use it in GitHub Desktop.
Save Cartman0/8789a2675b889ef5e74c to your computer and use it in GitHub Desktop.
BinarySearch を可視化
<!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