#include <iostream>
#include <cstdio>
#include <vector>

#define RC2P(r,c) (((r)<<2)+(c))	//r*4+c
#define P2R(p) ((p)>>2)				//p/4
#define P2C(p) ((p)&3)				//p%4
#define HASHMAX 1000003

typedef unsigned long long int Pkey;

int dist(Pkey x, int t);
int abs(int x);

struct Pandt{
	Pkey p;
	int t;
	int w;

	Pandt(){ return; }
	Pandt(Pkey p, int t) :p(p), t(t){
		w = dist(p, t);
		return;
	}

	bool operator==(const Pandt& rhs) const{
		return (p == rhs.p && t == rhs.t);
	}
};

void insert(std::vector<Pandt> &A, Pandt v);
Pandt extract(std::vector<Pandt> &A);
int SolvePuzzle(std::vector<int> P);


std::vector< Pandt > Puzzles(HASHMAX);
std::vector< int > mds(HASHMAX);

int h1(Pkey key){
	return (int)(key % HASHMAX); 
}
int h2(Pkey key){
	return (int)((key % (HASHMAX - 1)) + 1);
}
int HashFind(Pkey key);
int HashInsert(Pkey key, int val);


void InitHash(){
	Pandt Nullpandt(0, -1);
	for (int i = 0; i < HASHMAX; i++){
		Puzzles[i] = Nullpandt;
	}
}

int HashFind(Pkey key){

	int curhash = h1(key);
	int sechash = -1;
	for (int i = 0; i < HASHMAX; i++){
		if (Puzzles[curhash].t == -1){
			return -1;
		}
		else if (Puzzles[curhash].p == key){
			return curhash;
		}
		else{
			if (sechash == -1) sechash = h2(key);
			curhash = (curhash + sechash) % HASHMAX;
		}
	}
	return -1;
}

int HashInsert(Pkey key, int val){

	int curhash = h1(key);
	int sechash = -1;
	for (int i = 0; i < HASHMAX; i++){
		if (Puzzles[curhash].t == -1){
			Puzzles[curhash].t = val;
			Puzzles[curhash].p = key;
			return curhash;
		}
		else{
			if (sechash == -1) sechash = h2(key);
			curhash = (curhash + sechash) % HASHMAX;
		}
	}
	return -1;
}

int dist(Pkey x, int t){
	if (x == 0 && t == 0) return 0;
	int tmp, result = 0;
	for (int i = 0; i < 16; i++){
		tmp = (x & ((Pkey)15 << (i << 2))) >> (i << 2);
		if (tmp == 0) continue;
		result += abs(P2C(tmp - 1) - P2C(i)) + abs(P2R(tmp - 1) - P2R(i));
	}
	return -result - t;
}

int abs(int x){
	return x < 0 ? -x : x;
}

bool comp(Pandt rhs, Pandt lhs){
	return rhs.w == lhs.w ? rhs.t < lhs.t : rhs.w < lhs.w;
}

void insert(std::vector< Pandt > &A, Pandt v){
	int n = A.size();
	A.push_back(v);
	Pandt tmp;
	while (n != 0){
		int i = (n - 1) >> 1;
		if (comp(A[i], A[n])){
			tmp = A[n];
			A[n] = A[i];
			A[i] = tmp;
		}
		n = i;
	}
	return;
}

Pandt extract(std::vector< Pandt > &A){
	int n = A.size() - 1;
	Pandt tmp, res = A[0];
	A[0] = A[n];
	A.pop_back();
	
	for (int i = 0, j; (i << 1) + 1 < n;){
		j = (i << 1) + 1;
		if (j != n - 1 && comp(A[j], A[j + 1])){
			j++;
		}
		if (comp(A[i], A[j])){
			tmp = A[j];
			A[j] = A[i];
			A[i] = tmp;
		}
		i = j;
	}
	return res;
}

Pkey PtoI(std::vector<int> p){
	unsigned long long int keyI = 0;
	for (int i = 0; i < 16; i++){
		keyI += (unsigned long long int)(15 & p[i]) << (i << 2);
	}
	return keyI;
}

void AddToQueue(std::vector<Pandt> &Que, Pkey Qnext, Pandt ext){
	int Qsearch = HashFind(Qnext);
	Pandt Qnextt(Qnext, ext.t + 1);
	if (Qsearch == -1){
		HashInsert(Qnext, ext.t + 1);
		insert(Que, Qnextt);
	}
	else if (Puzzles[Qsearch].t > ext.t + 1){
		insert(Que, Qnextt);
		Puzzles[Qsearch].t = ext.t + 1;
		Puzzles[Qsearch].w = Qnextt.w;
	}
	return;
}

int SolvePuzzle(std::vector<int> P){
	std::vector< Pandt > Que;
	Pkey init = PtoI(P);
	Pandt initt(init, 0);
	insert(Que, initt);
	int answer = 45;
	while (true){
		Pandt ext = extract(Que);
		int Cursor;
		if (ext.p == 0xFEDCBA987654321){
			answer = ext.t;
			break;
		}

		if (-ext.w >= 45) break;

		for (int i = 0; i < 16; i++){
			if ((ext.p & ((Pkey)15 << (i << 2))) == 0){
				Cursor = i;
				break;
			}
		}
		Pkey Qnext;
		Pkey tmp;
		if (Cursor >= 4){
			tmp = (ext.p & ((Pkey)15 << ((Cursor - 4) << 2)));
			Qnext = ext.p & ~tmp | (tmp << 16);
			AddToQueue(Que, Qnext, ext);
		}
		if (Cursor < 12){
			tmp = (ext.p & ((Pkey)15 << ((Cursor + 4) << 2)));
			Qnext = ext.p & ~tmp | (tmp >> 16);
			AddToQueue(Que, Qnext, ext);
		}
		if (P2C(Cursor) != 0){
			tmp = (ext.p & ((Pkey)15 << ((Cursor - 1) << 2)));
			Qnext = ext.p & ~tmp | (tmp << 4);
			AddToQueue(Que, Qnext, ext);
		}
		if (P2C(Cursor) != 3){
			tmp = (ext.p & ((Pkey)15 << ((Cursor + 1) << 2)));
			Qnext = ext.p & ~tmp | (tmp >> 4);
			AddToQueue(Que, Qnext, ext);
		}
	}

	return answer;
}

int main(){

	InitHash();

	int k;
	std::vector<int> P;
	for (int i = 0; i < 16; i++){
		scanf("%d", &k);
		P.push_back(k);
	}
	int n = SolvePuzzle(P);

	printf("%d\n", n);

	return 0;
}


Measured memory_bytes: 30744