package cn.edu.hpu.hdu;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner;
public class Hdu3095_20130707_2006 {
private static Map<String,Integer> smap = new HashMap<String,Integer>(); //存储从初始状态搜索所到达的状态
private static Map<String, Integer> emap = new HashMap<String, Integer>();//存储从目的状态搜索所到达的状态
private static Status sStatus = null; //初始状态
private static Status eStatus = null;//目的状态
private static int [][] dirs = new int[][]{{1,0},{-1,0},{0,-1},{0,1}}; //方向
private static Queue<Status> sq = new ArrayDeque<Status>();
private static Queue<Status> eq = new ArrayDeque<Status>();
private final static Integer maxLevel = 10;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int cases = in.nextInt();
while(cases-->0){
inputData(in);
if(eStatus.getStatus().equals(sStatus.getStatus())){ //如果初始状态等于目的状态,输出0
System.out.println(0);
}else{
emap.put(eStatus.getStatus(), 0);
smap.put(sStatus.getStatus(), 0);
int step = doublcBFS(sq,eq);
if(step == -1 || step > 20){
System.out.println("No solution!");
}else{
System.out.println(step);
}
}
}
}
/**
* 输入数据
* @param in
*/
private static void inputData(Scanner in){
initResourse();
int value = 0;
sStatus.map[1][3] = in.nextInt();
eStatus.map[1][3] = value++;
for(int i = 2; i <= 4; ++i){
sStatus.map[2][i] = in.nextInt();
eStatus.map[2][i] = value++;
}
for(int i = 1; i <= 5; ++i){
sStatus.map[3][i] = in.nextInt();
eStatus.map[3][i] = value++;
}
for(int i = 2; i <= 4; ++i){
sStatus.map[4][i] = in.nextInt();
eStatus.map[4][i] = value++;
}
sStatus.map[5][3] = in.nextInt();
eStatus.map[5][3] = 0;
smap.clear();
emap.clear();
sStatus.initPoint();
eStatus.initPoint();
sq.clear();
eq.clear();
sq.add(sStatus);
eq.add(eStatus);
}
/**
* 初始化数据
*/
private static void initResourse(){
sStatus = new Status();
eStatus = new Status();
for(int i = 0;i < sStatus.map.length; ++i){
Arrays.fill(sStatus.map[i], -1);
Arrays.fill(eStatus.map[i], -1);
}
}
/**
* 双向搜索函数
* @param sq 初始状态搜索所需要的队列
* @param eq 目的状态搜索所需要的队列
* @return 初始状态到达目的状态所需要的最小步数,如果在maxLevel数值之内没有结果,则返回-1
*/
private static int doublcBFS(Queue<Status> sq, Queue<Status> eq){
int x, y;
while(!sq.isEmpty()||!eq.isEmpty()){
if(!sq.isEmpty()){ //初始状态搜索
Status s = sq.poll();
for(int i = 0; i < s.points.size(); ++i ){
Point p = s.points.get(i);
for(int j = 0; j < dirs.length; ++j){
x = p.x + dirs[j][0];
y = p.y + dirs[j][1];
if(s.map[x][y] == -1 || s.map[x][y] == 0){
continue;
}
int [][] ms = copyArray(s.map);
ms[p.x][p.y] = ms[x][y];
ms[x][y] = 0;
Status status = new Status();
status.map = ms;
status.points.add(new Point(x,y));
status.points.add(s.points.get((i+1)%2).copyPoint());
status.level = s.level + 1;
String ss = status.getStatus();
if(emap.containsKey(ss)){ //如果与目的状态搜索到的状态相遇,刚返回步数
return emap.get(ss) + status.level;
}
if(!smap.containsKey(ss) && s.level <= maxLevel){
smap.put(ss, status.level);
sq.add(status);
}
}
}
}
if(!eq.isEmpty()){ //目的状态搜索
Status s = eq.poll();
for(int i = 0; i < s.points.size(); ++i ){
Point p = s.points.get(i);
for(int j = 0; j < dirs.length; ++j){
x = p.x + dirs[j][0];
y = p.y + dirs[j][1];
if(s.map[x][y] == -1 || s.map[x][y] == 0){
continue;
}
int [][] ms = copyArray(s.map);
ms[p.x][p.y] = ms[x][y];
ms[x][y] = 0;
Status status = new Status();
status.map = ms;
status.points.add(new Point(x,y));
status.points.add(s.points.get((i+1)%2).copyPoint());
status.level = s.level + 1;
String ss = status.getStatus();
if(smap.containsKey(ss)){//如果与初始状态搜索到的状态相遇,刚返回步数
return smap.get(ss) + status.level;
}
if(!emap.containsKey(ss) && s.level <= maxLevel){
emap.put(ss, status.level);
eq.add(status);
}
}
}
}
}
return -1;
}
/**
* 打印一个二维数组
* @param map
*/
private static void show(int [][] map){
StringBuilder sb = new StringBuilder();
for(int i = 1; i < map.length - 1; ++i){
for(int j = 1; j < map[i].length - 1; ++j){
if(map[i][j] == -1){
sb.append(' ');
}else{
sb.append(map[i][j]);
}
}
sb.append('\n');
}
System.out.println(sb.toString());
}
/**
* 拷贝一个二维数组
* @param map
* @return
*/
private static int[][] copyArray(int [][] map){
int [][] m = new int[map.length][map[0].length];
for(int i = 0; i < map.length; ++i){
System.arraycopy(map[i],0,m[i],0,map[i].length);
}
return m;
}
}
/**
* 存储状态
* @author Administrator
*
*/
class Status{
final static int N = 7;
int [][] map; //当前地图
List<Point> points; //当前0点坐标
int level = 0; //到达当前状态所需步数
public Status(){
map = new int[N][N];
points = new ArrayList<Point>();
level = 0;
}
public Status(int [][] map, List<Point> points, int level){
this.map = map;
this.points = points;
this.level = level;
}
public void initPoint(){
for(int i = 1; i < map.length -1; ++i){
for(int j = 1; j < map[i].length - 1; ++j){
if(map[i][j] == 0){
points.add(new Point(i,j));
}
}
}
}
/**
* 返回一个可唯一标识当前状态的字符串
* @return
*/
public String getStatus(){
StringBuilder sb = new StringBuilder();
for(int i = 1; i < map.length -1; ++i){
for(int j = 1; j < map[i].length -1; ++j){
if(map[i][j] != -1){
sb.append(map[i][j]);
sb.append(',');
}
}
}
return sb.toString();
}
}
/**
* 坐标
* @author Administrator
*
*/
class Point{
int x;
int y;
public Point(){
}
public Point(int x, int y){
this.x = x;
this.y = y;
}
/**
* 拷贝一个坐标
* @return
*/
public Point copyPoint(){
Point p = new Point();
p.x = x;
p.y = y;
return p;
}
}