//遅延評価を実装したくなったときの参考サイトhttp://tsutaj.hatenablog.com/entry/2017/03/30/224339
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <math.h>
#include <iomanip>
#include <limits>
#include <list>
#include <queue>
#include <tuple>
#include <map>
using namespace std;
#define MOD (long long int)(1e9+7)
#define ll long long int
#define rep(i,n) for(int i=0; i<(int)(n); i++)
#define reps(i,n) for(int i=1; i<=(int)(n); i++)
#define REP(i,n) for(int i=n-1; i>=0; i--)
#define REPS(i,n) for(int i=n; i>0; i--)
#define INF (int)(123456789)
//#define LINF (long long int)(123456789012345678)
#define LINF (long long int)(((ll)1<<31)-1)
#define all(v) v.begin(), v.end()
#define MAX_V 1000

const int MAX_N = 1 << 20;

//葉の数
int N;
//扱うデータ型をllとしている.適宜修正.
ll dat[2 * MAX_N - 1];

void init(int n_){
  //簡単のため, 要素数を2のべき乗に
  N = 1;
  while(N < n_) N *= 2;

  //初期化処理をここに書く
  rep(i,2 * N - 1){
    dat[i] = 0;
  }
}

//k番目の値について, 処理を行う
//例として, aに変更している
ll update(int k){
  //葉のノード番号
  k += N-1;

  //葉の更新処理をここに書く.
  //dat[k] = a;
  ll ret = dat[k];


  //登りながら更新.
  while(k > 0){
    k = (k-1) / 2;
    //中間ノードの更新処理をここに書く.
    //dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
    ret += dat[k];
  }

  return ret;
}

//[a,b)における評価値を得る. ここでは最小値としている.
//nowが現在の接点番号, nowは[l, r)に対応している.
//呼ぶ時は query(a,b,0,0,N)
void query(int a, int b, int now, int l, int r, int add){
  //[a,b)と[l,r)が交差しなければ, 無を返す.
  //評価値が最小値ならばINT_MAX. 修正すること.
  if(r <= a || b <= l) return;

  // [a, b)が[l, r)を完全に含んでいれば, このノードの値
  if(a <= l && r <= b){
    dat[now] += add;
  }else{
    //そうでなければ, 2つの個の複合値
    //ここでは, 2つの子の最小値. 修正すること.
    query(a, b, now*2+1, l, (l+r)/2, add);
    query(a, b, now*2+2, (l+r)/2, r, add);
  }
}

int main(void){
  /*int n,q;cin>>n>>q;
  init(n);
  rep(i,q){
    ll com,x,y;
    cin>>com>>x>>y;
    if(com == 0){
      update(x, y);
    }else{
      cout<<query(x, y+1, 0, 0, N)<<endl;
    }
  }*/
  
  vector<int> w2i[26];
  vector<int> p2i;
  vector<bool> left;
  string s;
  cin>>s;
  rep(i,s.size()){
    w2i[s[i]-'a'].push_back(i);
    //移動後の場所 to 移動前の場所
    p2i.push_back(i);
    left.push_back(false);
  }
  
  vector<pair<int,int>> ps;
  int count = 0;
  rep(i,26){
    rep(j,(w2i[i].size()+1)/2){
      left[w2i[i][j]] = true;
      ps.push_back({w2i[i][j], w2i[i][w2i[i].size()-1 - j]});
    }
    if(w2i[i].size()%2==1){
      count++;
    }
  }
  if(count > 0){
    if(s.size()%2 == 0){
      cout<<-1<<endl;
      return 0;
    }else{
      if(count > 1){
        cout<<-1<<endl;
        return 0;
      }
    }
  }

  sort(all(ps));
  rep(i,ps.size()){
    int fi = ps[i].first;
    int se = ps[i].second;
    if(fi == se){
      p2i[fi] = s.size()/2;
      continue;
    }
    p2i[fi] = -1;
    p2i[se] = s.size()-1 - i;
  }

  /*rep(i,p2i.size()){
    cerr<<p2i[i]<<" ";
  }
  cerr<<endl;*/

  //psのseを左から順番に処理
  //psのseからp2i[ps.se]に移動する
  //seg[ps[se]]とp2i[ps.se]の差分を足す, 右端まで+1
  init(s.size());
  reps(i,s.size()-1){
    query(i,s.size(),0,0,N,1);
  }
  ll ans = 0;
  rep(i,ps.size()){
    int idx = ps[i].second;
    int goal = p2i[idx];
    if(goal == -1) continue;
    if(goal - update(idx) <= 0) continue;
    ans += goal - update(idx);
    //cout<<ps[i].first<<" "<<ps[i].second<<" "<<update(idx)<<" "<<goal<<" "<<goal - update(idx)<<endl;;
    query(idx, s.size(), 0, 0, N, -1);
  }
  cout<<ans<<endl;

  return 0;
}

Measured memory_bytes: 10228