#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#define TASKNAME "covering"

const int MaxN = 9, MaxK = 3, NUM = 6, MaxP = 12, TRIES = 4, MaxS = 2,
 MaxL = (MaxN + MaxK) * (MaxN + MaxK) + 1;
const double MinT = -8.0, MaxT = 6.0, DeltaT = 0.00005;

int a [MaxN + MaxK * 2] [MaxN + MaxK * 2];
bool b [MaxK] [MaxK];
int left [MaxL] [NUM], right [MaxL] [NUM];
bool tile [MaxL];
int cell [MaxL];
int x [MaxP], y [MaxP * NUM];
int count, oldcount, min;
int m, n;

inline void add (int z)
{
 assert (z && !tile[z]);
 cell[left[z][0]]++;
 cell[left[z][1]]++;
 cell[left[z][2]]++;
 cell[left[z][3]]++;
 cell[left[z][4]]++;
 cell[left[z][5]]++;
 tile[z] = true;
 count++;
}

inline void rem (int z)
{
 assert (z && tile[z]);
 cell[left[z][0]]--;
 cell[left[z][1]]--;
 cell[left[z][2]]--;
 cell[left[z][3]]--;
 cell[left[z][4]]--;
 cell[left[z][5]]--;
 tile[z] = false;
 count--;
}

void pattern (void)
{
 int x, y, lim, u, v, k, i, j, p, q;
 bool ok;
 for (x = 1; x <= MaxN; x++)
  for (y = 1; y <= MaxN; y++)
  if (x * y < MaxP)
  {
   lim = 1 << (x * y);
   for (u = 0; u < MaxK; u++)
    for (v = 0; v < MaxK; v++)
     for (k = lim - 1; k >= 0; k--)
     {
      memset (a, 0, sizeof (a));
      count = 0;
      for (i = 1; i <= m; i++)
       for (j = 1; j <= n; j++)
        if (k & (1 << (((i % y) * x) + (j % x))))
        {
         ok = false;
         for (p = 0; p < MaxK; p++)
          for (q = 0; q < MaxK; q++)
           if (!a[i + p][j + q] && b[p][q])
           {
            if (i + p >= u && i + p < m + u && j + q >= v && j + q < n + v)
             ok = true;
            a[i + p][j + q]++;
           }
         if (ok)
         count++;
        }
       for (i = 1; i <= m; i++)
        for (j = 1; j <= n; j++)
        if (k & (1 << (((i % y) * x) + (j % x))))
        {
         ok = false;
         for (p = 0; p < MaxK; p++)
          for (q = 0; q < MaxK; q++)
           if (a[i + p][j + q] == 1 && b[p][q])
            if (i + p >= u && i + p < m + u && j + q >= v && j + q < n + v)
             ok = true;
         if (!ok)
         {
          for (p = 0; p < MaxK; p++)
           for (q = 0; q < MaxK; q++)
            if (b[p][q])
             a[i + p][j + q]--;
          count--;
         }
        }
       ok = true;
       for (i = u; i < m + u; i++)
        for (j = v; j < n + v; j++)
         ok &= a[i][j];
       if (ok)
        if (min > count)
         min = count;
     }
  }
}

void anneal (void)
{
 int i, j, k, l, p, q, r;
 double t, e;
 memset (a, 0, sizeof (a));
 memset (left, 0, sizeof (left));
 memset (right, 0, sizeof (right));
 l = 1; // cells
 for (i = MaxK; i < m + MaxK; i++)
  for (j = MaxK; j < n + MaxK; j++)
   a[i][j] = l++;
 k = 1; // tiles
 for (i = 1; i < m + MaxK; i++)
  for (j = 1; j < n + MaxK; j++)
  {
   r = 0;
   for (p = 0; p < MaxK; p++)
    for (q = 0; q < MaxK; q++)
     if (b[p][q])
      left[k][r++] = a[i + p][j + q];
   k++;
  }
 for (i = 1; i < l; i++)
 {
  r = 0;
  for (j = 1; j < k; j++)
   for (p = 0; p < NUM; p++)
    if (left[j][p] == i)
     right[i][r++] = j;
  assert (r == NUM);
 }
 // left is from tile to cell
 // right is from cell to tile
 memset (cell, 0, sizeof (cell));
 memset (tile, 0, sizeof (tile));
 count = 0;
 for (i = 1; i < k; i++)
  add (i);
 for (q = 0; q < TRIES; q++) for (t = MinT; t < MaxT; t += DeltaT)
 {
  oldcount = count;
  r = rand () % MaxS + 1;
  for (i = 0; i < r; i++)
  {
   if (count <= 0) break;
   do
   {
    x[i] = rand () % (k - 1) + 1;
   }
   while (!tile[x[i]]);
   rem (x[i]);
   if (count >= 0 && i + 1 < r)
   {
    int z, w;
    z = 0;
    w = 0;
    for (j = 0; j < NUM; j++)
     if ((w = left[x[i]][j]) && cell[w])
      z++;
    if (!z) continue;
    z = rand () % z;
    for (j = 0; j < NUM; j++)
     if ((w = left[x[i]][j]) && cell[w])
     {
      z--;
      if (z < 0)
       break;
     }
    z = w;
    w = rand () % cell[z];
    for (j = 0; j < NUM; j++)
     if (tile[right[z][j]])
     {
      w--;
      if (w < 0)
       break;
     }
    i++;
    x[i] = right[z][j];
    rem (x[i]);
   }
  }
  r = i;
  p = 0;
  for (i = 1; i < l; i++)
   if (!cell[i])
   {
    y[p] = right[i][rand () % NUM];
    add (y[p]);
    p++;
   }
  if (min > count)
   min = count;
  if (count < oldcount)
  {
   e = 1048576 * exp (t) * (oldcount - count);
   if (rand () & 1048575 >= e)
   {
    for (p--; p >= 0; p--)
     rem (y[p]);
    for (r--; r >= 0; r--)
     add (x[r]);
   }
  }
 }
}

int main (void)
{
 int i, j;
 char c;
 srand (12314);
 freopen (TASKNAME ".in", "r", stdin);
 freopen (TASKNAME ".out", "w", stdout);
 while (scanf (" %d %d", &m, &n) != EOF)
 {
  assert (1 <= m && m <= MaxN);
  assert (1 <= n && n <= MaxN);
  for (i = 0; i < MaxK; i++)
   for (j = 0; j < MaxK; j++)
   {
    assert (scanf (" %c", &c) == 1);
    assert (c == 'X' || c == '.');
    b[j][i] = (c == 'X');
   }
  count = 0;
  for (i = 0; i < MaxK; i++)
   for (j = 0; j < MaxK; j++)
    if (b[i][j])
     count++;
  assert (count == NUM);
  min = MaxL;
  pattern ();
  anneal ();
  printf ("%d\n", min);
 }
 return 0;
}
