#include <bits/stdc++.h>
using namespace std;
template <typename Ty>
class dlist {
 private:
  struct Node {
    int pos;
    Ty v;
    Node *l, *r;
  };
  typedef Node* cnode;
  cnode position;
  int siz;
  void no_position() { cout << "The list is empty!" << endl; }

 public:
  dlist() {
    siz = 0;
    position = nullptr;
  }
  void clear() {
    siz = 0;
    position = nullptr;
  }
  int size() { return siz; }
  bool first() {
    if (not position) {
      no_position();
      return false;
    }
    return (not position->l);
  }
  bool last() {
    if (not position) {
      no_position();
      return false;
    }
    return (not position->r);
  }
  void next() {
    if (not position) {
      no_position();
      return;
    }
    if (last()) {
      cout << "this is already the last node" << endl;
      return;
    }
    position = position->r;
    position->pos = 1 + position->l->pos;
  }
  void previous() {
    if (not position) {
      no_position();
      return;
    }
    if (first()) {
      cout << "this is already the first node" << endl;
      return;
    }
    position = position->l;
  }
  Ty value() {
    if (not position) {
      no_position();
      return 0;
    }
    return position->v;
  }
  void insert(Ty value) {
    ++siz;
    if (not position)
      position = new Node{0, value, nullptr, nullptr};
    else {
      cnode a = new Node{(position->pos) + 1, value, position, position->r};
      if (not last()) position->r->l = a;
      position->r = a;
    }
  }
  void move_to(int pos) {
    if (pos < 0 or pos >= size()) {
      cout << "out of bounds" << endl;
      return;
    }
    while ((position->pos) > pos) previous();
    while ((position->pos) < pos) next();
  }
  void erase() {
    if (last()) {
      cout << "this is the last node, there is none after" << endl;
      return;
    }
    --siz;
    if (not position->r->r) {
      delete position->r;
      position->r = nullptr;
    } else {
      position->r->r->l = position;
      position->r = position->r->r;
    }
  }
};
vector<queue<int> > G;
dlist<int> path;
void H_dfs(int v) {
  path.insert(v);
  path.next();
  if (G[v].empty()) return;
  int u = G[v].front();
  G[v].pop();
  H_dfs(u);
}
vector<long long int> Hierholzer(int v) {
  path.clear();
  path.insert(v);
  for (int i = 0; i < path.size(); ++i) {
    int u = path.value();
    while (not G[u].empty()) {
      H_dfs(u);
      path.move_to(i);
      path.erase();
    }
    if (not path.last()) path.next();
  }
  path.move_to(0);
  vector<long long int> ans(path.size());
  for (int i = 0; i < path.size(); ++i) {
    ans[i] = path.value();
    if (not path.last()) path.next();
  }
  return ans;
}
void solve(int n) {
  if (n & 1) {
    cout << -1 << endl;
    return;
  }
  if (n == 2) {
    cout << "0 1 0" << endl;
    return;
  }
  int m = (n >> 1);
  G = vector<queue<int> >(m);
  for (int i = 1; i < m; ++i) {
    G[i].push((i << 1) % m);
    G[i].push(((i << 1) + 1) % m);
  }
  G[0].push(1);
  vector<long long int> ans = Hierholzer(0);
  ans.push_back(0);
  for (int i = 1; i < ans.size(); ++i) {
    if ((ans[i - 1] << 1) % m == ans[i])
      ans[i] = (ans[i - 1] * 2) % n;
    else
      ans[i] = (ans[i - 1] * 2 + 1) % n;
  }
  for (int i = 0; i < ans.size(); ++i) cout << ans[i] << ' ';
  cout << endl;
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n;
  cin >> n;
  solve(n);
}
