MoyaSystem

もやしです。

JavaScript の console.log で菱型を書く

いつの間にか食レポじゃなくなっていた『俺の食べログ』さんで面白そうな問題があったので。

www.2dgod.com

function diamond(length) {
	const height = 2 * length - 1;
	const width = height;
	const halfline = (width + 1) / 2;
	const space = ' ';
	const ast = '*';

	for (var i=1; i <= height; i++) {
		var numOfAst = 0;
		var spaces = '';
		var asts = '';
                if (i <= halfline) {
			numOfAst = i*2-1;
		} else {
			numOfAst = width - 2 * (i - halfline);
		}
		spaces = space.repeat( (width - numOfAst) / 2);
		asts = ast.repeat(numOfAst);
		console.log(spaces + asts + spaces);
	}
}

diamond(10);

/*
          *         

         ***        

        *****       

       *******      

      *********     

     ***********    

    *************   

   ***************  

  ***************** 

 *******************

  ***************** 

   ***************  

    *************   

     ***********    

      *********     

       *******      

        *****       

         ***        

          *         
*/

Quick sort, Merge sort and Heap sort in PHP

<?php

/**
 * QUICK SORT
 */
function quick_sort($a){

	if(sizeof($a) <= 1){
		return $a;
	}

	$left_a = [];
	$right_a = [];
	$pivot = array_pop($a);

	foreach($a as $e){
		if($e <= $pivot){
			array_push($left_a, $e);
		}else{
			array_push($right_a, $e);
		}
	}

	$left_a = quick_sort($left_a);
	$right_a = quick_sort($right_a);
	return array_merge($left_a, [$pivot], $right_a);
}


/**
 * MERGE SORT
 */
function merge_sort($a){
	$left_a = [];
	$right_a = [];

	if(sizeof($a) <= 1){
		return $a;
	}

	$middle = (int)sizeof($a)/2;

	$left_a = array_slice($a, 0, $middle);
	$right_a = array_slice($a, $middle);

	$left_a = merge_sort($left_a);
	$right_a= merge_sort($right_a);

	return merge($left_a, $right_a);
}

function merge($left, $right){
	$result = [];
	while(sizeof($left) > 0 && sizeof($right) > 0){
		$l = $left[0];
		$r = $right[0];

		if($l <= $r){
			array_push($result, array_shift($left));
		}else{
			array_push($result, array_shift($right));
		}
	}

	while(sizeof($left) > 0){
		array_push($result, array_shift($left));
	}

	while(sizeof($right) > 0){
		array_push($result, array_shift($right));
	}

	return $result;
}


/**
 * HEAP SORT
 */
function heap_sort($a){
	$result = $a;

	// create heap
	for($i=0;$i<sizeof($a);$i++){
		$result = upheap($result, $i);
	}

	for($i=sizeof($a)-1;$i>0;$i--){
		// put the first element into sorted list area
		$result = swap($result, 0, $i);
		$result = downheap($result, $i);
	}

	return $result;
}

function swap($arr, $a, $b){
	$temp = $arr[$a];
	$arr[$a] = $arr[$b];
	$arr[$b] = $temp;
	return $arr;
}

// make arr[0] - arr[$n] heap
function upheap($arr, $n){
	while($n > 0){
		// get parent value
		$m = (int)(($n+1)/2-1);
		if($arr[$m] < $arr[$n]){
			// if a child is bigger than its parent, swap them
			$arr = swap($arr, $m, $n);
		}else{
			// if $arr is valiable heap, break
			break;
		}
		// check parent's value
		$n = $m;
	}
	return $arr;
}

// make arr[0] - arr[$n-1] heap
function downheap($arr, $n){
	$parent_to_swap = 0;
	$child_to_swap = 0;

	while(true){
		$l_child = (int)($parent_to_swap+1)*2-1;
		$r_child = (int)($parent_to_swap+1)*2;

		// if left child overflow the target, break
		if($l_child >= $n){
			break;
		}

		// Is left child bigger than its parent?
		if($arr[$l_child] > $arr[$child_to_swap]){
			$child_to_swap = $l_child;
		}

		// Is right child within target and bigger than its parent?
		if($r_child < $n && $arr[$r_child] > $arr[$child_to_swap]){
			$child_to_swap = $r_child;
		}

		// no need to swap, break
		if($child_to_swap === $parent_to_swap){
			break;
		}

		$arr = swap($arr, $child_to_swap, $parent_to_swap);

		// continue checking with the swaped child as a new parent
		$parent_to_swap = $child_to_swap;
	}

	return $arr;
}



$arr = [5,3,2,9,7,0,1,4,6,8];
var_dump(quick_sort($arr));
echo "<br/>";
var_dump(merge_sort($arr));
echo "<br/>";
var_dump(heap_sort($arr));
?>

PHPUnit の setUp関数と setUpBeforeClass 関数の違い

PHPUnit の setUp 関数について勘違いしていた。


setUp 関数は、クラス内のテストケースそれぞれについて、開始前に1回ずつ起動する。インスタンスのプロパティの初期化に用いるとよい。


一方、setUpBeforeClass 関数は、クラスをインスタンス化する前に1度だけ起動する。DBへの接続や、テストケースで共通に使う値(ユーザなど)の作成に用いると良い。これは static 関数なので、当然 static な変数しか扱えないことに注意。


tearDown 関数と tearDownAfterClass 関数にも同様の関係が言える。


setUp 関数は全部のテストケース実行前になされるものだと思っていたら違ったのでメモメモ。

CSS の text-decoration 要素の設定値

設定値は6つあり、主な設定値は、overline、underline、line-through の3つ。

<span style='text-decoration: overline'>overline</span>

出力: overline

いつつかうんだ?これ。

<span style='text-decoration: underline'>underline</span>

出力: underline

<span style='text-decoration: line-through'>line-through</span>

出力: line-through

あとは

  • none
  • initial
  • inherit

の3つを設定できる。

ポートフォリオサイト的なの作った

GitHubポートフォリオサイト的なの作りました。

"Hassy"'s portfolio

1日でやっつけた割にはそこそこのできになったと思います。英文チェック全然やってないから添削必要だとは思うけど。

ぼくはデザインスキルほぼ皆無なので、こういった素敵ツールは役に立ちます。

bootflat.github.io


なおサムネイルにホバーすると浮き上がった感じに見えるエフェクトは

Ishikura Noboru portfolio

さんを パk オマージュさせていただきました。この場を借りて感謝申し上げます m(_ _)m

Object.create()時にenumerableをtrueにしておかないとオブジェクトがクローンできない件

Object.create()とは

JavaScriptにおいて、プロトタイプベースの継承を行う際によく用いられる関数です。

MDN: Object.create()

拙著過去記事も参照ください

JavaScriptにクラスはありません - オブジェクトリテラルとコンストラクタパターン編 -

JavaScriptにクラスはありません - プロトタイプで継承編 -

オブジェクト指向でよくみられる、「親クラスのプロパティをすべて再利用しつつ、子クラス独自のプロパティも定義する」ことをJavaScriptで実現できます。使用例を次に示します。

var obj = function obj(){};
obj.prototype.prop = function(){alert('prop')};
// オブジェクト生成
var object = Object.create(obj.prototype,{
    hoge: {value: 'fuga'},
    foo: {value: 'bar'}
});

var subobj = function subobj(){};
subobj.prototype = new obj(); // objのプロパティを継承
subobj.prototype.myprop = function(){alert('myprop')}; // 独自のプロパティ

例に示したように、Object.createの引数はふたつあります。第1引数は新しいオブジェクトのプロトタイプ、そして第2引数はプロパティオブジェクトと呼ばれる、オブジェクトのプロパティを要素に持つオブジェクトです。 このプロパティオブジェクト、設定値がいろいろあるのですが、悪いこと言わないのでenumerableをtrueにしておけという話です。

enumerableをtrueにしておかないと

何が困るかというと、underscore.jsやlodash.jsを使ってオブジェクトをクローンする時に困るのです。 JavaScriptにおいて、オブジェクトや配列の代入は参照渡しです。そのため、あるオブジェクトを変数に格納して、そののちオブジェクトを編集すると、変数の中身も変わります。

var obj = {hoge: 'fuga'};
var a = obj;
obj.hoge = 'piyo';
console.log(a.hoge); // 'piyo'

残念ながら通常のJavaScriptで実体の代入を実現するのは非常にめんどくさいです。そのためライブラリを用いるのが一般的です。わたしはlodash.jsで用意されている_.cloneDeep()関数をよく使っています。

var obj = {hoge: 'fuga'};
var a = _.cloneDeep(obj); //実体のコピーを作成して代入
obj.hoge = 'piyo';
console.log(a.hoge); // 'fuga'

ところが、Object.create()で作られたオブジェクトをこの関数に適用させる場合、プロパティのenumerableがtrueになっていないとコピーされないのです。 enumerableはデフォルトでfalseになっているので(なぜだ……)、明示的にtrueを指定してやる必要があります。

var obj = function obj(){};
obj.prototype.prop = function(){alert('prop')};
// オブジェクト生成
// ダメな例
var no_good_object = Object.create(obj.prototype,{
    hoge: {value: 'fuga'},
    foo: {value: 'bar'}
});
// これはOK
var good_object = Object.create(obj.prototype,{
    hoge: {value: 'fuga', enumerable: true},
    foo: {value: 'bar', enumerable: true}
});
var a = _.cloneDeep(no_good_object); // これはクローンされない!
var b = _.cloneDeep(good_object); // これはクローンされる

この現象に直面して、lodash.jsのバグじゃないかと思いライブラリのコードを追いかけて数時間無駄にしたのが今日の筆者です。ということで、enumerableをtrueにして快適JavaScriptライフをすごしましょう!