// Slower C++ solution:
#include<stdio.h>

#include<string.h>

#include<algorithm>

using namespace std;

#include<map>

#include<queue>

#define Max 9

int gg[Max]={1,2,3,4,5,6,7,8,0}, s[Max];



int ff[4][2] = {0,-1,1,0,0,1,-1,0};

int sum;

struct node

{

	int a[Max];

	int step;

};

map<int ,int >m;





int bfs()

{

	node tt;

	memcpy(tt.a,s,sizeof(s));

	tt.step = 0;

	queue<node > q;

	q.push(tt);

	while(!q.empty())

	{

		node star = q.front();

		q.pop();

		int i;

		for(i = 0;i<9;i++)

			if(star.a[i]==0)

				break;

		int y = i/3;

		int x = i%3;

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

		{

			int tx = x + ff[i][0];

			int ty = y + ff[i][1];

			if(tx >= 0&&ty>=0&&ty<3&&tx<3)

			{

				node end;

				memcpy(end.a,star.a,sizeof(star.a));

				int k = ty*3+tx;

				swap(end.a[k],end.a[y*3+x]);

				int sum1 = 0;

				for(int j = 0;j<9;j++)

					sum1 = sum1*10+end.a[j];

				if(!m[sum1])

				{

					m[sum1] = sum++;

					end.step = star.step+1;

					if(memcmp(end.a,gg,sizeof(gg))==0)

						return end.step;

					q.push(end);

				}

			}

		}

	}

}

int main()

{

	int i,j;



	while(~scanf("%d",&s[0]))

	{

		m.clear();

		int k = s[0];

		sum = 1;

		for(i = 1;i<9;i++)

		{

			scanf("%d",&s[i]);

			k = k*10+s[i];

		}

		m[k] = sum++;

		if(memcmp(s,gg,sizeof(gg))==0)

			printf("0\n");

		else printf("%d\n",bfs());

		

	}	

	return 0;

} 


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

#include<stdio.h>

#include<string.h>

#include<math.h>

int Map[4][4];

int max1,min1;

int start_x,start_y;

int flag;

int c[4][2]= {0,1,-1,0,1,0,0,-1};///右（0），上（1），下（2），左（3）；



int HMD()///曼哈顿距离；

{

    int i,j,num=0;

    for(i=0; i<3; i++)

        for(j=0; j<3; j++)

            if(Map[i][j]==0)

                continue;

            else

                num+=fabs((Map[i][j]-1)/3-i)+fabs((Map[i][j]-1)%3-j);

    return num;

}



void start_xyz()///0的起始位置；

{

    int i,j;

    for(i=0; i<3; i++)

        for(j=0; j<3; j++)

            if(Map[i][j]==0)

            {

                start_x=i;

                start_y=j;

                return ;

            }

}



void swap(int *a,int *b)///交换函数;

{

    int t;

    t=*a;

    *a=*b;

    *b=t;

}



void dfs(int x,int y,int s,int last_step)

{

    if(flag)

        return ;

    if(s==max1)///当结果等于当前假定最优解；

    {

        int l=HMD();

        if(l==0)///与目标状态相同；

        {

            min1=s;///记录结果；

            flag=1;

        }

        return ;

    }

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

    {

        if(last_step+i==3&&s>0)///和上次方向不能相反；

            continue;

        int dx=x+c[i][0];

        int dy=y+c[i][1];

        if(dx<0||dy<0||dx>=3||dy>=3)///是否越界；

            continue;

        swap(&Map[dx][dy],&Map[x][y]);///先交换0和要交换数的值；

        if(HMD()+s<=max1&&!flag)///IDA*剪枝。核心：当前曼哈顿距离+当前深度<=假定最优解；

        {

            dfs(dx,dy,s+1,i);

            if(flag)

                return ;

        }

        swap(&Map[dx][dy],&Map[x][y]);///回溯；

    }

}

int main()

{

    char a[10];

    int i,j;

    for(i=0;i<3;i++)

        for(j=0;j<3;j++)

            scanf("%d",&Map[i][j]);

    start_xyz();///找到0的起始位置；

    max1=HMD();///初始假定最优解；

    flag=0;

    while(!flag)

    {

        dfs(start_x,start_y,0,0);

        if(!flag)

            max1++;///增加假定最优解；

    }

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

    return 0;

}