#pragma warning(disable:4786)
#include <algorithm>
#include <cstdio>
#include <set>
#include <utility>
#include <cassert>
#include <ctime>
#include <cstring>
using namespace std;

/*
                item 用来记录一个结点的对应信息
                其中:
                state 表明当前8数码对应的格局比如102345678
                对应:     8 7 6
                5 4 3
                2     1
                由所有数字(0代替空格)反向连接而成
                blank用于记录空格所在的位置上例中为 7
                pre用于记录当前这个状态是由closed表中哪个状态扩展而来的
*/
struct item
{
                int state;
                int blank;
                int pre;
};

const int MAXSTEPS = 500000;
const int MAXCHAR = 100;
char buf[MAXCHAR][MAXCHAR];
//[0, top) 为closed表, [top, end]间为open表
item open[MAXSTEPS];

//读入,将矩阵表示8数码转化为用整数表示
bool read(pair<int,int> &state)
{
                if (!gets(buf[0]))
                                return false;
                if (!gets(buf[1]))
                                return false;
                if (!gets(buf[2]))
                                return false;
                assert(strlen(buf[0]) == 5 && strlen(buf[1]) == 5 && strlen(buf[2]) == 5);
                state.first = 0;
                for (int i = 0, p = 1; i < 3; ++i)
                {
                                for (int j = 0; j < 6; j += 2)
                                {
                                                if (buf[i][j] == ' ')
                                                                state.second = i * 3 + j / 2;
                                                else
                                                                state.first += p * (buf[i][j] - '0');
                                                p *= 10;
                                }
                }
                return true;
}

//将整数表示的8数码转换成矩阵表示输出
void pr(int state)
{
                memset(buf, ' ', sizeof(buf));
                for (int i = 0; i < 3; ++i)
                {
                                for (int j = 0; j < 6; j += 2)
                                {
                                                if (state % 10)
                                                                buf[i][j] = state % 10 + '0';
                                                state /= 10;
                                }
                                buf[i][5] = '\0';
                                puts(buf[i]);
                }
}

//判断空格是否移出矩阵,即当前状态空格是否可以向对应方向移动
inline bool suit(int a, int b)
{
                return (a >= 0 && a < 3 && b >= 0 && b < 3);
}

int steps = 0;//记录需要移动的步数
//递归打印出形成最终8数码的过程
void path(int index)
{
                if (index == 0)
                {
                                pr(open[index].state);
                                puts("");
                                return;
                }
                path(open[index].pre);
                pr(open[index].state);
                puts("");
                ++steps;
}

int main()
{
                unsigned int t1 = clock(), t2;
                freopen("astar.in", "r", stdin);
                freopen("bfs.out", "w", stdout);
                set<int>states;
                char tmp[100];
                int i, x, y, a, b, nx, ny, end, top, next, kase = 0;
                pair<int,int> start, target;
                item head;
                //向四个方向转移需要的偏移量
                const int xtran[4] = {-1, 0, 1, 0};
                const int ytran[4] = {0, 1, 0, -1};
                const int p[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
                
                while (read(start))
                {
                                t2 = clock();
                                printf("Case %d:\n\n", ++kase);
                                gets(tmp);
                                read(target);
                                gets(tmp);
                                open[0].state = start.first;
                                open[0].blank = start.second;
                                open[0].pre     = -1;
                                states.insert(start.first);
                                for (top = 0, end = 1; top < end; ++top)
                                {
                                                assert(top < MAXSTEPS);
                                                //取出顶部元素,与A*算法主要区别没有对所要扩展的元素进行启发式选择
                                                head = open[top];
                                                if (head.state == target.first)
                                                {
                                                                path(top);
                                                                break;
                                                }
                                                x = head.blank / 3;
                                                y = head.blank % 3;
                                                
                                                //对应四个方向是否可以移动
                                                for (i = 0; i < 4; ++i)
                                                {
                                                                nx = x + xtran[i];
                                                                ny = y + ytran[i];
                                                                if (suit(nx, ny))
                                                                {
                                                                                a = head.blank;
                                                                                b = nx * 3 + ny;
                                                                                //整数对应两个十进制数字位调换
                                                                                next = head.state + ((head.state % p[a + 1]) / p[a] - (head.state % p[b + 1]) / p[b]) * p[b]
                                                                                                + ((head.state % p[b + 1]) / p[b] - (head.state % p[a + 1]) / p[a]) * p[a];
                                                                                //判断该状态是否已经扩展过
                                                                                if (states.find(next) == states.end())
                                                                                {
                                                                                                states.insert(next);
                                                                                                open[end].pre     = top;
                                                                                                open[end].blank = b;
                                                                                                open[end].state = next;
                                                                                                ++end;
                                                                                }
                                                                }
                                                }
                                }
                                if (top > end)
                                                printf("No solution\n");
                                else
                                {
                                                printf("Num of steps: %d\n", steps);
                                                printf("Num of expanded: %d\n", top);
                                                printf("Num of generated: %d\n", end);
                                                printf("Time consumed: %u\n\n", clock() - t2);
                                }
                                states.clear();
                                steps = 0;
                }
                printf("Total time consumed: %u\n", clock() - t1);
                return 0;
}