using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
//ダイス番号(1〜8)と、6面の配置候補の配列のList
static Dictionary<int, List<char[]>> Use6MenArrListDict =
new Dictionary<int, List<char[]>>();
struct JyoutaiDef
{
internal int Level;
internal List<int> SetDiceNo; //配置したダイス番号
internal List<char[]> Set6MenArrList; //配置したダイスの展開図のList
}
static void Main()
{
DeriveUse6MenArrListDict();
var stk = new Stack<JyoutaiDef>();
JyoutaiDef WillPush;
WillPush.Level = 0;
WillPush.SetDiceNo = new List<int>();
WillPush.Set6MenArrList = new List<char[]>();
stk.Push(WillPush);
int AnswerCnt = 0;
while (stk.Count > 0) {
JyoutaiDef Popped = stk.Pop();
if (Popped.Level == 8) {
Console.WriteLine("解{0}を発見", ++AnswerCnt);
PrintAnswer(Popped);
continue;
}
WillPush.Level = Popped.Level + 1;
foreach (var EachPair in Use6MenArrListDict) {
//最初に配置するダイスは、固定で1番とする
if (WillPush.Level == 1 && EachPair.Key != 1) continue;
//回転解の除外で
//上段右後のダイス番号 < 上段左前のダイス番号
if (WillPush.Level == 3)
if (Popped.SetDiceNo[1] < EachPair.Key == false)
continue;
if (Popped.SetDiceNo.Contains(EachPair.Key)) continue;
foreach (char[] EachKouhoArr in EachPair.Value) {
WillPush.SetDiceNo = new List<int>(Popped.SetDiceNo) { EachPair.Key };
WillPush.Set6MenArrList = new List<char[]>(Popped.Set6MenArrList);
WillPush.Set6MenArrList.Add(EachKouhoArr);
if (IsValid(WillPush.Set6MenArrList) == false) continue;
stk.Push(WillPush);
}
}
}
}
//8つのダイスの、使用する6面の候補を求める
static void DeriveUse6MenArrListDict()
{
//この展開図と配列の添字を対応させて、8つのダイスの展開図を定義
// 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[] { '黄', '緑', '黒', '青', '白', '赤' });
wk6MenArrList.Add(new char[] { '黒', '白', '緑', '青', '黄', '赤' });
wk6MenArrList.Add(new char[] { '緑', '黒', '白', '青', '赤', '黄' });
wk6MenArrList.Add(new char[] { '黄', '黒', '青', '緑', '赤', '白' });
for (int I = 0; I <= wk6MenArrList.Count - 1; I++) {
Use6MenArrListDict[I + 1] = DeriveUse6MenArrList(wk6MenArrList[I]);
}
}
//1つのダイスの、配置の候補を求める(ダイス1つにつき48通り)
static List<char[]> DeriveUse6MenArrList(char[] p6MenArr)
{
var WillReturn = new List<char[]>();
Action<int, int> wkAct = (pSokumenInd1, pSokumenInd2) =>
{
var wk4MenList = new List<char>(p6MenArr);
//2と5以外の4面を使用する場合は、番号順にならないので入れ替え
if (pSokumenInd1 == 2 && pSokumenInd2 == 5) {
char wkChar = wk4MenList[3];
wk4MenList[3] = wk4MenList[4];
wk4MenList[4] = wkChar;
}
wk4MenList.RemoveAt(Math.Max(pSokumenInd1, pSokumenInd2));
wk4MenList.RemoveAt(Math.Min(pSokumenInd1, pSokumenInd2));
WillReturn.AddRange(DeriveUse4MenArrList(p6MenArr[pSokumenInd1],
p6MenArr[pSokumenInd2], wk4MenList.ToArray()));
};
wkAct(0, 4); //0と4を側面としてダイスを配置
wkAct(1, 3); //1と3を側面としてダイスを配置
wkAct(2, 5); //2と5を側面としてダイスを配置
return WillReturn;
}
//使用する4面の並び順を求める(16通り)
static List<char[]> DeriveUse4MenArrList(char pSokumen1, char pSokumen2, char[] p4MenArr)
{
const int UB = 3;
var WillReturn = new List<char[]>();
//正順と逆順での共通処理
Action<List<char>> CommonAct = pWKList =>
{
char[] WillAddArr = new char[6];
WillAddArr[0] = pWKList[0];
WillAddArr[2] = pWKList[1];
WillAddArr[4] = pWKList[2];
WillAddArr[5] = pWKList[3];
WillAddArr[1] = pSokumen1; WillAddArr[3] = pSokumen2;
WillReturn.Add(WillAddArr);
WillAddArr = (char[])WillAddArr.Clone();
WillAddArr[1] = pSokumen2; WillAddArr[3] = pSokumen1;
WillReturn.Add(WillAddArr);
};
//正順の4つ
for (int StaPos = 0; StaPos <= UB; StaPos++) {
var WKList = new List<char>();
for (int KasanP = 0; KasanP <= UB; KasanP++) {
int TargetPos = StaPos + KasanP;
if (TargetPos > UB) TargetPos -= (UB + 1);
WKList.Add(p4MenArr[TargetPos]);
}
CommonAct(WKList);
}
//逆順の4つ
for (int StaPos = 0; StaPos <= UB; StaPos++) {
var WKList = new List<char>();
for (int GenzanP = 0; GenzanP <= UB; GenzanP++) {
int TargetPos = StaPos - GenzanP;
if (TargetPos < 0) TargetPos += (UB + 1);
WKList.Add(p4MenArr[TargetPos]);
}
CommonAct(WKList);
}
return WillReturn;
}
//上段左後 上段右後
//上段左前 上段右前
//下段左後 下段右後
//下段左前 下段右前
//の順番でダイスを配置するので、有効な状態かをチェックする
static bool IsValid(List<char[]> pSet6MenArrList)
{
//上段右後の配置
if (pSet6MenArrList.Count == 2) {
//後面 = 上段左後のダイスの後面
if (pSet6MenArrList[1][0] != pSet6MenArrList[0][0]) return false;
//左面 = 上段左後のダイスの右面
if (pSet6MenArrList[1][1] != pSet6MenArrList[0][3]) return false;
//上面 = 上段左後のダイスの上面
if (pSet6MenArrList[1][5] != pSet6MenArrList[0][5]) return false;
}
//上段左前の配置
if (pSet6MenArrList.Count == 3) {
//後面 = 上段左後のダイスの前面
if (pSet6MenArrList[2][0] != pSet6MenArrList[0][4]) return false;
//左面 = 上段左後のダイスの左面
if (pSet6MenArrList[2][1] != pSet6MenArrList[0][1]) return false;
//上面 = 上段左後のダイスの上面
if (pSet6MenArrList[2][5] != pSet6MenArrList[0][5]) return false;
}
//上段右前の配置
if (pSet6MenArrList.Count == 4) {
//後面 = 上段右後のダイスの前面
if (pSet6MenArrList[3][0] != pSet6MenArrList[1][4]) return false;
//左面 = 上段左前のダイスの右面
if (pSet6MenArrList[3][1] != pSet6MenArrList[2][3]) return false;
//右面 = 上段右後のダイスの右面
if (pSet6MenArrList[3][3] != pSet6MenArrList[1][3]) return false;
//前面 = 上段左前のダイスの前面
if (pSet6MenArrList[3][4] != pSet6MenArrList[2][4]) return false;
//上面 = 上段左後のダイスの上面
if (pSet6MenArrList[3][5] != pSet6MenArrList[0][5]) return false;
}
//下段左後の配置
if (pSet6MenArrList.Count == 5) {
//後面 = 上段左後のダイスの後面
if (pSet6MenArrList[4][0] != pSet6MenArrList[0][0]) return false;
//左面 = 上段左後のダイスの左面
if (pSet6MenArrList[4][1] != pSet6MenArrList[0][1]) return false;
//上面 = 上段左後のダイスの下面
if (pSet6MenArrList[4][5] != pSet6MenArrList[0][2]) return false;
}
//下段右後の配置
if (pSet6MenArrList.Count == 6) {
//後面 = 上段左後のダイスの後面
if (pSet6MenArrList[5][0] != pSet6MenArrList[0][0]) return false;
//左面 = 下段左後のダイスの右面
if (pSet6MenArrList[5][1] != pSet6MenArrList[4][3]) return false;
//下面 = 下段左後のダイスの下面
if (pSet6MenArrList[5][2] != pSet6MenArrList[4][2]) return false;
//右面 = 上段右後のダイスの右面
if (pSet6MenArrList[5][3] != pSet6MenArrList[1][3]) return false;
//上面 = 上段右後のダイスの下面
if (pSet6MenArrList[5][5] != pSet6MenArrList[1][2]) return false;
}
//下段左前の配置
if (pSet6MenArrList.Count == 7) {
//後面 = 下段左後のダイスの前面
if (pSet6MenArrList[6][0] != pSet6MenArrList[4][4]) return false;
//左面 = 上段左後のダイスの左面
if (pSet6MenArrList[6][1] != pSet6MenArrList[0][1]) return false;
//下面 = 下段左後のダイスの下面
if (pSet6MenArrList[6][2] != pSet6MenArrList[4][2]) return false;
//前面 = 上段左前のダイスの前面
if (pSet6MenArrList[6][4] != pSet6MenArrList[2][4]) return false;
//上面 = 上段左前のダイスの下面
if (pSet6MenArrList[6][5] != pSet6MenArrList[2][2]) return false;
}
//下段右前の配置
if (pSet6MenArrList.Count == 8) {
//後面 = 下段右後のダイスの前面
if (pSet6MenArrList[7][0] != pSet6MenArrList[5][4]) return false;
//左面 = 下段左前のダイスの右面
if (pSet6MenArrList[7][1] != pSet6MenArrList[6][3]) return false;
//下面 = 下段左後のダイスの下面
if (pSet6MenArrList[7][2] != pSet6MenArrList[4][2]) return false;
//右面 = 上段右後のダイスの右面
if (pSet6MenArrList[7][3] != pSet6MenArrList[1][3]) return false;
//前面 = 上段左前のダイスの前面
if (pSet6MenArrList[7][4] != pSet6MenArrList[2][4]) return false;
//上面 = 上段右前のダイスの下面
if (pSet6MenArrList[7][5] != pSet6MenArrList[3][2]) return false;
}
return true;
}
//配置したダイスを展開図で表示する
//上段左後 上段右後
//上段左前 上段右前
//下段左後 下段右後
//下段左前 下段右前
//の順番で展開図を表示する
static void PrintAnswer(JyoutaiDef pJyoutaiDef)
{
Action<int> PrintPairTenkaizu = pBaseSoeji =>
{
var sb = new System.Text.StringBuilder();
sb.AppendFormat("Dice{0} Dice{1}",
pJyoutaiDef.SetDiceNo[pBaseSoeji], pJyoutaiDef.SetDiceNo[pBaseSoeji + 1]);
sb.AppendLine();
Action<int> CommonSyori = (pTargetMen) =>
{
sb.AppendFormat(" {0} {1}",
pJyoutaiDef.Set6MenArrList[pBaseSoeji][pTargetMen],
pJyoutaiDef.Set6MenArrList[pBaseSoeji + 1][pTargetMen]);
sb.AppendLine();
};
CommonSyori(0);
sb.AppendFormat("{0}{1}{2} {3}{4}{5}",
pJyoutaiDef.Set6MenArrList[pBaseSoeji][1],
pJyoutaiDef.Set6MenArrList[pBaseSoeji][2],
pJyoutaiDef.Set6MenArrList[pBaseSoeji][3],
pJyoutaiDef.Set6MenArrList[pBaseSoeji + 1][1],
pJyoutaiDef.Set6MenArrList[pBaseSoeji + 1][2],
pJyoutaiDef.Set6MenArrList[pBaseSoeji + 1][3]);
sb.AppendLine();
CommonSyori(4);
CommonSyori(5);
Console.WriteLine(sb.ToString());
};
for (int I = 0; I <= pJyoutaiDef.SetDiceNo.Count - 1; I+=2) {
if (I == 0) Console.WriteLine("上段左後と上段右後の展開図");
if (I == 2) Console.WriteLine("上段左前と上段右前の展開図");
if (I == 4) Console.WriteLine("下段左後と下段右後の展開図");
if (I == 6) Console.WriteLine("下段左前と下段右前の展開図");
PrintPairTenkaizu(I);
}
}
}