橋梁モードで螺旋行列アルゴリズムを実現する


先日、「ないぶらせんマトリックスアルゴリズム」の実装を分析し、オブジェクト向けプログラミングの拡張性について議論した文章を書きました.そこで、今日はブリッジモードでコードをいくつか改造しました.具体的には、以下の通りです.
package com.algo;

class Position {
	private int x;
	private int y;

	public Position(int x, int y) {
		this.x = x;
		this.y = y;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}
}

/**
 *       
 */
abstract class Direction {
	protected StartPos startPos;
	protected Position pos;//      
	protected Position periodPos;//          
	protected int max;//       
	protected int min;//       
	protected int len;//      

	private void init() {
		if (startPos == null || len <= 0)
			return;
		Position tempPos = startPos.getPos(len);
		pos = new Position(tempPos.getX(), tempPos.getY());
		periodPos = new Position(tempPos.getX(), tempPos.getY());
		max = len - 1;
		min = 0;
	}

	public void setStartPos(StartPos startPos) {//             
		this.startPos = startPos;
		init();
	}

	public void setLen(int len) {//           
		this.len = len;
		init();
	}

	public int getLen() {
		return len;
	}

	public Position getPos() {
		int currRow = pos.getX();
		int currCol = pos.getY();
		Position currPos = new Position(currRow, currCol);
		genNextPos();
		return currPos;
	}

	protected abstract void genNextPos();
}

/**
 *        
 */
class ClockwiseDir extends Direction {
	protected void genNextPos() {
		int row = pos.getX();
		int col = pos.getY();
		if (row == min && col < max) {
			col++;
		} else if (row < max && col == max) {
			row++;
		} else if (row == max && col > min) {
			col--;
		} else if (row > min && col == min) {
			row--;
		} else{
			return; //        ,     (          )
		}
		if (row == periodPos.getX() && col == periodPos.getY()) {
			min++;
			max--;
			genNextPos();
			periodPos = new Position(pos.getX(), pos.getY());
		} else {
			pos.setX(row);
			pos.setY(col);
		}
	}
}

/**
 *        
 */
class AntiClockwiseDir extends Direction {
	protected void genNextPos() {
		int row = pos.getX();
		int col = pos.getY();
		if (row == min && col > min) {
			col--;
		} else if (row < max && col == min) {
			row++;
		} else if (row == max && col < max) {
			col++;
		} else if (row > min && col == max) {
			row--;
		} else{
			return; //        ,     (          )
		}
		if (row == periodPos.getX() && col == periodPos.getY()) {
			min++;
			max--;
			genNextPos();
			periodPos = new Position(pos.getX(), pos.getY());
		} else {
			pos.setX(row);
			pos.setY(col);
		}
	}
}

/**
 *         
 */
interface StartPos {
	public Position getPos(int len);
}

/**
 *            
 */
class TopLeft implements StartPos {
	public Position getPos(int len) {
		return new Position(0, 0);
	}
}

/**
 *            
 */
class TopRight implements StartPos {
	public Position getPos(int len) {
		return new Position(0, len - 1);
	}
}

/**
 *            
 */
class BottomLeft implements StartPos {
	public Position getPos(int len) {
		return new Position(len - 1, 0);
	}
}

/**
 *            
 */
class BottomRight implements StartPos {
	public Position getPos(int len) {
		return new Position(len - 1, len - 1);
	}
}

public class HelixAlgo {
	public void print(Direction dir,int initVal,int step) {
		int len = dir.getLen();
		if (len <= 0) {
			System.out.println("     0   !");
			return;
		}
		int[][] helix = calculate(dir, len,initVal,step);
		for (int i = 0; i < helix.length; i++) {
			for (int j = 0; j < helix[i].length; j++) {
				System.out.print(helix[i][j] + "\t");
			}
			System.out.println("");
		}
	}

	private int[][] calculate(Direction dir, int len,int val,int step) {
		int[][] helix = new int[len][len];
		for (int i = 0; i < len * len; i++) {
			Position pos = dir.getPos();
			int row = pos.getX();
			int col = pos.getY();
			helix[row][col] = val;
			val+=step;
		}
		return helix;
	}

	public static void main(String[] args) {
		HelixAlgo algo = new HelixAlgo();
		int len = 5;
		Direction dir_clockwise = new ClockwiseDir();
		dir_clockwise.setLen(len); // set         

		Direction dir_antiClockwise = new AntiClockwiseDir();
		dir_antiClockwise.setLen(len);

		System.out.println("
( " + len + "):"); dir_clockwise.setStartPos(new TopLeft()); // set algo.print(dir_clockwise,1,1); System.out.println("
( " + len + "):"); dir_clockwise.setStartPos(new TopRight()); algo.print(dir_clockwise,1,1); System.out.println("
( " + len + "):"); dir_clockwise.setStartPos(new BottomRight()); algo.print(dir_clockwise,1,1); System.out.println("
( " + len + "):"); dir_clockwise.setStartPos(new BottomLeft()); algo.print(dir_clockwise,1,1); System.out.println("
( " + len + "):"); dir_antiClockwise.setStartPos(new TopLeft()); algo.print(dir_antiClockwise,1,1); System.out.println("
( " + len + "):"); dir_antiClockwise.setStartPos(new TopRight()); algo.print(dir_antiClockwise,1,1); System.out.println("
( " + len + "):"); dir_antiClockwise.setStartPos(new BottomRight()); algo.print(dir_antiClockwise,1,1); System.out.println("
( " + len + "):"); dir_antiClockwise.setStartPos(new BottomLeft()); algo.print(dir_antiClockwise,1,1); System.out.println("
( " + len + "):"); dir_antiClockwise.setStartPos(new TopLeft()); algo.print(dir_antiClockwise,len*len,-1); System.out.println("
( " + len + "):"); dir_clockwise.setStartPos(new TopLeft()); algo.print(dir_clockwise,len*len,-1); } }

 
螺旋行列の解題の構想は多くなくて、知らないのは私の前の文章の“インナースパイラルマトリクスアルゴリズム解析”を見ることができて、ここで主にどうして橋梁のモードを使うのかを言います:
まず、スパイラルマトリクスにどのような変化点があるかを見てみましょう.マトリクス次数(すなわち、エッジ長)、初期位置、およびスパイラル方向(時計回り、反時計回り)です.
初期位置の前の文章は返事の中ですでに言及して、合法的な初期位置は4つのマトリクスの4つの角しかなくて、さもなくば路地が現れます(前の文章の10階の返事を参照することができます).
弾性を考慮すると、この3つの変化点は独立して変化できるはずです.マトリクス次数は整数で、その変化は比較的便利ですが、他の2つは異なるインタフェースでカプセル化することができます.つまり、上のコードの「StartPos」インタフェースと「Direction」抽象クラスです.このような2つの変化点は独立して変化することができます.そのため、ブリッジモードを使用することを考えました.この2つの変化点の結合を完全にオブジェクトレベルに移動すると、mian関数の「dir_clockwise」と「dir_antiClockwise」の2つのオブジェクトパッケージの複数の出力が得られる.
その他は多く言わないで、コードは運行することができて、直接機械の上で走ってすぐわかるべきで、何が不足してあるいは疑問がみんなを歓迎していっしょに討論します.