k01ken’s b10g

He110 W0r1d!

PHPでお絵かきロジックの任意の一行/一列分のスペースの全パターンを列挙する

開発環境は、Windows 7 Professional(32bit)+XAMPP v3.22+PHP 7.1.7。

お絵かきロジック
例えば、一行が15マスで、ある横のヒント数が3,1,1,3として、4つだった場合、スペースとして考えられるのは、5箇所(ヒント数+1)なので、5と指定。
次に、ヒント数の合計(3,1,1,3とすれば8)を一行の15マスから引いて、余りが7。
自作したtest関数では、第1引数に5を第2引数に7を入れると、その一行分のスペースの全パターンが取得できる。

ある一行分/一列分だけ実現するためには、for文を何重にもして作ればいいが、あらゆる行列に汎用的に対応するためには、再帰関数を作ったほうが良いので作った。頭がこんがらがりながらも、何とか作りました。

<?php
/*
	任意の1行/1列分のスペースの全パターンが列挙される。
	$max - スペースの数 = ヒント数+1
	$comma_sum - 余っているコマの合計 = 一列か行の枠の数 - ヒント数の合計
	$count - 現在の階層を知る = 常に0。内部ではカウントしていく。
	$p - 現在の位置を取得する
        $comma_sumは、数が少ない場合と多い場合は、組み合わせのパターンは少なくて、中央部分の
	組み合わせのパターンは多い?正規分布みたいになる?合計が0と最大値はただ1つだけだ。
*/
function test($max,$comma_sum,$count = 0,$p = null){
	$frame_min = 0;
	$frame_max = 0;
	$count++;

	if(($count === 1 or $count === $max) and $max !== 2){
		$frame_min = 0;
		$frame_max = $comma_sum;
	}else if(($count === 1 or $count === $max) and $max === 2){
		# ヒント数が1つしかない場合
		$frame_min = 0;
		$frame_max = $comma_sum+1;
	}else{
		$frame_min = 1;
		$frame_max = $comma_sum;
	}

	for($i = $frame_min; $i < $frame_max; $i++){
		if($count < $max){
			test($max,$comma_sum,$count,$p.$i.",");
		}else{
			$x = $p.$i;
			$arr = explode(",",$x);
			$sum = 0;
			for($s = 0; $s < count($arr); $s++){ $sum += $arr[$s]; }

			if($sum === $comma_sum){
				echo $x."<br>";
			}
		}
	}
}

test(5,7);

?>

動作結果はこちら、
f:id:k01ken:20180408235932p:plain