Magicsq.java

/*
 * $Id: Magicsq.java,v 1.12 2008/02/25 08:35:51 koga Exp $
 * 
 * Copyright (C) 2004 Koga Laboratory. All rights reserved.
 */
package org.mklab.tool.matrix;

import org.mklab.nfc.matrix.DoubleMatrix;
import org.mklab.nfc.matrix.IntMatrix;


/**
 * 魔方陣を求めるクラスです。
 * 
 * <p> Magic Square
 * 
 * @author koga
 * @version $Revision: 1.12 $
 */
public class Magicsq {

  /**
   * <code>size</code>×<code>size</code>の魔方陣を求めます。
   * 
   * @param size 次数
   * @return 魔方陣 (magic square)
   */
  public static DoubleMatrix magicsq(int size) {
    DoubleMatrix A = new DoubleMatrix(size, size);
    DoubleMatrix M = new DoubleMatrix(size, size);
    if (size % 2 == 0) {
      // Make a seed matrix of magic square of even-order
      for (int i = 1; i <= size / 2; i++) {
        for (int j = 1; j <= size; j++) {
          if (i % 2 != 0) {
            A.setElement(i, j, j);
            A.setElement(size - i + 1, j, j);
          } else {
            A.setElement(i, j, size - j + 1);
            A.setElement(size - i + 1, j, size - j + 1);
          }
        }
      }

      // 4m + 2 order
      if ((size - 2) % 4 == 0) {
        A.setSubMatrix(size / 2, size / 2, 1, A.getColumnSize(), A.getSubMatrix(size / 2, size / 2, 1, A.getColumnSize()).flipLeftRight());
        A.setSubMatrix(size / 2, size / 2, IntMatrix.series(size / 2, size / 2 + 1), A.getSubMatrix(size / 2, size / 2, IntMatrix.series(size / 2 + 1, size / 2)));
        A.setSubMatrix(size, size, IntMatrix.series(size / 2, size / 2 + 1), A.getSubMatrix(size, size, IntMatrix.series(size / 2 + 1, size / 2)));
      }

      for (int i = 1; i <= size; i++) {
        for (int j = 1; j <= size; j++) {
          M.setElement(i, j, A.getDoubleElement(i, j) + size * (A.getDoubleElement(j, i) - 1));
        }
      }
    } else {
      // odd order
      int k = 0;
      for (int i = -size / 2; i <= size / 2; i++) {
        for (int j = 0; j < size; j++) {
          M.setElement((j - i + size % size) + 1, (j + i + size % size) + 1, ++k);
        }
      }
    }

    return M;
  }

}