#include <cstdio>
#include <algorithm>
#include <cassert>
#include <cstring>
using namespace std;

struct Board {
	char state[4][8];
	Board(){}
};

bool operator< (const Board& lhs, const Board& rhs) {
	return memcmp(&lhs.state, &rhs.state, sizeof(lhs.state)) < 0;
}

typedef pair<int, Board> heap_t;

struct HeapNode {
	heap_t value;
	HeapNode *left, *right, *parent;

	HeapNode(){}
	HeapNode(heap_t value, HeapNode *left, HeapNode *right, HeapNode *parent):
		value(value), left(left), right(right), parent(parent)
	{}

};

const int MAX_HEAP = 1<<18;
HeapNode nodes__[MAX_HEAP];
int freeNodeStack__[MAX_HEAP], *lastStack__;

void initHeap(int n = MAX_HEAP) {
	for (int i = 0; i < n; ++i) {
		freeNodeStack__[i] = n - 1 - i;
	}
	lastStack__ = freeNodeStack__ + n;
}

inline bool cmpHeap(const heap_t& lhs, const heap_t& rhs) {
	return lhs < rhs;
}


HeapNode *allocateHeap() {
	return &nodes__[*--lastStack__];
}

void freeHeap(HeapNode *x) {
	if (x) {
		*lastStack__ = (int)(x - nodes__);
		++lastStack__;
	}
}

inline bool isRoot(HeapNode *a) {
	return !(a->parent || a->right);
}

inline bool isLeft(HeapNode *x) {
	//assert(x && x->parent);
	return x->parent->left == x;
}

heap_t getMinimum(HeapNode *a) {
	//assert(a);
	return a->value;
}

HeapNode *makeHeap(heap_t value) {
	HeapNode *ret = allocateHeap();
	*ret = HeapNode(value, 0, 0, 0);
	return ret;
}

HeapNode *meld(HeapNode *a, HeapNode *b) {
	if (!(a && b)) {
		return a ? a : b;
	}

	if (!cmpHeap(a->value, b->value)) {
		swap(a, b);
	}

	if (a->left) {
		a->left->parent = b;
		b->right = a->left;
	}
	a->left = b;
	b->parent = a;
	return a;
}

HeapNode *insert(HeapNode *a, const heap_t& value) {
	return meld(a, makeHeap(value));
}

HeapNode *meldPair(HeapNode *a) {
	if (!(a && a->right)) {
		return a;
	}
	HeapNode *nxt = a->right;
	HeapNode *nxtNxt = nxt->right;
	if (nxtNxt) {
		nxtNxt->parent = 0;
	}
	a->right = nxt->right = nxt->parent = 0;
	return meld( meld(a, nxt), meldPair(nxtNxt) );
}

HeapNode *eraseMinimum(HeapNode *a) {
	if (!(a && a->left)) {
		return 0;
	}
	a->left->parent = 0;
	return meldPair(a->left);
}

void eraseSubHeap__(HeapNode *x) {
	//assert(x && x->parent);
	if (isLeft(x)) {
		x->parent->left = x->right;
	}
	else {
		x->parent->right = x->right;
	}

	if (x->right) {
		x->right->parent = x->parent;
	}
	x->parent = x->right = 0;
}

HeapNode *decreaseKey(HeapNode *a, HeapNode *x, const heap_t& newValue) {
	//assert(a && isRoot(x));
	if (!(x && cmpHeap(newValue, x->value))) {
		return a;
	}
	x->value = newValue;
	if (a == x) {
		return x;
	}
	if (isLeft(x) && cmpHeap(x->parent->value, x->value)) {
		return a;
	}

	eraseSubHeap__(x);
	return meld(a, x);
}

HeapNode *erase(HeapNode *a, HeapNode *x) {
	//assert(a);
	if (!x) {
		return a;
	}
	if (a == x) {
		return eraseMinimum(a);
	}

	eraseSubHeap__(x);
	x->parent = x->right = 0;
	return meld(a, eraseMinimum(x));
}

HeapNode *changeKey(HeapNode *a, HeapNode *x, const heap_t& newValue) {
	if (x && !cmpHeap(x->value, newValue)) {
		return decreaseKey(a, x, newValue);
	}
	a = erase(a, x);
	x->value = newValue;
	x->left = x->right = x->parent = 0;
	return meld(a, x);
}



struct Heap {
	HeapNode *root;
	int size__;

	Heap():root(0), size__(0) {}

	bool isEmpty() {
		return !root;
	}

	int size() {
		return size__;
	}

	void clear() {
		size__ = 0;
		if (!root) {
			return ;
		}
		HeapNode *tmp = root;
		root = tmp->right;
		clear();
		root = tmp->left;
		clear();
		root = 0;
		freeHeap(tmp);
	}

	HeapNode *push(const heap_t& value) {
		++size__;
		HeapNode *ret = makeHeap(value);
		root = meld(root, ret);
		return ret;
	}

	heap_t top() {
		return getMinimum(root);
	}

	void erase(HeapNode *x) {
		--size__;
		root = ::erase(root, x);
	}

	void pop() {
		--size__;
		HeapNode *tmp = root;
		root = eraseMinimum(root);
		freeHeap(tmp);
	}

	void decreaseKey(HeapNode *x, const heap_t& newValue) {
		root = ::decreaseKey(root, x, newValue);
	}

	void changeKey(HeapNode *x, const heap_t& newValue) {
		root = ::changeKey(root, x, newValue);
	}
};


typedef unsigned long long hash_t;
//typedef Board key_t;
#define key_t Board
typedef int value_t;

struct HashMap {
	static const int TABLE_SIZE = 1<<18;
	hash_t hashes[TABLE_SIZE];
	value_t values[TABLE_SIZE];

	HashMap()
	{
		memset(hashes, ~0, sizeof(hashes));
	}

	void clear() {
		memset(hashes, ~0, sizeof(hashes));
	}

	inline hash_t hasher(const key_t &x) const {
		hash_t ret = 0;
		for (int i = 0; i < 4; ++i) {
			//ret = ret * 1000007ULL + ((hash_t*)x.state[i])[0];
			for (int j = 0; j < 8; ++j) {
				ret = ret * 10000007ULL + hash_t(x.state[i][j] + 1);
			}
		}
		if (ret == ~0ULL) {
			ret = 538;
		}
		return ret;
	}

	void set (const key_t &x, const value_t &v) {
		const hash_t hash = hasher(x);
		int sub = hash % TABLE_SIZE;
		
		for (;hashes[sub] != hash && ~hashes[sub]; sub = (sub + 1 == TABLE_SIZE ? 0 : sub + 1)) ;
		hashes[sub] = hash;
		values[sub] = v;
	}

	value_t get (const key_t &x) const {
		const hash_t hash = hasher(x);
		int sub = hash % TABLE_SIZE;
		
		for (;hashes[sub] != hash && ~hashes[sub]; sub = (sub + 1 == TABLE_SIZE ? 0 : sub + 1)) ;
		return values[sub];
	}


	bool containKey(const key_t &x) const {
		const hash_t hash = hasher(x);
		int sub = hash % TABLE_SIZE;
		
		for (;hashes[sub] != hash && ~hashes[sub]; sub = (sub + 1 == TABLE_SIZE ? 0 : sub + 1)) ;
		return hashes[sub] == hash;
	}
};



int board[4][8];

void init() {
	memset(board, 0, sizeof(board));
	for (int i = 0; i < 4; ++i) {
		for (int j = 0; j < 7; ++j) {
			scanf("%d", board[i]+j+1);
		}
	}
}

int estimateBoard(const Board& x) {
	int ans = 0;
	for (int i = 0; i < 4; ++i) {
		for (int j = 0; j < 8; ++j) if (x.state[i][j] != -1) {
			if (!((x.state[i][j]>>3) == i && (x.state[i][j]&7) == j)) {
				++ans;
			}
		}
	}
	return ans ? 1 : 0;
}



int solve() {
	static HashMap estimate;
	estimate.clear();
	Heap que;
	initHeap();

	Board start;
	memset(&start.state, ~0, 4*8);
	for (int i = 0; i < 4; ++i) {
		for (int j = 1; j < 8; ++j) {
			if (board[i][j]) {
				start.state[i][j] = ((board[i][j]/10 - 1)<<3) | (board[i][j]%10 - 1);
			}
			if ((start.state[i][j]&7) == 0) {
				swap(start.state[start.state[i][j]>>3][0], start.state[i][j]);
			}
		}
	}
	estimate.set(start, estimateBoard(start));
	que.push(make_pair(estimate.get(start), start));


	for (;!que.isEmpty();) {
		int dist = que.root->value.first;
		Board cur = que.root->value.second;
		que.pop();

		int esti = estimate.get(cur);
		if (esti == 0) {
			return dist;
		}
		dist -= esti;

		for (int i = 0; i < 4; ++i) {
			for (int j = 1; j < 8; ++j) if (cur.state[i][j] == -1) {
				char left = cur.state[i][j-1] + 1;
				for (int ii = 0; ii < 4; ++ii) {
					for (int jj = 1; jj < 8; ++jj) if (cur.state[ii][jj] == left) {
						swap(cur.state[ii][jj], cur.state[i][j]);
						if (!estimate.containKey(cur)) {
							const int add = estimateBoard(cur);
							estimate.set(cur, add);
							int nd = dist + 1 + add;
							que.push(make_pair(nd, cur));
						}
						swap(cur.state[ii][jj], cur.state[i][j]);
					}
				}
			}
		}
	}

	return -1;
}

int main() {
	int T; scanf("%d", &T);
	for (int _ = 0; _ < T; ++_) {
		init();
		printf("%d\n", solve());
	}
	return 0;
}