#include <iostream>
#include <cassert>
#define GET_MACRO(_1,_2,_3,_4,_5,_6,_7,_8,NAME,...) NAME
#define pr(...) std::cerr<< GET_MACRO(__VA_ARGS__,pr8,pr7,pr6,pr5,pr4,pr3,pr2,pr1)(__VA_ARGS__) <<std::endl
#define pr1(a) (#a)<<"="<<(a)<<" "
#define pr2(a,b) pr1(a)<<pr1(b)
#define pr3(a,b,c) pr1(a)<<pr2(b,c)
#define pr4(a,b,c,d) pr1(a)<<pr3(b,c,d)
#define pr5(a,b,c,d,e) pr1(a)<<pr4(b,c,d,e)
#define pr6(a,b,c,d,e,f) pr1(a)<<pr5(b,c,d,e,f)
#define pr7(a,b,c,d,e,f,g) pr1(a)<<pr6(b,c,d,e,f,g)
#define pr8(a,b,c,d,e,f,g,h) pr1(a)<<pr7(b,c,d,e,f,g,h)
#define prArr(a) {cerr<<(#a)<<"={";int i=0;for(auto t:(a))cerr<<(i++?", ":"")<<t;cerr<<"}"<<endl;}
 
template<typename T>
class Deque{
public:
  T *val;
  int sz;
  int length;
  int head, tail;
   
  Deque(){sz = 0, length = 0, val = new T[0];}
  Deque(int size, T init = T()){
    length = 1;
    while(length < size) length *= 2;
    val = new T[length];
    sz = size;
    head = 0;
    tail = 0;
    for(int i=0;i<size;i++) val[tail++] = init;
  }
   
  Deque(const Deque &t){
    sz = t.size();
    length = 1;
    while(length < sz) length *= 2;
    val = new T[length];
    head = 0;
    tail = 0;
    for(int i=0;i<sz;i++) val[tail++] = t[i];
  }
 
  ~Deque(){
    delete [] val;
  }
   
  Deque<T> operator = (const Deque<T> t){
    delete [] val;
    sz = t.size();
    length = 1;
    while(length < sz) length *= 2;
    val = new T[length];
    head = 0;
    tail = 0;
    for(int i=0;i<sz;i++) val[tail++] = t[i];
    return t;
  };
   
  T& operator [] (int i){
    assert(0 <= i && i < sz);
    return head+i<length? val[head+i]:val[head+i - length];
  }
  T& operator [] (int i)const{
   assert(0 <= i && i < sz);
    return head+i<length? val[head+i]:val[head+i - length];
  }
   
  bool operator == (const Deque<T> &a)const{
    if(size() != a.size()) return 0;
    for(int i=0;i<size();i++)
      if(!((*this)[i] == a[i])) return 0;
    return 1;
  }
   
  T& front(){return val[head];}
  T& back(){return val[(head + sz - 1) % length];}
   
  int size()const{return sz;}
  int empty()const{return sz == 0;}
   
  void resize(int n, T v=T()){
    while(n < size()) pop_back();
    while(n > size()) push_back_fast(v);
  }
 
 
  void increaseMemory(){
    int length_ = length;
    length = length * 2;
    if(length == 0) length = 1;
    T *val2 = new T[length];
    for(int i=0;i<sz;i++) val2[i] = val[(head + i)%length_];
    head = 0;
    tail = sz;
    delete [] val;
    val = val2;
  };
   
  void push_back(T v){
    if(sz == length) increaseMemory();
    sz++;
    val[tail++] = v;
    if(tail == length) tail = 0;
  }
 
  void push_back_fast(T &v){
    if(sz == length) increaseMemory();
    sz++;
    val[tail++] = v;
    if(tail == length) tail = 0;
  }
     
  void push_front(int v){
    if(sz == length) increaseMemory();
    sz++;
    head--;
    if(head == -1) head = length - 1;
    val[head] = v;
  }
 
  void pop_back(){
    assert(sz > 0);
    sz--;
    tail--;
    if(tail == -1) tail = length - 1;
  }
   
  void pop_front(){
    assert(sz > 0);
    sz--;
    head++;
    if(head == length) head = 0;
  }
 
  friend std::ostream& operator << (std::ostream& os,const Deque<T> a){
    os<<"[";
    for(int i=0;i<a.size();i++){
      if(i) os<<" ";
      os<<a[i];
    }
    os<<"]";
    return os;
  }
};
template <typename T>
using vector = Deque<T>;
 
template <typename T>
using queue = Deque<T>;
 
template <typename T, typename D>
class Pair{
public:
  T first;
  D second;
  Pair(){first = T(),second = D();}
  Pair(const T &first, const D &second):first(first), second(second){}
   
  bool operator < (const Pair t)const{
    return first != t.first? (first < t.first):(second < t.second);
  }
  bool operator > (const Pair t)const{
    return first != t.first? (first > t.first):(second > t.second);
  }
   
  friend std::ostream& operator << (std::ostream& os,const Pair<T, D> a){
    os<<"("<<a.first<<", "<<a.second<<")";
    return os;
  }
};
 
template<class T, class D>
class HashTable{
public:
  using ull = unsigned int;
  ull tableSize;
  vector<vector<T> > tableKey;
  vector<vector<D> > tableVal;
   
  HashTable(ull tableSize = 500009){
    for(int i=2;i*i<=tableSize;i++)
      assert(tableSize % i != 0 && "tableSize have to be prime number");
    this->tableSize = tableSize;
    tableKey.resize(tableSize);
    tableVal.resize(tableSize);
 
  }
 
  void push(T key, D val, ull hash){
    hash %= tableSize;
    tableKey[hash].push_back_fast(key);
    tableVal[hash].push_back_fast(val);
  }
 
  bool count(T key, ull hash){
    hash %= tableSize;
    int count = 0;
    for(int i=0;i<tableKey[hash].size();i++)
      if(tableKey[hash][i] == key) count++;
    return count;
  }
 
  D getVal(T key, ull hash){
    hash %= tableSize;
    for(int i=0;i<tableKey[hash].size();i++)
      if(tableKey[hash][i] == key) return tableVal[hash][i];
    assert(!"key not exists");
  }
};
 
template<class T>
void swap(T &a, T &b){
  T tmp = a;
  a = b;
  b = tmp;
}
 
using D = vector<vector<int> >;
using P = Pair<int, D>;
const int N = 3;
using ull = unsigned int;
 
ull toHash(D &mp){
  const ull B = 1777771;
  ull hash = 0;
  for(int i=0;i<N;i++)
    for(int j=0;j<N;j++) hash = hash * B + mp[i][j];
  return hash;
}
 
HashTable<D, int> bfs(D start, D goal, int limit){
  queue <P> Q;
  Q.push_back(P(0,start));
  HashTable <D, int> memo(100019);
  memo.push(start, 0, toHash(start));
   
  while(!Q.empty()){
    int cost = Q.front().first;
    D mp = Q.front().second;
    Q.pop_front();
    if(cost == limit) continue;
     
    for(int i=0;i<N;i++)
      for(int j=0;j<N;j++){
    if(j+1<N && (mp[i][j] == 0 || mp[i][j+1] == 0)){
      D key = mp; swap(key[i][j], key[i][j+1]);
      int val = cost + 1;
      ull hash = toHash(key);
      if(!memo.count(key, hash)){ 
        memo.push(key, val, hash);
        Q.push_back(P(val, key));
      }
    }
 
    if(i+1<N && (mp[i][j] == 0 || mp[i+1][j] == 0)){
      D key = mp; swap(key[i][j], key[i+1][j]);
      int val = cost + 1;
      ull hash = toHash(key);
      if(!memo.count(key, hash)){
        memo.push(key, val, hash);
        Q.push_back(P(val, key));
      }
    }
      }
  }
  return memo;
}
 
signed main(){
 
  D goal(N, vector<int>(N));
  for(int i=0;i<N;i++)
    for(int j=0;j<N;j++) goal[i][j] = i*N + j + 1;
  goal[N-1][N-1] = 0;
 
  D start(N, vector<int>(N));
  for(int i=0;i<N;i++)
    for(int j=0;j<N;j++) std::cin>>start[i][j];
 
   
  auto A = bfs(start, goal, 20);
  auto B = bfs(goal, start, 15);
 
  int ans = 1000000;
  for(int i=0;i<(int)B.tableSize;i++)
    for(int j=0;j<(int)B.tableKey[i].size();j++){
      auto key = B.tableKey[i][j];
      auto costB = B.tableVal[i][j];
      int costA = 10000000;
      if(A.count(key, i)) costA = A.getVal(key, i);
      if(ans > costA + costB) ans = costA + costB;
     
 
    }
   
  std::cout<<ans<<std::endl;
}


Measured memory_bytes: 58624