using System;
using System.Collections.Generic;
class Program
{
const int UB = 3 - 1;
struct JyoutaiDef
{
internal int Level;
internal int[,] BanArr;
}
static void Main()
{
var que = new Queue<JyoutaiDef>();
JyoutaiDef WillEnqueue;
WillEnqueue.Level = 0;
WillEnqueue.BanArr = new int[UB + 1, UB + 1];
Action<int, int, int> SetAct = (pX, pY, pSetVal) =>
WillEnqueue.BanArr[pX, pY] = pSetVal;
SetAct(0, 0, 1); SetAct(1, 0, 2); SetAct(2, 0, 3);
SetAct(0, 1, 4); SetAct(1, 1, 5); SetAct(2, 1, 6);
SetAct(0, 2, 7); SetAct(1, 2, 8); SetAct(2, 2, 9);
que.Enqueue(WillEnqueue);
//訪問済の盤面のHashSet
var VisitedBan = new HashSet<int>();
VisitedBan.Add(BanToInt(WillEnqueue.BanArr));
int AnswerLevel = int.MinValue;
var AnswerBanArrList = new List<int[,]>();
while (que.Count > 0) {
JyoutaiDef Dequeued = que.Dequeue();
if (AnswerLevel < Dequeued.Level) {
AnswerLevel = Dequeued.Level;
AnswerBanArrList.Clear();
}
if (AnswerLevel == Dequeued.Level) {
AnswerBanArrList.Add(Dequeued.BanArr);
}
WillEnqueue.Level = Dequeued.Level + 1;
for (char I = 'a'; I <= 'l'; I++) {
int[,] ChangedBan = DeriveChangedBan(I, Dequeued.BanArr);
//訪問済なら枝切り
if (VisitedBan.Add(BanToInt(ChangedBan)) == false)
continue;
WillEnqueue.BanArr = ChangedBan;
que.Enqueue(WillEnqueue);
}
}
//最長手数な盤面を1つ表示する
Console.WriteLine("最長手数は{0}手で、{1}通り", AnswerLevel, AnswerBanArrList.Count);
Console.WriteLine();
for (int I = 0; I <= 3; I++) {
Console.WriteLine("解{0}は、",I+1);
PrintBan(AnswerBanArrList[I]);
}
}
//選んだ矢印を引数とし、動かした後の盤面を返す
static int[,] DeriveChangedBan(char pArrow, int[,] pBanArr)
{
int[,] ChangedBan = (int[,])pBanArr.Clone();
if (pArrow == 'a' || pArrow == 'b' || pArrow == 'c') {
int X = 0;
if (pArrow == 'a') X = 0;
if (pArrow == 'b') X = 1;
if (pArrow == 'c') X = 2;
ChangedBan[X, 0] = pBanArr[X, 2];
ChangedBan[X, 1] = pBanArr[X, 0];
ChangedBan[X, 2] = pBanArr[X, 1];
}
if (pArrow == 'd' || pArrow == 'e' || pArrow == 'f') {
int Y = 0;
if (pArrow == 'd') Y = 0;
if (pArrow == 'e') Y = 1;
if (pArrow == 'f') Y = 2;
ChangedBan[0, Y] = pBanArr[1, Y];
ChangedBan[1, Y] = pBanArr[2, Y];
ChangedBan[2, Y] = pBanArr[0, Y];
}
if (pArrow == 'g' || pArrow == 'h' || pArrow == 'i') {
int X = 0;
if (pArrow == 'g') X = 2;
if (pArrow == 'h') X = 1;
if (pArrow == 'i') X = 0;
ChangedBan[X, 0] = pBanArr[X, 1];
ChangedBan[X, 1] = pBanArr[X, 2];
ChangedBan[X, 2] = pBanArr[X, 0];
}
if (pArrow == 'j' || pArrow == 'k' || pArrow == 'l') {
int Y = 0;
if (pArrow == 'j') Y = 2;
if (pArrow == 'k') Y = 1;
if (pArrow == 'l') Y = 0;
ChangedBan[0, Y] = pBanArr[2, Y];
ChangedBan[1, Y] = pBanArr[0, Y];
ChangedBan[2, Y] = pBanArr[1, Y];
}
return ChangedBan;
}
//盤面をInt型に変換
static int BanToInt(int[,] pBanArr)
{
int WillReturn = 0;
for (int Y = 0; Y <= UB; Y++) {
for (int X = 0; X <= UB; X++) {
WillReturn *= 10;
WillReturn += pBanArr[X, Y];
}
}
return WillReturn;
}
//盤面を出力
static void PrintBan(int[,] pBanArr)
{
var sb = new System.Text.StringBuilder();
for (int Y = 0; Y <= pBanArr.GetUpperBound(1); Y++) {
for (int X = 0; X <= pBanArr.GetUpperBound(0); X++) {
sb.Append(pBanArr[X, Y]);
}
sb.AppendLine();
}
Console.WriteLine(sb.ToString());
}
}