### BUGGY CODE ###

from queue import Queue
from collections import namedtuple


def get_offset(x, y):
    return 16 * y + 4 * x


def swap(board, orig_x, orig_y, dest_x, dest_y):
    orig_offset = get_offset(orig_x, orig_y)
    dest_offset = get_offset(dest_x, dest_y)
    try:
        dest_val = board & (0b1111 << dest_offset)
    except:
        print(orig_x, orig_y, dest_x, dest_y)
        raise
    offset_diff = dest_offset - orig_offset
    swap_val = dest_val >> offset_diff if offset_diff > 0 else dest_val << abs(offset_diff)
    return board - dest_val + swap_val


def put_next_puzzle(puzzle):
    board, x0, y0, count = puzzle.board, puzzle.x0, puzzle.y0, puzzle.count
    for move_horizontal in [0, 1]:
        for direction in [-1, 1]:
            if move_horizontal:
                new_x0, new_y0 = x0 + direction, y0
                if not 0 <= new_x0 < 4:
                    continue
            else:
                new_x0, new_y0 = x0, y0 + direction
                if not 0 <= new_y0 < 4:
                    continue
            new_board = swap(board, x0, y0, new_x0, new_y0)
            if new_board in cache:
                continue
            if new_board == CORRECT:
                return count + 1
            cache.append(new_board)
            puzzles.put(Puzzle(
                    board=new_board,
                    count=count + 1,
                    x0=new_x0,
                    y0=new_y0
            ))
    return -1


CORRECT = 0x0fedcba987654321
puzzles = Queue()
Puzzle = namedtuple('Puzzle', 'board count x0 y0')
cache = []
board = 0
x0 = y0 = -1

for j in range(4):
    for i, v in enumerate(map(int, input().strip().split())):
        board += v << get_offset(i, j)
        if v == 0:
            x0, y0 = i, j

# print('%x' % board)

puzzles.put(Puzzle(board=board, count=0, x0=x0, y0=y0))
cache.append(board)
result = None

while True:
    if puzzles.empty():
        break

    result = put_next_puzzle(puzzles.get())
    if result > -1:
        break

print(result)

### FIXED CODE ###

from heapq import heappop, heappush

manhattan = [[abs((i % 4) - (j % 4)) + abs((i // 4) - (j // 4)) for j in range(16)] for i in range(16)]
movables = [{1, 4}, {0, 2, 5}, {1, 3, 6}, {2, 7}, {0, 5, 8}, {1, 4, 6, 9}, {2, 5, 7, 10}, {3, 6, 11},
            {4, 9, 12}, {5, 8, 10, 13}, {6, 9, 11, 14}, {7, 10, 15}, {8, 13}, {9, 12, 14}, {10, 13, 15}, {11, 14}]
swap_mul = [[(1 << mf) - (1 << mt) for mt in range(0, 64, 4)] for mf in range(0, 64, 4)]
destination = 0xfedcba9876543210

i = 0
board_init = 0
blank_init = 0
for _ in range(4):
    for n in map(int, input().split()):
        if n:
            n -= 1
        else:
            n = 15
            blank_init = i
        board_init += n * 16 ** i
        i += 1

estimation_init = sum(manhattan[i][((board_init >> (4 * i)) & 15)] for i in range(16) if i != blank_init)

queue = [(estimation_init, board_init, blank_init)]
visited = set()

while True:
    estimation, board, blank = heappop(queue)
    if board in visited:
        continue
    elif board == destination:
        print(estimation)
        break
    visited.add(board)
    for new_blank in movables[blank]:
        num = (board >> (4 * new_blank)) & 15
        new_board = board + swap_mul[new_blank][blank] * (15 - num)
        if new_board in visited:
            continue
        new_estimation = estimation + 1 - manhattan[new_blank][num] + manhattan[blank][num]
        if new_estimation > 45:
            continue
        heappush(queue, (new_estimation, new_board, new_blank))