using System;
using System.Linq;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.IO;

namespace AOJ
{
    class Program
    {
        static public long[] Sarray() { return ReadLine().Trim().Split().Select(long.Parse).ToArray(); }
        static public List<long> Slist() { return ReadLine().Split().Select(long.Parse).ToList(); }

        static void Main(string[] args)
        {
            var n = 4;
            var n2 = n * n;
            var masu = new int[n, n];
            for (var i = 0; i < n; ++i)
            {
                var num = Sarray();
                for (var j = 0; j < n; ++j)
                    masu[i, j ] = (int)num[j];
            }
            var e = new Astar(masu);
            WriteLine(e.astar());
        }
        class Astar
        {
            public class Puzzle :IEquatable<Puzzle>
            {
                public int space, MD, cost;
                public int[] f;
                public Puzzle(int N2, int space, int MD)
                {
                    this.space = space;
                    f = new int[N2];
                    this.MD = MD;
                    cost = 0;
                }
                public Puzzle(Puzzle p)
                {
                    space = p.space;
                    MD = p.MD;
                    cost = p.cost;
                    f = new int[p.f.Length];
                    Array.Copy(p.f, f, p.f.Length);
                }
                public bool Equals(Puzzle other) => this.f.SequenceEqual(other.f);
                public override int GetHashCode() => f.Aggregate(0, (acc, i) => unchecked(acc * 457 + i * 389));
            }
            class State
            {
                public Puzzle puzzle;
                public int estimated;
                public State(Puzzle p, int e)
                {
                    puzzle = p;
                    estimated = e;
                }
            }
            readonly int[] dx = new int[] { 0, -1, 0, 1 };//Height
            readonly int[] dy = new int[] { 1, 0, -1, 0 };//Width
            readonly int N;
            readonly int N2;
            readonly int[,] MDT;
            Puzzle p;
            public Astar(int[,] inp)
            {
                N = inp.GetLength(0);
                N2 = N * N;
                p = new Puzzle(N2, 0, 0);
                for(var i=0;i<N;++i)
                    for(var j=0;j<N;++j)
                    {
                        p.f[i * N + j] = inp[i, j];
                        if (p.f[i * N + j] == 0)
                        {
                            p.space = i * N + j;
                            p.f[i * N + j] = N2;
                        }
                    }
                MDT = new int[N2, N2];
                for (var i = 0; i < N2; ++i)
                    for (var j = 0; j < N2; ++j)
                        MDT[i, j] = Math.Abs(i / N - j / N) + Math.Abs(i % N - j % N);

            }
            int getAllMD(Puzzle pz)
            {
                var sum = 0;
                for (var i = 0; i < N2; ++i)
                {
                    if (pz.f[i] == N2) continue;
                    sum += MDT[i, pz.f[i] - 1];
                }
                return sum;
            }
            public int astar()
            {
                var PQ = new priority_queue<State>((l, r) => r.estimated - l.estimated);
                var V = new HashSet<Puzzle>();

                p.MD = getAllMD(p);
                var initial = new State(p, p.MD);
                PQ.insert(initial);

                while (PQ.num != 0)
                {
                    var u = PQ.extract().puzzle;
                    if (u.MD == 0) return u.cost;
                    V.Add(u);

                    var sx = u.space / N;
                    var sy = u.space % N;

                    for (var r = 0; r < 4; ++r)
                    {
                        var tx = sx + dx[r];
                        var ty = sy + dy[r];
                        if (tx < 0 || ty < 0 || N <= tx || N <= ty) continue;

                        var v = new Puzzle(u);
                        v.MD -= MDT[tx * N + ty, v.f[tx * N + ty] - 1];
                        v.MD += MDT[sx * N + sy, v.f[tx * N + ty] - 1];
                        v.f[sx * N + sy] = v.f[tx * N + ty];
                        v.f[tx * N + ty] = N2;
                        v.space = tx * N + ty;

                        if (!V.Contains(v))
                        {
                            v.cost++;
                            var news = new State(v, v.cost + v.MD);
                            PQ.insert(news);
                        }
                    }
                }
                return -1;
            }
        }
        class priority_queue<T>
        {
            Comparison<T> cmp;
            T[] A = new T[2000000];
            public priority_queue(Comparison<T> c)
            {
                cmp = c;
            }
            public int num { get; private set; } = 0;
            public void insert(T v)
            {
                A[num] = v;
                ++num;
                increaseKey(num);
            }
            void increaseKey(int i)
            {
                while (1 < i && 0 < cmp(A[i - 1], A[i / 2 - 1]))
                {
                    var t = A[i - 1];
                    A[i - 1] = A[i / 2 - 1];
                    A[i / 2 - 1] = t;
                    i = i / 2;
                }
            }
            public T extract()
            {
                if (num < 1) return default(T);
                var max = A[0];
                A[0] = A[num - 1];
                --num;
                maxHeapify(1);
                return max;
            }
            void maxHeapify(int i)
            {
                var H = num;
                var l = left(i);
                var r = right(i);
                var largest = 0;
                if (l <= H && 0 < cmp(A[l - 1], A[i - 1]))
                { largest = l; }
                else
                { largest = i; }
                if (r <= H && 0 < cmp(A[r - 1], A[largest - 1]))
                { largest = r; }
                if (largest != i)
                {
                    var t = A[i - 1];
                    A[i - 1] = A[largest - 1];
                    A[largest - 1] = t;
                    maxHeapify(largest);
                }
            }
            int left(int l) => l * 2;
            int right(int r) => r * 2 + 1;
        }

    }
}


Measured memory_bytes: 431984