// Slower C++ solution:
#include <algorithm>

#include <iostream>

#include <list>

#include <vector>

#include <string>

#include <map>

#include <utility>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cctype>



using namespace std;



typedef long long Board;



const int N = 9;

const Board GOAL = 0x087654321;



struct state {

    Board board;

    int count;

};



list<state> q;

map<Board,char> history;



inline void swap(int numpos, int spacepos, Board& board) {

    long long num = (board >> (numpos*4)) & 15;

    board |= num << (spacepos*4);

    board &= ~(15LL << (numpos*4));

}



inline int swap_and_check(int numpos, int spacepos, state s) {

    swap(numpos, spacepos, s.board);

    map<Board,char>::iterator it = history.find(s.board);

    if (it != history.end()) {

        return -1;

    }

    history.insert(make_pair(s.board, ' '));

//    for (list<state>::iterator it = q.begin(); it != q.end(); ++it) {

//        if (it->board == s.board) {

//            return -1;

//        }

//    }

    ++s.count;

    if (s.board == GOAL) {

        return s.count;

    }

    q.push_back(s);

    return -1;

}



void print(Board b) {

    for (int i = 0; i < N; ++i) {

        printf("%2lld", (b >> (i*4) & 15));

    }

    printf("\n");

}



int main(void) {



    Board board = 0;

    for (int i = 0; i < N; ) {

        char ch;

        scanf("%c", &ch);

        if (isdigit(ch)) {

            board |= static_cast<long long>((ch - '0')) << (i*4);

            ++i;

        }

    }



    if (board == GOAL) {

        printf("0\n");

        return 0;

    }



//    print(GOAL);

//    print(board);



    q.push_back({ board, 0 });

    int count = 0;

    while (!q.empty()) {

        state s = q.front();

        q.pop_front();

        // ?????????????????????

        int pos;

        for (pos = 0; pos < N; ++pos) {

            if (((s.board >> (pos*4)) & 15) == 0) {

                break;

            }

        }



        if (pos < 6) {

            if ((count = swap_and_check(pos + 3, pos, s)) > 0) {

                break;

            }

        }

        if (pos > 2) {

            if ((count = swap_and_check(pos - 3, pos, s)) > 0) {

                break;

            }

        }

        if (pos % 3 < 2) {

            if ((count = swap_and_check(pos + 1, pos, s)) > 0) {

                break;

            }

        }

        if (pos % 3 > 0) {

            if ((count = swap_and_check(pos - 1, pos, s)) > 0) {

                break;

            }

        }

    }



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



    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 2.431852646940501x):
/* 

 * I used # 1687007 as a refference. Thx. 

 */

#include <iostream>

#include <queue>

#include <set>

#include <cassert>

#include <cmath>

#include <cstdio>

#include <cstdlib>

#include <cctype>



using namespace std;



typedef long long Board;



const int N = 9;

//const int PATTERN = 181440;       // NG; 9! / 2;

const int PATTERN = 362880;         // OK; 9!

const Board GOAL = 0x123456780LL;

const int DX[] = { -1, 0, 1,  0 },

          DY[] = {  0, 1, 0, -1 };



int history[PATTERN];

queue<Board> q;



// I made this function based on one by Haruhiko Okumura(Algorithm 

// Dictionary, p116) and one by M.Hiroi(Puzzle DE Programming).

inline int change_number(long long board) {

    static int fact_table[N] = {

         40320, 5040, 720, 120, 24, 6, 2, 1, 0      // on N = 8

    };

    int value = 0;

    for (int j = 0; j < N - 1; ++j) {

        int J = static_cast<int>((board >> (j*4) & 0xF));

        value += fact_table[j] * J;

        for (int k = j + 1; k < N; ++k) {

            int K = static_cast<int>((board >> k*4) & 0xF);

            if (J < K) {

                board &= ~(0xFLL << k*4);

                board |= (static_cast<long long>(K - 1) << k*4);

            }

        }

    }

//    printf("[change_number] value = %d\n", value);

    return value;

}



inline Board swap(int numpos, int zeropos, Board board) {

    long long num = (board >> (numpos * 4)) & 0xF;

    return (board | (num << zeropos * 4)) & ~(0xFLL << numpos * 4);

}



inline int check(Board newboad, Board board) {

    int hash = change_number(newboad);

    int direction = history[change_number(board)];

    if (history[hash] == 0) {

        q.push(newboad);

        history[hash] = direction + (direction > 0 ? 1 : -1);

    }

    else if ((history[hash] > 0 && direction < 0)

            || (history[hash] < 0 && direction > 0)) {

        return abs(history[hash]) + abs(direction) - 1;

    }

    return 0;

}



void print(Board b) {

    for (int i = N - 1; i >= 0; --i) {

        printf("%2lld", (b >> (i*4) & 0xF));

    }

    printf("\n");

}



// OK

int main(void) {



    Board board = 0;

    for (int i = N - 1, num; i >= 0; --i) {

        scanf("%d", &num);

        board |= static_cast<long long>(num) << (i * 4);

    }

//    print(board);

//    print(GOAL);



    int count = 0;

    if (board == GOAL)

        goto END;



    history[change_number(board)] =  1;     // forward

    history[change_number(GOAL)]  = -1;     // backward



    q.push(board);

    q.push(GOAL);

    while (!q.empty()) {

        board = q.front();

        q.pop();



        int zeropos = -1;

        while (++zeropos < N)

            if (((board >> (zeropos * 4)) & 0xF) == 0)

                break;



        int zx = zeropos % 3, zy = zeropos / 3;

        for (int i = 0; i < 4; ++i) {

            int nx = zx + DX[i], ny = zy + DY[i];

            if (nx < 0 || nx > 2 || ny < 0 || ny > 2)

                continue;

            int numpos = nx + ny * 3;

            Board newboard = swap(numpos, zeropos, board);

            if ((count = check(newboard, board)))

                goto END;

        }

    }



END:

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



    return 0;

}