#include <stdio.h>
#include <limits.h>
#include <ctype.h>

#define TW  8                   /* board side length */
#define NKMAX  64
#define UNKNOWN -1
#define BUFSIZE 256

#define INFILE "CAMELOT.IN"
#define OUTFILE "CAMELOT.OUT"

#define DEBUG

typedef int Board[TW][TW];      /* The type of cost matrices */

static int NK;
static int IP[NKMAX*2];          /* input positions */
static Board MCM[NKMAX];	 /* cost matrices of matings */
static Board KnightCostMat[TW][TW]; /* all-pos knight costs */
static Board KingMat;

#define TW2 (2*TW)

#define CL(c) (int)(c-'A') /* chess letter */
#define CD(c) (int)(c-'1') /* chess digit */


void Erase(Board t)
{
  int h,v;

  for(h=0;h<TW;h++)
    for(v=0;v<TW;v++)
      t[h][v] = UNKNOWN;
}

void KnightCost(int h, int v, int s, Board t)
{
  if((t[h][v]<0 || s<t[h][v]) && h>=0 && h<TW && v>=0 && v<TW)
    {
       t[h][v] = s++;
       KnightCost(h+2,v+1,s,t);
       KnightCost(h+2,v-1,s,t);
       KnightCost(h-2,v+1,s,t);
       KnightCost(h-2,v-1,s,t);
       KnightCost(h+1,v+2,s,t);
       KnightCost(h+1,v-2,s,t);
       KnightCost(h-1,v+2,s,t);
       KnightCost(h-1,v-2,s,t);
    }
}

void InitKBoard(void)
{
  int h,v;
  for(h=0;h<TW;h++)
    for(v=0;v<TW;v++)
    {
      Erase(KnightCostMat[h][v]);
      KnightCost(h,v,0,KnightCostMat[h][v]);
    }
}

/* fill king table at (h,v) */

void KingCost(int h, int v, int s, Board t)
{
  int j;

  if((t[h][v]<0 || s<t[h][v]) && h>=0 && h<TW && v>=0 && v<TW)
    {
       t[h][v] = s++;
       KingCost(h,v+1,s,t);
       KingCost(h,v-1,s,t);
       for(j=-1;j<2;j++)
	 {
	   KingCost(h+1,v+j,s,t);
	   KingCost(h-1,v+j,s,t);
	 }
    }
}

/* Sum Boards  */

void AddBoard(Board a, Board b, Board c)
{
  int v,h;
  for(v=0;v<TW;v++)
    for(h=0;h<TW;h++)
      c[h][v] = a[h][v]+b[h][v];
}

/* Move Board */

void Move(Board a, Board b)
{
  int v,h;
  for(v=0;v<TW;v++)
    for(h=0;h<TW;h++)
      a[h][v] = b[h][v];
}


/* Minimum value of Board and Position */

int MinVal(Board k)
{
  int v,h,S=k[0][0];
  for(v=0;v<TW;v++)
    for(h=0;h<TW;h++) 
      if(k[h][v]<S)
        S=k[h][v];
  return S;
}

/* Compute all NK matings cost */

void MakePairs(void)
{
  int i,ii,h,v;
  Board tb,tu,kmt;

  for(i=0;i<NK;i++) /* for each knigt */
    {
      ii = i*2;
      AddBoard(KnightCostMat[IP[ii]][IP[ii+1]],KingMat,tb);
      for(h=0;h<TW;h++)
	for(v=0;v<TW;v++)
	  {
	    Move(kmt,KnightCostMat[h][v]);
	    AddBoard(tb,kmt,tu);
	    MCM[i][h][v]=MinVal(tu);
          }
    }
}

void Results(char *fname, int val)
{
  int i;
  FILE *of;
  of = fopen(fname,"w+");
  fprintf(of,"%d\n",val);
  fclose(of);
}

/* Pick the Best */

int Best(void)
{
  Board rs,rn,kt;
  int ii,h,v,i;
  int val;

      /* first case, no gathering */

  Move(rs,KnightCostMat[IP[0]][IP[1]]);

  ii = 2;
  for(i=1;i<NK; i++)
    {
      Move(kt,KnightCostMat[IP[ii]][IP[ii+1]]);
      AddBoard(rs,kt,rs);
      ii += 2;
    }

  AddBoard(rs,KingMat,rn);
  val = MinVal(rn);

      /* possible gatherings */

  ii = 0;
  for(i=0;i<NK; i++)
    {
      int newval;
      Move(kt,KnightCostMat[IP[ii]][IP[ii+1]]);
      for(h=0;h<TW;h++)
	for(v=0;v<TW;v++)
	  rn[h][v] = rs[h][v] - kt[h][v] + MCM[i][h][v];
      newval = MinVal(rn);
      if(newval<val)
	    val = newval;
      ii += 2;
    }
#ifdef DEBUG
  printf("%d\n",val);
#endif
  return val;
}

void InitData(void)
{
  InitKBoard();
  Erase(KingMat);
}

void ReadPieces(char *fname)
{
  FILE * f ;
  char buf[BUFSIZE];
  int i;
  
  if(fname)
    {
      f = fopen(fname,"r");
      if(f==NULL) exit(1);
      else 
        {
          fscanf(f,"%s",buf);
          fclose(f);
        }
    } else exit(1);
  KingCost(CL(buf[0]),CD(buf[1]),0,KingMat);
  i = 2; NK = 0;
  while(isalpha(buf[i]))
    {
      IP[i-2]=CL(buf[i]);
      i++;
      IP[i-2]=CD(buf[i]);
      i++;
      NK++;
    }
}


void main()
{
  InitData();
  ReadPieces(INFILE);
  MakePairs();
  Results(OUTFILE,Best());
}
