/*
 * File:    Order5.cpp
 * Author:  S Harry White
 * Created: 2009-07-09
 * Updated: 2022-01-17
 *   Tidy code.
 */

/*
      Monday 2022-01-17 11:46:26 Newfoundland Standard Time

      Output files are in folder Order5

      Center  1,25 number of squares   4365792, elapsed time  0:13
      Center  2,24 number of squares   5464716, elapsed time  0:14
      Center  3,23 number of squares   7659936, elapsed time  0:18
      Center  4,22 number of squares   7835348, elapsed time  0:19
      Center  5,21 number of squares   9727224, elapsed time  0:21
      Center  6,20 number of squares  10403516, elapsed time  0:23
      Center  7,19 number of squares  12067524, elapsed time  0:25
      Center  8,18 number of squares  12448644, elapsed time  0:26
      Center  9,17 number of squares  13890160, elapsed time  0:27
      Center 10,16 number of squares  13376136, elapsed time  0:28
      Center 11,15 number of squares  15735272, elapsed time  0:30
      Center 12,14 number of squares  15138472, elapsed time  0:29
      Center 13    number of squares  19079744, elapsed time  0:28

             total number of squares 275305224, elapsed time  5:01
 */

#include "stdafx.h"
#include <conio.h>
#include <direct.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <share.h>
#include <sys\stat.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <Windows.h>

const bool F=false, T=true;
const int N=5, NN=N*N,

// zero based
          Mid=(NN-1) / 2,      // 12
          MagicConstant=Mid*N; // 60

int X[N][N], *P[N]={ &X[0][0], &X[1][0], &X[2][0], &X[3][0], &X[4][0] },
    Y[N][N], *Q[N]={ &Y[0][0], &Y[1][0], &Y[2][0], &Y[3][0], &Y[4][0] };

// Combinations of N chosen from 0 .. NN-1 that total to MagicConstant.

// Combinations that contain K where K is one of 0 .. Mid.
const int maxKCombos=302; int KCombos[maxKCombos][N+1], numKCombos;

// Permutations of KCombos with K omitted.
const int maxCenterKPermus=7248; int CenterKPermus[maxCenterKPermus][N], numCenterKPermus;

// CenterKPermus in which the third number is greater than the second.
const int maxCenterKUPermus=3624; int *CenterKUPermus[maxCenterKUPermus], sizeCenterKUPermus;

struct spu { int *p, u; };

const int maxCenterKPermusIJ=22;
// CenterKPermus indexed by the first and fourth.
spu CenterKPermus14[NN][NN][maxCenterKPermusIJ]; int sizeCenterKPermus14[NN][NN];

// CenterKPermus indexed by the second and third.
spu CenterKPermus23[NN][NN][maxCenterKPermusIJ]; int sizeCenterKPermus23[NN][NN];

// Combinations that do not contain K.
const int maxOKCombos=1150; int OKCombos[maxOKCombos][N], numOKCombos;

// Permutations of OKCombos.
const int maxOKPermus=138000; /* 1150 x 5! */ int OKPermus[maxOKPermus][N], numOKPermus;

const int maxOKPermusIJ=330;
// OKPermus in which the fourth is greater than the second,
// indexed by the second and fourth.
spu OKUPermus24[NN][NN][maxOKPermusIJ]; int sizeOKUPermus24[NN][NN];

// OKPermus indexed by the first, second and fifth.
const int maxOKPermusIJK=20;
spu OKPermus125[NN][NN][NN][maxOKPermusIJK]; int sizeOKPermus125[NN][NN][NN];

// OKPermus in which the fourth is greater than the second,
// indexed by the second, third and fourth.
spu OKUPermus234[NN][NN][NN][maxOKPermusIJK]; int sizeOKUPermus234[NN][NN][NN],

// Fourth of OKPermus indexed by the first, second, third and fifth.
    OKPermus1235[NN][NN][NN][NN],
// Third of OKPermus indexed by the first, second, fourth and fifth.
    OKPermus1245[NN][NN][NN][NN];
//================================================ output ==============================================

const int bufSize=128;
bool openDir() {
//   -------
  int sub=0; char buf[bufSize], msg[bufSize]; const char *baseName="Order5";
  strcpy_s(buf, bufSize, baseName);
  do {
    if (_mkdir(buf)!=-1) break;
    if (errno!=EEXIST) { sprintf_s(msg, bufSize, "Can't make folder %s", buf); perror(msg); return F; }
    sprintf_s(buf, bufSize, "%s_%d", baseName, ++sub);
  } while (T);
  if (_chdir(buf)==-1) { sprintf_s(msg, bufSize, "Can't open folder %s", buf); perror(msg); return F; }
  printf("Output files are in folder %s\n\n", buf); return T;
} // openDir

int openFile(const int K) {
//  --------
  int wfd=-1; char buf[bufSize]; sprintf_s(buf, bufSize, "Center%d.txt", K);
  _sopen_s(&wfd, buf, _O_CREAT|_O_WRONLY, _SH_DENYWR, _S_IREAD);
  if (wfd==-1) {
    char msg[bufSize]; sprintf_s(msg, bufSize, "\a\nCan't open for write %s", buf); perror(msg);
  }
  return wfd;
} // openFile

bool openFiles(const int K, int *wfdK, int *wfdCK) {
//   ---------
  if ((*wfdK=openFile(K+1))==-1) return F;
  if (K==Mid) *wfdCK =-1;  else if ((*wfdCK=openFile(NN-K))==-1) return F; return T;
} // openFiles

void closeFiles(const int wfd, const int wfdC) { if (wfd!=-1) _close(wfd); if (wfdC!=-1) _close(wfdC); }
//   ----------

const int squareBytes=76, numSquares=1048576, outSize=numSquares*squareBytes;
char outputBuffer1[outSize], outputBuffer2[outSize], *outPointer1=NULL, *outPointer2=NULL; int outSquares;
void writeSquares (int *X[N]) {
//   ------------
  const int t0='1', t1='0'-9, t2='0'-19; char *s=outPointer1; int a;
  for (int r=0; r<N; ++r) {
    for (int c=0; c<N; ++c) {
      a=X[r][c]; if (a<9) { *s++=' '; *s++=t0+a; } else if (a<19) { *s++='1'; *s++=t1+a; }
      else { *s++='2'; *s++=t2+a; } *s++=' ';
    }
    *--s='\n'; ++s;
  }
  *s++='\n'; outPointer1=s;
  if (outPointer2!=NULL) {
    const int c0='0'+25, c1='0'+15, c2='0'+5; char *s=outPointer2;
    for (int r=0; r<N; ++r) {
      for (int c=0; c<N; ++c) {
        a=X[r][c]; if (a>15) { *s++=' '; *s++=c0-a; } else if (a>5) { *s++='1'; *s++=c1-a; }
        else { *s++='2'; *s++=c2-a; } *s++=' ';
      }
      *--s='\n'; ++s;
    }
    *s++='\n'; outPointer2=s;
  }
} // writeSquares

bool writeOut(const int outBytes, const int wfd, const int wfdC) {
//   --------
  if (_write(wfd, outputBuffer1, outBytes)!=outBytes) return F; outPointer1=outputBuffer1; outSquares=0;
  if (wfdC!=-1) { if (_write(wfdC, outputBuffer2, outBytes)!=outBytes) return F; outPointer2=outputBuffer2; }
  return T;
} // writeOut

void swapRowsCols1(int *X[N], const int w) {
//   -------------
  const int y=N-1-w; int *tmp=X[w]; X[w]=X[y]; X[y]=tmp;
  for (int r=0; r<N; ++r) { const int tmp=X[r][w]; X[r][w]=X[r][y]; X[r][y]=tmp; }
} // swapRowsCols1

void swapRowsCols2(int *X[N], const int w, const int x) {
//   -------------
  const int y=N-1-w, z=N-1-x; int *tmp=X[w]; X[w]=X[x]; X[x]=tmp; tmp=X[y]; X[y]=X[z]; X[z]=tmp;
  for (int r=0; r<N; ++r) {
    int tmp=X[r][w]; X[r][w]=X[r][x]; X[r][x]=tmp; tmp=X[r][y]; X[r][y]=X[r][z]; X[r][z]=tmp;
  }
} // swapRowsCols2

bool outputSquares(const int wfd, const int wfdC) {
//   -------------
  for (int r=0; r<N; ++r) for (int c=0; c<N; ++c) Q[r][c]=P[r][c]; writeSquares(P); 
  swapRowsCols2(P,0,1); /* xform 2 */ writeSquares(P);
  swapRowsCols1(Q,0);   /* xform 1 */ writeSquares(Q);
  swapRowsCols2(Q,0,1); /* xform 2 of 1 */ writeSquares(Q); 
  outSquares+=4; if ((outSquares==numSquares)&&!writeOut(outSize, wfd, wfdC)) return F; return T;
} // outputSquares
//============================================== make ===============================================

void putCombo(const int K, const int a, const int b, const int c, const int d, const int e) {
//   --------
  int *p;
  if ((a==K)||(b==K)||(c==K)||(d==K)||(e==K)) {
    p=KCombos[numKCombos++]; p[5]=((1<<a)|(1<<b)|(1<<c)|(1<<d)|(1<<e))&~(1<<K);
  } else p=OKCombos[numOKCombos++];
  p[0]=a; p[1]=b; p[2]=c; p[3]=d; p[4]=e;
} // putKCombo

void getCombos(const int K) {
//   ---------
  numKCombos=0; numOKCombos=0;
  for (int i=0; i<(NN-4); i++)
    for (int j=i+1; j<(NN-3); j++)
      for (int k=j+1; k<(NN-2); k++)
        for (int l=k+1; l<(NN-1); l++)
          for (int m=l+1; m<NN; m++)
            if ((i+j+k+l+m)==MagicConstant) putCombo(K, i, j, k, l, m);
} // getCombos

void permuteCenterK_3(const int K, const int a, const int b, const int c, const int d, const int e, const int u) {
//   ----------------
  if (c==K) {
    int *p=CenterKPermus[numCenterKPermus++]; p[0]=a; p[1]=b; p[2]=d; p[3]=e; spu *q;
    q=&(CenterKPermus14[a][e][(sizeCenterKPermus14[a][e])++]); q->p=p; q->u=(1<<b)|(1<<d);
    q=&(CenterKPermus23[b][d][(sizeCenterKPermus23[b][d])++]); q->p=p; q->u=(1<<a)|(1<<e);
    if (d>b) { CenterKUPermus[sizeCenterKUPermus++]=p; p[4]=u; }

    p=CenterKPermus[numCenterKPermus++]; p[0]=a; p[1]=b; p[2]=e; p[3]=d;
    q=&(CenterKPermus14[a][d][(sizeCenterKPermus14[a][d])++]); q->p=p; q->u=(1<<b)|(1<<e);
    q=&(CenterKPermus23[b][e][(sizeCenterKPermus23[b][e])++]); q->p=p; q->u=(1<<a)|(1<<d);
    if (e>b) { CenterKUPermus[sizeCenterKUPermus++]=p; p[4]=u; }
  } else if (d==K) {
    int *p=CenterKPermus[numCenterKPermus++]; p[0]=a; p[1]=b; p[2]=c; p[3]=e; spu *q;
    q=&(CenterKPermus14[a][e][(sizeCenterKPermus14[a][e])++]); q->p=p; q->u=(1<<b)|(1<<c);
    q=&(CenterKPermus23[b][c][(sizeCenterKPermus23[b][c])++]); q->p=p; q->u=(1<<a)|(1<<e);
    if (c>b) { CenterKUPermus[sizeCenterKUPermus++]=p; p[4]=u; }

    p=CenterKPermus[numCenterKPermus++]; p[0]=a; p[1]=b; p[2]=e; p[3]=c;
    q=&(CenterKPermus14[a][c][(sizeCenterKPermus14[a][c])++]); q->p=p; q->u=(1<<b)|(1<<e);
    q=&(CenterKPermus23[b][e][(sizeCenterKPermus23[b][e])++]); q->p=p; q->u=(1<<a)|(1<<c);
    if (e>b) { CenterKUPermus[sizeCenterKUPermus++]=p; p[4]=u; }
  } else if (e==K) {
    int *p=CenterKPermus[numCenterKPermus++]; p[0]=a; p[1]=b; p[2]=c; p[3]=d; spu *q;
    q=&(CenterKPermus14[a][d][(sizeCenterKPermus14[a][d])++]); q->p=p; q->u=(1<<b)|(1<<c);
    q=&(CenterKPermus23[b][c][(sizeCenterKPermus23[b][c])++]); q->p=p; q->u=(1<<a)|(1<<d);
    if (c>b) { CenterKUPermus[sizeCenterKUPermus++]=p; p[4]=u; }

    p=CenterKPermus[numCenterKPermus++]; p[0]=a; p[1]=b; p[2]=d; p[3]=c;
    q=&(CenterKPermus14[a][c][(sizeCenterKPermus14[a][c])++]); q->p=p; q->u=(1<<b)|(1<<d);
    q=&(CenterKPermus23[b][d][(sizeCenterKPermus23[b][d])++]); q->p=p; q->u=(1<<a)|(1<<c);
    if (d>b) { CenterKUPermus[sizeCenterKUPermus++]=p; p[4]=u; }
  }
} // permuteCenterK_

void permuteK_4(const int K, const int a, const int b, const int c, const int d, const int e, const int u) {
//   ----------
  permuteCenterK_3(K, a, b, c, d, e, u); permuteCenterK_3(K, a, c, b, d, e, u);
  permuteCenterK_3(K, a, d, c, b, e, u); permuteCenterK_3(K, a, e, c, d, b, u);
} // permuteK_4

void getCenterKPermus(const int K) {
//   ----------------
  numCenterKPermus=0; sizeCenterKUPermus=0;
  for (int i=0; i<NN; i++) for (int j=0; j<NN; j++) {
    sizeCenterKPermus14[i][j]=0; sizeCenterKPermus23[i][j]=0;
  }
  for (int i=0; i<numKCombos; i++) {
    const int *p=KCombos[i], a=p[0], b=p[1], c=p[2], d=p[3], e=p[4], u=p[5];
    permuteK_4(K, a, b, c, d, e, u); permuteK_4(K, b, a, c, d, e, u); permuteK_4(K, c, b, a, d, e, u);
    permuteK_4(K, d, b, c, a, e, u); permuteK_4(K, e, b, c, d, a, u);
  }
} // getCenterKPermus

void permuteOK_3(const int a, const int b, const int c, const int d, const int e) {
//   -----------
  int *p, t; spu *q;

  p=OKPermus[numOKPermus++]; p[0]=a; p[1]=b; p[2]=c; p[3]=d; p[4]=e;
  q=&(OKPermus125[a][b][e][(sizeOKPermus125[a][b][e])++]); q->p=p; q->u=(1<<c)|(1<<d);
  OKPermus1235[a][b][c][e]=d; OKPermus1245[a][b][d][e]=c;
  if (d>b) {
    q=&(OKUPermus234[b][c][d][(sizeOKUPermus234[b][c][d])++]); q->p=p; q->u=t=(1<<a)|(1<<e);
    q=&(OKUPermus24[b][d][(sizeOKUPermus24[b][d])++]); q->p=p; q->u=t|(1<<c);
  }

  p=OKPermus[numOKPermus++]; p[0]=a; p[1]=b; p[2]=c; p[3]=e; p[4]=d;
  q=&(OKPermus125[a][b][d][(sizeOKPermus125[a][b][d])++]); q->p=p; q->u=(1<<c)|(1<<e);
  OKPermus1235[a][b][c][d]=e; OKPermus1245[a][b][e][d]=c;
  if (e>b) {
    q=&(OKUPermus234[b][c][e][(sizeOKUPermus234[b][c][e])++]); q->p=p; q->u=t=(1<<a)|(1<<d);
    q=&(OKUPermus24[b][e][(sizeOKUPermus24[b][e])++]); q->p=p; q->u=t|(1<<c);
  }

  p=OKPermus[numOKPermus++]; p[0]=a; p[1]=b; p[2]=d; p[3]=c; p[4]=e;
  q=&(OKPermus125[a][b][e][(sizeOKPermus125[a][b][e])++]); q->p=p; q->u=(1<<c)|(1<<d);
  OKPermus1235[a][b][d][e]=c; OKPermus1245[a][b][c][e]=d;
  if (c>b) {
    q=&(OKUPermus234[b][d][c][(sizeOKUPermus234[b][d][c])++]); q->p=p; q->u=t=(1<<a)|(1<<e);
    q=&(OKUPermus24[b][c][(sizeOKUPermus24[b][c])++]); q->p=p; q->u=t|(1<<d);
  }

  p=OKPermus[numOKPermus++]; p[0]=a; p[1]=b; p[2]=d; p[3]=e; p[4]=c;
  q=&(OKPermus125[a][b][c][(sizeOKPermus125[a][b][c])++]); q->p=p; q->u=(1<<d)|(1<<e);
  OKPermus1235[a][b][d][c]=e; OKPermus1245[a][b][e][c]=d;
  if (e>b) {
    q=&(OKUPermus234[b][d][e][(sizeOKUPermus234[b][d][e])++]); q->p=p; q->u=t=(1<<a)|(1<<c);
    q=&(OKUPermus24[b][e][(sizeOKUPermus24[b][e])++]); q->p=p; q->u=t|(1<<d);
  }

  p=OKPermus[numOKPermus++]; p[0]=a; p[1]=b; p[2]=e; p[3]=c; p[4]=d;
  q=&(OKPermus125[a][b][d][(sizeOKPermus125[a][b][d])++]); q->p=p; q->u=(1<<c)|(1<<e);
  OKPermus1235[a][b][e][d]=c; OKPermus1245[a][b][c][d]=e;
  if (c>b) {
    q=&(OKUPermus234[b][e][c][(sizeOKUPermus234[b][e][c])++]); q->p=p; q->u=t=(1<<a)|(1<<d);
    q=&(OKUPermus24[b][c][(sizeOKUPermus24[b][c])++]); q->p=p; q->u=t|(1<<e);
  }

  p=OKPermus[numOKPermus++]; p[0]=a; p[1]=b; p[2]=e; p[3]=d; p[4]=c;
  q=&(OKPermus125[a][b][c][(sizeOKPermus125[a][b][c])++]); q->p=p; q->u=(1<<d)|(1<<e);
  OKPermus1235[a][b][e][c]=d; OKPermus1245[a][b][d][c]=e;
  if (d>b) {
    q=&(OKUPermus234[b][e][d][(sizeOKUPermus234[b][e][d])++]); q->p=p; q->u=t=(1<<a)|(1<<c);
    q=&(OKUPermus24[b][d][(sizeOKUPermus24[b][d])++]); q->p=p; q->u=t|(1<<e);
  }
} // permuteOK_3

void permuteOK_4(const int a, const int b, const int c, const int d, const int e) {
//   -----------
  permuteOK_3(a, b, c, d, e); permuteOK_3(a, c, b, d, e);
  permuteOK_3(a, d, c, b, e); permuteOK_3(a, e, c, d, b);
} // permuteOK_4

void getOKPermus() {
//   -----------
  numOKPermus=0;
  for (int i=0; i<NN; i++) for (int j=0; j<NN; j++) { sizeOKUPermus24[i][j]=0;
    for (int k=0; k<NN; k++) {
      sizeOKPermus125[i][j][k]=0; sizeOKUPermus234[i][j][k]=0;
      for (int l=0; l<NN; l++) { OKPermus1235[i][j][k][l]=-1; OKPermus1245[i][j][k][l]=-1; }
    }
  }
  for (int i=0; i<numOKCombos; i++) {
    int *p=OKCombos[i], a=p[0], b=p[1], c=p[2], d=p[3], e=p[4];
    permuteOK_4(a, b, c, d, e); permuteOK_4(b, a, c, d, e); permuteOK_4(c, b, a, d, e);
    permuteOK_4(d, b, c, a, e); permuteOK_4(e, b, c, d, a);
  }
} // getOKPermus 

// Used to disable some pairs of diagonal permutations.
struct bools { union { bool off[NN][NN][NN][NN][NN][NN]; int align[(NN*NN*NN*NN*NN*NN+3)/4]; } u; };
bools noOff, diags;

// fill order: \dia, /dia, r 1, c 0, c 4, a[3][2], r 2, c 2, c 1, a[0][3], a[4][3]
//
//  1 21 19 23  5
//  9  2 10  6 11
// 12 17  0 18 14
// 13  7 16  3 15
//  8 22 20 24  4

int makeCenterKSquares(const int K, const int wfd, const int wfdC) {
//  ------------------
  int count=0, i0=sizeCenterKUPermus, **p0=CenterKUPermus; // B2>B1
  while (i0--) { // \ back diagonal B   
    const int *B=*p0, B0=B[0], B1=B[1], B2=B[2], B3=B[3];
          int i1=sizeCenterKUPermus, **p1=CenterKUPermus; // F2>F1
    while (i1--) { // / forward diagonal D
      const int *D=*p1; if ( (D[1]>B1)&&(!(D[4]&B[4])) ) {
      const int F0=D[0], F1=D[1], F2=D[2], F3=D[3];
      // F2>F1 and F1>B1, so F2>B1, (see second column below).

      if (diags.u.off[B0][B1][B2][F0][F1][F2]) { ++p1; continue; }

      // Count 4: the square, xform 1, xform 2, and xform 2 of xform 1.
      if (F3<F0) {    // xform 1: Turn off its xform 2 and skip.
        if (B3>B0) {  // xform 2
          if (F3>B0) diags.u.off[B1][B0][B3][F2][F3][F0]=T; else diags.u.off[F2][F3][F0][B1][B0][B3]=T;
        } else {     // xform 2, reverse B
          if (F3>B3) diags.u.off[B2][B3][B0][F2][F3][F0]=T; else diags.u.off[F2][F3][F0][B2][B3][B0]=T;
        }
        ++p1; continue;
      } else {       // Turn off xform 2.
		    if (B3>B0) { // xform 2
          if (F0>B0) diags.u.off[B1][B0][B3][F1][F0][F3]=T; else diags.u.off[F1][F0][F3][B1][B0][B3]=T;
		    } else {     // xform 2, reverse B
		      if (F0>B3) diags.u.off[B2][B3][B0][F1][F0][F3]=T; else diags.u.off[F1][F0][F3][B2][B3][B0]=T;
		    }
      }

      const int fUsed=D[4]|B[4]; spu *p2=OKUPermus24[B1][F1]; int i2=sizeOKUPermus24[B1][F1];
      while (i2--) { if (!(p2->u&fUsed)) { // second row
        const int *r1=p2->p, r1Used=p2->u|fUsed;
        spu *p3=OKPermus125[B0][r1[0]][F3]; int i3=sizeOKPermus125[B0][r1[0]][F3];
        while (i3--) { if (!(p3->u&r1Used)) { // first column;
          const int *c0=p3->p, c0Used=p3->u|r1Used;
          spu *p4=OKPermus125[F0][r1[4]][B3]; int i4=sizeOKPermus125[F0][r1[4]][B3];
          while (i4--) { if (!(p4->u&c0Used)) { // fifth column
            const int *c4=p4->p, a32=OKPermus1245[c0[3]][F2][B2][c4[3]];
            int c4Used=p4->u|c0Used; if ( (a32>=0)&&(!(c4Used&(1<<a32))) ) { c4Used|=(1<<a32);
            spu *p5=CenterKPermus14[c0[2]][c4[2]]; int i5=sizeCenterKPermus14[c0[2]][c4[2]];
            while (i5--) { if (!(p5->u&c4Used)) { // third row            
              const int *r2=p5->p, r2Used=p5->u|c4Used;
              spu *p6=CenterKPermus23[r1[2]][a32]; int i6=sizeCenterKPermus23[r1[2]][a32];
              while (i6--) { if (!(p6->u&r2Used)) { // third column
                const int *c2=p6->p, c2Used=p6->u|r2Used;
                spu *p7=OKUPermus234[B1][r2[1]][F2]; int i7=sizeOKUPermus234[B1][r2[1]][F2];
                while (i7--) { if (!(p7->u&c2Used)) { // second column
                  const int *c1=p7->p, c1Used=p7->u|c2Used, a03=OKPermus1235[B0][p7->p[0]][c2[0]][F0];
                  if ((a03>=0)&&!(c1Used&(1<<a03))) {
                    P[0][0]=B0; P[0][1]=c1[0]; P[0][2]=c2[0]; P[0][3]=a03; P[0][4]=F0;
                    P[1][0]=r1[0]; P[1][1]=B1; P[1][2]=r1[2]; P[1][3]=F1; P[1][4]=r1[4];
                    P[2][0]=c0[2]; P[2][1]=r2[1]; P[2][2]=K; P[2][3]=r2[2]; P[2][4]=c4[2];
                    P[3][0]=c0[3]; P[3][1]=F2; P[3][2]=a32; P[3][3]=B2; P[3][4]=c4[3];
                    P[4][0]=F3; P[4][1]=c1[4]; P[4][2]=c2[3]; P[4][3]=OKPermus1235[F3][c1[4]][c2[3]][B3];
                    P[4][4]=B3; if (!outputSquares(wfd, wfdC)) return 0; ++count;
                  }
                } ++p7; }
              } ++p6; }
            } ++p5; }
          }} ++p4; }
        } ++p3; }
      } ++p2; }
    } ++p1; } ++p0;
  }
  if (!writeOut(outSquares*squareBytes, wfd, wfdC)) return 0; return count;
} // makeCenterKSquares 

void printElapsedTime(time_t startTime) {
//   ---------------- 
  const int et=(int)difftime(time(NULL), startTime); printf("%2d:%02d\n", et/60, et%60);
} // printElapsedTime

bool makeSquares() {
//   -----------
  int count=0; time_t startTime=time(NULL); int wfdK=-1, wfdCK=-1;
  for (int K=0; K <= Mid; ++K) if (openFiles(K, &wfdK, &wfdCK)) {
    time_t startTimeK=time(NULL); getCombos(K); getCenterKPermus(K); getOKPermus();
    outPointer1=outputBuffer1; outSquares=0; outPointer2=wfdCK==-1 ? NULL : outputBuffer2;
    int Kcount=makeCenterKSquares(K, wfdK, wfdCK);
    if (Kcount==0) { perror("\a\nError writing file"); return F; }
    Kcount*=4; count+=Kcount;
    if (K==Mid) printf("Center %2d    number of squares %9d, elapsed time ", K+1, Kcount);
    else { printf("Center %2d,%2d number of squares %9d, elapsed time ", K+1, NN-K, Kcount);
     count+=Kcount; diags=noOff;
    }
    printElapsedTime(startTimeK); closeFiles(wfdK, wfdCK);
  }
  printf("\n       total number of squares %9d, elapsed time ", count);
  printElapsedTime(startTime); return T;
} // makeSquares

void outputLocalTime() {
//   --------------
  time_t startTime=time(NULL); struct tm local;
  if (localtime_s(&local, &startTime)==0) {
    char dateTime[100];
    size_t slen=strftime(dateTime, 100, "%A %Y-%m-%d %X %Z\n\n\0", &local); printf("\n%s", dateTime);
  }
} // outputLocalTime

int main() {
//  ----
  outputLocalTime(); bool ok=F; if (openDir()) ok=makeSquares();
  printf("\n\nPress a key to close the console");
  while (!_kbhit()) Sleep(250); return ok ? EXIT_SUCCESS : EXIT_FAILURE;
} // main