#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
//typedef unsigned long long int ull;
#define ull unsigned long long int
#define ll int
#define pll pair<int,int>
//typedef int ll;
//typedef pair<ll,ll> pll;
#define F first
#define S second
/*
typedef pair<int,int> pi;
typedef pair<double,double> pd;
typedef pair<double,ll> pdl;

const ll E=1e18+7;
const ll MOD=1000000007;
*/

//const ll R=4;

#define R 4



inline ull Hash(vector<vector<ll>> &A){
    ull ret=0;
    for(int i=0;i<R;i++){
        for(int t=0;t<R;t++){
            ret+=A[i][t];
            if(i+1!=R || t+1!=R){
                ret*=16;
            }
        }
    }
    return ret;
}

vector<pll> where={{3,3},{0,0},{0,1},{0,2},{0,3},{1,0},{1,1},{1,2},{1,3},{2,0},{2,1},{2,2},{2,3},{3,0},{3,1},{3,2}};
vector<vector<ll>> ans={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,0}};


inline ll dist(vector<vector<ll>> &A){
    ll ret=0;
    for(int i=0;i<R;i++){
        for(int t=0;t<R;t++){
            ret+=abs(where[A[i][t]].F-i)+abs(where[A[i][t]].S-t);
        }
    }
    return ret;
}

//const ll mx=19;

#define mx 20

inline vector<vector<ll>> Rhash(ull hash){
    vector<vector<ll>> ret(R,vector<ll>(R));
    for(int i=R-1;i>=0;i--){
        for(int t=R-1;t>=0;t--){
            ret[i][t]=hash%16;
            hash/=16;
        }
    }
    return ret;
}

inline void Rhash(ull hash,vector<vector<ll>> &ret){
    for(int i=R-1;i>=0;i--){
        for(int t=R-1;t>=0;t--){
            ret[i][t]=hash%16;
            hash/=16;
        }
    }
}

vector<ll> dx={0,1,0,-1};
vector<ll> dy={1,0,-1,0};

map<ull,ll> M;

struct PZL{
    ll D;
    ull hash;
    ll h,w;
    ll d;
    
    inline bool operator < (const PZL &P) const {
        return D>P.D || (D==P.D && d>P.d);
    }
};

struct PZL2{
    ull hash;
    ll h,w;
    ll d;
};



void bfs(vector<vector<ll>> A){
    queue<PZL2> Q;
    Q.push({Hash(A),3,3,0});
    M[Hash(A)]=0;
    PZL2 W,N;
    while(!Q.empty()){
        W=Q.front(); Q.pop();
        Rhash(W.hash,A);
        for(int i=0;i<4;i++){
            ll x=W.h+dx[i];
            ll y=W.w+dy[i];
            if(x<0 || y<0 || x>=R || y>=R){continue;}
            N=W;
            swap(A[x][y],A[W.h][W.w]);
            N.hash=Hash(A);
            if(M.count(N.hash)){swap(A[x][y],A[W.h][W.w]); continue;}
            N.h=x;
            N.w=y;
            M[N.hash]=++N.d;
            if(N.d>=mx){return;}
            Q.push(N);
            swap(A[x][y],A[W.h][W.w]);
        }
    }
}

ll dfs(vector<vector<ll>> A,ll h,ll w){
    if(A==ans){return 0;}
    priority_queue<PZL> S;
    set<ull> done;
    ull hash=Hash(A);
    if(M.count(hash)){return M[hash];}
    S.push({dist(A),hash,h,w,0});
    done.insert(hash);
    PZL N,W;
    while(!S.empty()){
        W=S.top();
        S.pop();
        Rhash(W.hash,A);
        W.d++;
        W.D+=2;
        W.D-=abs(where[A[W.h][W.w]].F-W.h)+abs(where[A[W.h][W.w]].S-W.w);
        for(int i=0;i<4;i++){
            ll x=W.h+dx[i];
            ll y=W.w+dy[i];
            if(x<0 || y<0 || x>=R || y>=R){continue;}
            N=W;
            N.D-=abs(where[A[x][y]].F-x)+abs(where[A[x][y]].S-y);
            swap(A[x][y],A[W.h][W.w]);
            N.D+=abs(where[A[x][y]].F-x)+abs(where[A[x][y]].S-y);
            N.D+=abs(where[A[W.h][W.w]].F-W.h)+abs(where[A[W.h][W.w]].S-W.w);
            if(N.D>90){swap(A[x][y],A[W.h][W.w]); continue;}
            N.hash=hash=Hash(A);
            if(N.D-N.d*2<=mx*2 && M.count(N.hash)){return N.d+M[N.hash];}
            swap(A[x][y],A[W.h][W.w]);
            if(done.count(hash)){continue;}
            done.insert(hash);
            N.h=x;
            N.w=y;
            S.push(N);
        }
    }
    return -1;
}



int main(){
    bfs(ans);
    vector<vector<ll>> a(4,vector<ll>(4,0));
    ll h,w;
    for(int i=0;i<R;i++){
        for(int t=0;t<R;t++){
            cin>>a[i][t];
            if(a[i][t]==0){h=i; w=t;}
        }
    }
    cout<<dfs(a,h,w)<<endl;
    
    
    
    
    return 0;
}



Measured memory_bytes: 223852