using System;
using System.Collections.Generic;
class Program
{
static Dictionary<int, List<char[]>> Use4MenArrListDict =
new Dictionary<int, List<char[]>>();
const int UB = 3;
struct JyoutaiDef
{
internal int Level;
internal List<char[]> CubeHaitiList; //要素数が4の配列のList
}
static void Main()
{
DeriveUse4MenArrListDict();
var stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
WillPush.Level = 1;
foreach (char[] Each4MenArr in Use4MenArrListDict[0]) {
WillPush.CubeHaitiList = new List<char[]>() { Each4MenArr };
stk.Push(WillPush);
}
int AnswerCnt = 0;
while (stk.Count > 0) {
JyoutaiDef Popped = stk.Pop();
//解判定
if (Popped.Level == 5) {
Console.WriteLine("解{0}を発見", ++AnswerCnt);
PrintBan(Popped.CubeHaitiList);
continue;
}
WillPush.Level = Popped.Level + 1;
foreach (char[] Each4MenArr in Use4MenArrListDict[Popped.Level]) {
WillPush.CubeHaitiList = new List<char[]>(Popped.CubeHaitiList) { Each4MenArr };
//枝切り
if (IsValid(WillPush.CubeHaitiList) == false) continue;
stk.Push(WillPush);
}
}
}
//5つの立方体の、使用する4面の候補を求める
static void DeriveUse4MenArrListDict()
{
//この展開図と配列の添字を対応させて、5つの立方体の展開図を定義
// 0
//123
// 4
// 5
var wk6MenArrList = new List<char[]>();
wk6MenArrList.Add(new char[] { '+', '●', '+', '■', '×', '★' });
wk6MenArrList.Add(new char[] { '■', '●', '■', '×', '+', '★' });
wk6MenArrList.Add(new char[] { '×', '+', '×', '■', '●', '★' });
wk6MenArrList.Add(new char[] { '●', '■', '●', '★', '×', '+' });
wk6MenArrList.Add(new char[] { '★', '■', '★', '×', '●', '+' });
for (int I = 0; I <= wk6MenArrList.Count - 1; I++) {
Use4MenArrListDict[I] = DeriveUse4MenArrList(wk6MenArrList[I]);
}
//回転解の除外で1つめのキューブの配置は、24通りではなく3通りとする
Use4MenArrListDict[0].RemoveRange(17, 7);
Use4MenArrListDict[0].RemoveRange(9, 7);
Use4MenArrListDict[0].RemoveRange(1, 7);
}
//1つの立方体の、使用する4面の候補を求める
static List<char[]> DeriveUse4MenArrList(char[] p6MenArr)
{
var WillReturn = new List<char[]>();
Action<int, int> wkAct = (pDelInd1, pDelInd2) =>
{
var wk4MenList = new List<char>(p6MenArr);
//2と5以外の4面を使用する場合は、番号順にならないので入れ替え
if (pDelInd1 == 2 && pDelInd2 == 5) {
char wkChar = wk4MenList[3];
wk4MenList[3] = wk4MenList[4];
wk4MenList[4] = wkChar;
}
wk4MenList.RemoveAt(Math.Max(pDelInd1, pDelInd2));
wk4MenList.RemoveAt(Math.Min(pDelInd1, pDelInd2));
WillReturn.AddRange(DeriveUse4MenArr(wk4MenList.ToArray()));
};
wkAct(0, 4); //0と4以外の4面を使用
wkAct(1, 3); //1と3以外の4面を使用
wkAct(2, 5); //2と5以外の4面を使用
return WillReturn;
}
//使用する4面の組み合わせを求める(8通り)
static List<char[]> DeriveUse4MenArr(char[] p4MenArr)
{
var WillReturn = new List<char[]>();
//正順の4つ
for (int StaPos = 0; StaPos <= UB; StaPos++) {
var WillAddList = new List<char>();
for (int KasanP = 0; KasanP <= UB; KasanP++) {
int TargetPos = StaPos + KasanP;
if (TargetPos > UB) TargetPos -= (UB + 1);
WillAddList.Add(p4MenArr[TargetPos]);
}
WillReturn.Add(WillAddList.ToArray());
}
//逆順の4つ
for (int StaPos = 0; StaPos <= UB; StaPos++) {
var WillAddList = new List<char>();
for (int GenzanP = 0; GenzanP <= UB; GenzanP++) {
int TargetPos = StaPos - GenzanP;
if (TargetPos < 0) TargetPos += (UB + 1);
WillAddList.Add(p4MenArr[TargetPos]);
}
WillReturn.Add(WillAddList.ToArray());
}
return WillReturn;
}
//有効な状態かを返す
static bool IsValid(List<char[]> pCubeHaitiList)
{
for (int I = 0; I <= UB; I++) {
var wkHashSet = new HashSet<char>();
for (int J = 0; J <= pCubeHaitiList.Count - 1; J++) {
if (wkHashSet.Add(pCubeHaitiList[J][I]) == false) return false;
}
}
return true;
}
//盤面を表示
static void PrintBan(List<char[]> pCubeHaitiList)
{
var sb = new System.Text.StringBuilder();
for (int I = 0; I <= UB; I++) {
for (int J = 0; J <= pCubeHaitiList.Count - 1; J++) {
sb.Append(pCubeHaitiList[J][I]);
}
sb.AppendLine();
}
Console.WriteLine(sb.ToString());
}
}