#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <string>
#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>

using namespace std;

// ---------------------
// repetition
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)

// debug
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;

// ---------------------
#define INF 922337203685477580
#define IINF (1<<21)
typedef long long ll;


class Board {
public:
  int board[3][3];
  Board() {}
  Board(int b[3][3]) {
    REP(i, 3) {
      REP(j, 3) {
        board[i][j] = b[i][j];
      }
    }
  }

  int hash() {
    int accum = 0;
    int digit = 1;
    REP(i, 3) {
      REP(j, 3) {
        accum += board[i][j] * digit;
        digit *= 10;
      }
    }
    return accum;
  }
  string to_str() {
    string str = "";
    REP(i, 3) {
      REP(j, 3) {
        str += " " + to_string(board[i][j]);
      }
      str += "\n";
    }
    return str;
  }
  bool operator==( const Board& other) {
    REP(i, 3) {
      REP(j, 3) {
        if (board[i][j] != other.board[i][j]) {
          return false;
        }
      }
    }
    return true;
  }
};

class Nully;
static Board Nully;

Board swap_with_upper(const Board& b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_i == 0) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i - 1][pos_j]);
  return next;
}
Board swap_with_lower(const Board& b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_i == 2) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i + 1][pos_j]);
  return next;
}
Board swap_with_left(const Board& b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_j == 0) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i][pos_j - 1]);
  return next;
}
Board swap_with_right(const Board& b) {
  int pos_i, pos_j;
  REP(i, 3) {
    REP(j, 3) {
      if (b.board[i][j] == 0) {
        pos_i = i;
        pos_j = j;
        break;
      }
    }
  }
  if (pos_j == 2) {
    return Nully;
  }

  Board next = b;
  swap(next.board[pos_i][pos_j], next.board[pos_i][pos_j + 1]);
  return next;
}

int main() {
  // int b[3][3] = {{1, 3, 0}, {4, 2, 5}, {7, 8, 6}};
  int b[3][3];
  REP(i, 3) {
    REP(j, 3) {
      cin >> b[i][j];
    }
  }

  int g[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}};
  Board init(b);
  Board goal(g);
  // cout << init.to_str() << endl;

  int depth = 0;
  queue<pair<Board, int> > Q;
  set<int> S;
  Q.push(make_pair(init, depth));
  S.insert(init.hash());

  while (!Q.empty()) {
    Board current = Q.front().first;
    Board next;
    int dpt = Q.front().second;
    Q.pop();

    if (goal == current) {
      cout << dpt << endl;
      return 0;
    }

    next = swap_with_upper(current);
    if (!(next == Nully) && S.count(next.hash()) == 0) {
      Q.push(make_pair(next, dpt + 1));
      S.insert(next.hash());
    }
    next = swap_with_lower(current);
    if (!(next == Nully) && S.count(next.hash()) == 0) {
      Q.push(make_pair(next, dpt + 1));
      S.insert(next.hash());
    }
    next = swap_with_left(current);
    if (!(next == Nully) && S.count(next.hash()) == 0) {
      Q.push(make_pair(next, dpt + 1));
      S.insert(next.hash());
    }
    next = swap_with_right(current);
    if (!(next == Nully) && S.count(next.hash()) == 0) {
      Q.push(make_pair(next, dpt + 1));
      S.insert(next.hash());
    }
  }

  return 0;
}

Measured memory_bytes: 12008