#include <iostream>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <cmath>
#include <vector>
#include <numeric>
#include <cstdio>
#include <bitset>
#include <map>
#include <string>
#include <valarray>
#include <queue>
#include <utility>

using namespace std;
typedef pair<int, int> Coordinate;

class PuzzleStatus
{
    // enum Direction {up, down, left, right};    

    public:
    friend ostream & operator<<(ostream & os, PuzzleStatus & ps);
    friend istream & operator>>(istream & is, PuzzleStatus & ps);
    bool operator<(const PuzzleStatus &) const;

    bool move_up();
    bool move_down();
    bool move_left();
    bool move_right();

    static const vector< vector<int> > & get_target();
    static void set_target();
    const vector< vector<int> > & get_position() const;
    // PuzzleStatus() {distance = 0;}

    private:
        vector< vector<int> > position;
        Coordinate space_pos;
        int distance = 0;   //the fewest steps from the original status
   
        //require c++11
        // static const vector< vector<int> > target;

        static vector< vector<int> > target;
};


bool move(PuzzleStatus & u, string direction);

//require c++11
// const vector< vector<int> > PuzzleStatus::target = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};

vector< vector<int> > PuzzleStatus::target;

// not used
// bool is_target(PuzzleStatus);
// vector<PuzzleStatus (PuzzleStatus::*) ()> funcs = 
// {PuzzleStatus::move_up, PuzzleStatus::move_down, PuzzleStatus::move_left, PuzzleStatus::move_right};
// int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
// PuzzleStatus move(PuzzleStatus, PuzzleStatus (PuzzleStatus::*) (PuzzleStatus));

//the size of puzzle
const int SIZE = 3;

int main()
{
    PuzzleStatus::set_target();
    
    PuzzleStatus origin;

    cin >> origin;

    queue<PuzzleStatus> Q;
    map<PuzzleStatus, bool> visited;
    
    Q.push(origin);
    visited[origin] = true;

    //require c++11
    // vector<string> directions = {"up", "down", "left", "right"};
    
    string d[] = {"up", "down", "left", "right"};
    vector<string> directions(d, d+4);

    while (!Q.empty())
    {
        if (Q.front().get_position() == PuzzleStatus::get_target())
            break;

        for (int i = 0; i < 4; i++)
        {
            PuzzleStatus temp = Q.front();
            if (move(temp, directions[i]) && !visited[temp])
            {
                visited[temp] = true; 
                Q.push(temp);                
            }
        }
        Q.pop();
    }

    cout << Q.front();
}


ostream & operator<<(ostream & os, PuzzleStatus & ps)
{
    os << ps.distance << endl;
    return os;
}

istream & operator>>(istream & is, PuzzleStatus & ps)
{
    ps.position.resize(SIZE);
    for (int i = 0; i < SIZE; i++)
    {
        ps.position[i].resize(SIZE);
        for (int j = 0; j < SIZE; j++)
        {
            is >> ps.position[i][j];
            if (ps.position[i][j] == 0)
            {
                ps.space_pos.first = i; 
                ps.space_pos.second = j; 
            }
                           
        }

    }
    return is;
}


bool PuzzleStatus::move_up()
{
    int & i = space_pos.first, & j = space_pos.second;

    if (i > 0)
    {
        swap(position[i-1][j], position[i][j]);
        i--;
        distance++;
        return true;     
    }  
    return false;   
}

bool PuzzleStatus::move_down()
{
    int & i = space_pos.first, & j = space_pos.second;

    if (i < SIZE-1)
    {
        swap(position[i+1][j], position[i][j]);
        i++;
        distance++;   
        return true;   
    }  
    return false;   
}

bool PuzzleStatus::move_left()
{
    int & i = space_pos.first, & j = space_pos.second;

    if (j > 0)
    {
        swap(position[i][j-1], position[i][j]);
        j--;
        distance++;
        return true;     
    }  
    return false;      
}

bool PuzzleStatus::move_right()
{
    int & i = space_pos.first, & j = space_pos.second;

    if (j < SIZE-1)
    {
        swap(position[i][j+1], position[i][j]);
        j++;
        distance++; 
        return true;    
    }  
    return false;   
}


// PuzzleStatus move(PuzzleStatus u, PuzzleStatus (PuzzleStatus::*func) ())
// {
//     return (u.*func)();
// }

bool move(PuzzleStatus & u, string direction)
{
    if (direction == "up")
        return u.move_up();
    else if (direction == "down")
        return u.move_down();
    else if (direction == "left")
        return u.move_left();
    else if(direction == "right")
        return u.move_right();
    else
        return false;
}


const vector< vector<int> > & PuzzleStatus::get_target()
{
    return target;
}

const vector< vector<int> > & PuzzleStatus::get_position() const
{
    return position;
}


bool PuzzleStatus::operator<(const PuzzleStatus & ps) const
{
    return position < ps.position;
}


void PuzzleStatus::set_target()
{
    target.resize(SIZE);
    for (int i = 0; i < SIZE; i++)
    {
        target[i].resize(SIZE);
        for (int j = 0; j < SIZE; j++)
            target[i][j] = i*SIZE+j+1;
    }
    target[SIZE-1][SIZE-1] = 0;
}


Measured memory_bytes: 52356