<?php error_reporting(E_ALL);
define('UB', 4 - 1 );
class JyoutaiDef
{
public $BanArr;
public $AlreadyHaitiArr;
public $RestList;
public $BanLog;
public $OpeLog;
}
$WillPush = new JyoutaiDef();
$wkBan = [['青','黒','白','黄'],
['黄','赤','青','黒'],
['白','黒','白','黄'],
['赤','青','赤','青']];
//X座標とY座標を変換してセット
$WillPush->BanArr = array();
for ($X = 0; $X <= UB; $X++) {
for ($Y = 0; $Y <= UB; $Y++) {
$WillPush->BanArr[$X][$Y] = $wkBan[$Y][$X];
}
}
$WillPush->AlreadyHaitiArr = CreateBoolArr();
$WillPush->RestList = array();
for($I = 1; $I <= 3 ; $I++) $WillPush->RestList[] = '赤';
for($I = 1; $I <= 3 ; $I++) $WillPush->RestList[] = '青';
for($I = 1; $I <= 3 ; $I++) $WillPush->RestList[] = '黄';
for($I = 1; $I <= 3 ; $I++) $WillPush->RestList[] = '黒';
for($I = 1; $I <= 4 ; $I++) $WillPush->RestList[] = '白';
$WillPush->BanLog = array();
$WillPush->OpeLog = array();
$Stk = new SplStack();
$Stk->push($WillPush);
$AnswerBanList = array();
$AnswerCnt = 0;
$VisitedSet = array();
while($Stk->isEmpty() == false){
$Popped = $Stk->pop();
if (count($Popped->RestList) == 0) {
$AnswerBanList[] = $Popped->BanArr;
printf('解%dを発見しました' . PHP_EOL , ++$AnswerCnt);
for ($I = 0; $I <= count($Popped->BanLog) - 1; $I++) {
printf('%d手目は %s' . PHP_EOL , $I + 1 , $Popped->OpeLog[$I]);
PrintBan($Popped->BanLog[$I]);
}
continue;
}
foreach(array_unique($Popped->RestList) as $HaitiColor){
for ($X = 0; $X <= UB; $X++) {
for ($Y = 0; $Y <= UB; $Y++) {
if ($Popped->AlreadyHaitiArr[$X][$Y]) continue;
if (CanHaiti($X, $Y, $Popped->BanArr, $HaitiColor) == false) continue;
$WillPush = new JyoutaiDef();
$WillPush->BanArr = $Popped->BanArr;
$WillPush->BanArr[$X][$Y] = $HaitiColor;
$WillPush->AlreadyHaitiArr = $Popped->AlreadyHaitiArr;
$WillPush->AlreadyHaitiArr[$X][$Y] = true;
$WillPush->RestList = $Popped->RestList;
$ind = array_search($HaitiColor,$WillPush->RestList);
unset($WillPush->RestList[$ind]);
$WillPush->BanLog = $Popped->BanLog;
$WillPush->BanLog[] = $WillPush->BanArr;
$WillPush->OpeLog = $Popped->OpeLog;
$WillPush->OpeLog[] = sprintf('[%d,%d]に%sを配置。%s'
,$X, $Y, $HaitiColor, DeriveRestLog($WillPush->RestList));
$Hash = GetHash($WillPush->BanArr, $WillPush->AlreadyHaitiArr);
if(in_array($Hash,$VisitedSet) == false){
$VisitedSet[] = $Hash;
$Stk->Push($WillPush);
}
}
}
}
}
//2次元配列を作って返す
function CreateBoolArr()
{
$WillReturn = array();
for ($I = 0; $I <= UB; $I++) {
$WillReturn[$I] = array();
for ($J = 0; $J <= UB; $J++) {
$WillReturn[$I][$J] = false;
}
}
return $WillReturn;
}
function CanHaiti($pX , $pY , array $pBanArr , $pHaitiColor)
{
for ($X = 0; $X <= UB; $X++) {
for ($Y = 0; $Y <= UB; $Y++) {
if (abs($pX - $X) > 1 || abs($pY - $Y) > 1) continue;
if ($pBanArr[$X][$Y] == $pHaitiColor) return false;
}
}
return true;
}
function DeriveRestLog( array $pRestList)
{
$WillReturn = '残りは';
$WillReturn .= sprintf('赤%d,', count(array_keys($pRestList , '赤')));
$WillReturn .= sprintf('青%d,', count(array_keys($pRestList , '青')));
$WillReturn .= sprintf('黄%d,', count(array_keys($pRestList , '黄')));
$WillReturn .= sprintf('黒%d,', count(array_keys($pRestList , '黒')));
$WillReturn .= sprintf('白%d,', count(array_keys($pRestList , '白')));
return $WillReturn;
}
function GetHash( array $pBanArr , array $pAlreadyHaitiArr )
{
$WillReturn = '';
for ($X = 0; $X <= UB; $X++) {
for ($Y = 0; $Y <= UB; $Y++) {
$WillReturn .= $pBanArr[$X][$Y];
$WillReturn .= ($pAlreadyHaitiArr[$X][$Y] ? '0' : '1');
}
}
return $WillReturn;
}
function PrintBan( array $pBanArr)
{
for ($Y = 0; $Y <= UB; $Y++) {
for ($X = 0; $X <= UB; $X++) {
echo $pBanArr[$X][$Y];
}
echo PHP_EOL;
}
echo PHP_EOL;
}
解1を発見しました
1手目は [0,0]に白を配置。残りは赤3,青3,黄3,黒3,白3,
白黒白黄
黄赤青黒
白黒白黄
赤青赤青
2手目は [0,1]に青を配置。残りは赤3,青2,黄3,黒3,白3,
白黒白黄
青赤青黒
白黒白黄
赤青赤青
3手目は [1,2]に黄を配置。残りは赤3,青2,黄2,黒3,白3,
白黒白黄
青赤青黒
白黄白黄
赤青赤青
4手目は [2,3]に黒を配置。残りは赤3,青2,黄2,黒2,白3,
白黒白黄
青赤青黒
白黄白黄
赤青黒青
5手目は [0,3]に黒を配置。残りは赤3,青2,黄2,黒1,白3,
白黒白黄
青赤青黒
白黄白黄
黒青黒青
6手目は [1,0]に黄を配置。残りは赤3,青2,黄1,黒1,白3,
白黄白黄
青赤青黒
白黄白黄
黒青黒青
7手目は [1,1]に黒を配置。残りは赤3,青2,黄1,黒0,白3,
白黄白黄
青黒青黒
白黄白黄
黒青黒青
8手目は [2,2]に赤を配置。残りは赤2,青2,黄1,黒0,白3,
白黄白黄
青黒青黒
白黄赤黄
黒青黒青
9手目は [3,3]に白を配置。残りは赤2,青2,黄1,黒0,白2,
白黄白黄
青黒青黒
白黄赤黄
黒青黒白
10手目は [2,0]に赤を配置。残りは赤1,青2,黄1,黒0,白2,
白黄赤黄
青黒青黒
白黄赤黄
黒青黒白
11手目は [2,1]に白を配置。残りは赤1,青2,黄1,黒0,白1,
白黄赤黄
青黒白黒
白黄赤黄
黒青黒白
12手目は [3,2]に青を配置。残りは赤1,青1,黄1,黒0,白1,
白黄赤黄
青黒白黒
白黄赤青
黒青黒白
13手目は [3,0]に青を配置。残りは赤1,青0,黄1,黒0,白1,
白黄赤青
青黒白黒
白黄赤青
黒青黒白
14手目は [3,1]に黄を配置。残りは赤1,青0,黄0,黒0,白1,
白黄赤青
青黒白黄
白黄赤青
黒青黒白
15手目は [0,2]に赤を配置。残りは赤0,青0,黄0,黒0,白1,
白黄赤青
青黒白黄
赤黄赤青
黒青黒白
16手目は [1,3]に白を配置。残りは赤0,青0,黄0,黒0,白0,
白黄赤青
青黒白黄
赤黄赤青
黒白黒白