using System;
using System.Collections.Generic;
class Program
{
const int Haba = 4;
static void Main()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
//var CombiList = new List<bool[,]>() {new bool[,] {{true,true,false,false},
// {true,false,true,true},
// {true,true,true,false},
// {true, false, false,true}}};
List<bool[,]> CombiList = DeriveCombiList();
RemoveLittleCnt(CombiList);
int AnswerCnt = 0;
var AnswerArrList = new List<bool[,]>();
foreach (var AnyBoolArr in CombiList) {
//横方向のコインを数える
Func<int, int> CntYokoCoin = pY =>
{
int WillReturn = 0;
for (int X = 0; X <= Haba - 1; X++)
if (AnyBoolArr[X, pY]) WillReturn++;
return WillReturn;
};
//縦方向のコインを数える
Func<int, int> CntTateCoin = pX =>
{
int WillReturn = 0;
for (int Y = 0; Y <= Haba - 1; Y++)
if (AnyBoolArr[pX, Y]) WillReturn++;
return WillReturn;
};
//右上方向のコインを数える
Func<int, int, int> CntMigiueCoin = (pX, pY) =>
{
int WillReturn = 0;
for (int X = pX, Y = pY; X <= Haba - 1 && 0 <= Y; X++, Y--)
if (AnyBoolArr[X, Y]) WillReturn++;
return WillReturn;
};
//左上方向のコインを数える
Func<int, int, int> CntHidariueCoin = (pX, pY) =>
{
int WillReturn = 0;
for (int X = pX, Y = pY; 0 <= X && 0 <= Y; X--, Y--)
if (AnyBoolArr[X, Y]) WillReturn++;
return WillReturn;
};
int EvenLineCnt = 0;
Action<int> EvenHyouka = (pTarget) =>
{
//問題文から0は偶数として扱わない
if (pTarget % 2 == 0 && pTarget > 0) EvenLineCnt++;
};
for (int I = 0; I <= Haba - 1; I++) {
EvenHyouka(CntYokoCoin(I));
EvenHyouka(CntTateCoin(I));
}
EvenHyouka(CntMigiueCoin(0, 1));
EvenHyouka(CntMigiueCoin(0, 2));
EvenHyouka(CntMigiueCoin(0, 3));
EvenHyouka(CntMigiueCoin(1, 3));
EvenHyouka(CntMigiueCoin(2, 3));
EvenHyouka(CntHidariueCoin(3, 1));
EvenHyouka(CntHidariueCoin(3, 2));
EvenHyouka(CntHidariueCoin(3, 3));
EvenHyouka(CntHidariueCoin(2, 3));
EvenHyouka(CntHidariueCoin(1, 3));
if (AnswerCnt > EvenLineCnt) continue;
AnswerCnt = EvenLineCnt;
AnswerArrList.Clear();
Console.WriteLine("偶数となるラインが{0}本の配置を発見。", EvenLineCnt);
AnswerArrList.Add(AnyBoolArr);
}
RemoveKaiten(AnswerArrList);
foreach (var AnyBoolArr in AnswerArrList)
PrintJyoutai(AnyBoolArr);
}
struct JyoutaiDef
{
internal int CurrX;
internal int CurrY;
internal bool[,] HaitiArr;
}
//2の16乗通りの組み合わせを求める
static List<bool[,]> DeriveCombiList()
{
var WillReturnList = new List<bool[,]>();
var stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
WillPush.CurrX = WillPush.CurrY = 0;
WillPush.HaitiArr = new bool[Haba, Haba];
stk.Push(WillPush);
WillPush.HaitiArr = new bool[Haba, Haba];
WillPush.HaitiArr[0, 0] = true;
stk.Push(WillPush);
while (stk.Count > 0) {
JyoutaiDef Popped = stk.Pop();
WillPush.CurrX = Popped.CurrX;
WillPush.CurrY = Popped.CurrY;
if (++WillPush.CurrX > WillPush.HaitiArr.GetUpperBound(0)) {
WillPush.CurrX = 0;
WillPush.CurrY++;
}
if (WillPush.CurrY > WillPush.HaitiArr.GetUpperBound(1)) {
WillReturnList.Add(Popped.HaitiArr);
continue;
}
WillPush.HaitiArr = Popped.HaitiArr;
stk.Push(WillPush);
WillPush.HaitiArr = (bool[,])Popped.HaitiArr.Clone();
WillPush.HaitiArr[WillPush.CurrX, WillPush.CurrY] = true;
stk.Push(WillPush);
}
return WillReturnList;
}
//0個,1個,2個は除外
static void RemoveLittleCnt(List<bool[,]> pTargetList)
{
for (int I = pTargetList.Count - 1; I >= 0; I--) {
int CoinCnt = 0;
for (int X = 0; X <= Haba - 1; X++) {
for (int Y = 0; Y <= Haba - 1; Y++) {
if (pTargetList[I][X, Y]) CoinCnt++;
}
}
if (CoinCnt <= 2) pTargetList.RemoveAt(I);
}
}
//回転を除外
static void RemoveKaiten(List<bool[,]> pTargetList)
{
const int UB = Haba - 1;
Predicate<int> IsExist = (pCurrInd) =>
{
for (int I = 0; I <= pCurrInd - 1; I++) {
bool IsOK1 = false, IsOK2 = false, IsOK3 = false, IsOK4 = false;
bool IsOK5 = false, IsOK6 = false, IsOK7 = false; //回転1から7
for (int X = 0; X <= UB; X++) {
for (int Y = 0; Y <= UB; Y++) {
bool CurrVal = pTargetList[pCurrInd][X, Y];
if (pTargetList[I][UB - X, Y] != CurrVal) IsOK1 = true;
if (pTargetList[I][UB - X, UB - Y] != CurrVal) IsOK2 = true;
if (pTargetList[I][X, UB - Y] != CurrVal) IsOK3 = true;
if (pTargetList[I][Y, X] != CurrVal) IsOK4 = true;
if (pTargetList[I][UB - Y, X] != CurrVal) IsOK5 = true;
if (pTargetList[I][UB - Y, UB - X] != CurrVal) IsOK6 = true;
if (pTargetList[I][Y, UB - X] != CurrVal) IsOK7 = true;
}
}
if (IsOK1 == false || IsOK2 == false || IsOK3 == false || IsOK4 == false
|| IsOK5 == false || IsOK6 == false || IsOK7 == false)
return true;
}
return false;
};
for (int I = pTargetList.Count - 1; I >= 0; I--) {
if (IsExist(I)) pTargetList.RemoveAt(I);
}
}
//盤面を表示
static void PrintJyoutai(bool[,] pHaitiArr)
{
for (int Y = 0; Y <= Haba - 1; Y++) {
for (int X = 0; X <= Haba - 1; X++) {
Console.Write(pHaitiArr[X, Y] ? '●' : '□');
}
Console.WriteLine();
}
}
}