주어진 N x M 크기의 정수 배열을 명령 순서대로 변환시킨 최종 형태를 반환하면 된다. 명령은 1 ~ 6으로 총 6가지이다. 각각의 명령은 다음과 같다.
배열의 구역은 배열을 일정한 크기로 4등분 하였을 때 다음과 같은 형태로 구역이 나뉜다.
2차원 배열을 생성하고 각각의 명령에 맞게 맞는 위치로 데이터를 옮길 수 있다. 하지만 이런 방식으로 하면 메모리 소모가 많기 때문에 그냥 각각의 원소를 위치와 데이터를 가진 객체로 다룬다.
class Element {
int row, col;
final int data;
public Element(int row, int col, int data) {
this.row = row;
this.col = col;
this.data = data;
}
}
각각의 명령에 대한 처리는 규칙을 확인하면 쉽게 다룰 수 있다. (6 x 4 크기 배열의 원소별 위치들이 어떻게 변경되는지 확인해보면 규칙을 확인할 수 있다.) 각 규칙들을 적용하여 배열 형태를 변환한다. 마지막으로 각 요소들을 탐색하면서 2차원 배열을 생성한다.
public int[][] getArray() {
int[][] array = new int[rowSize][colSize];
elements.forEach(element -> array[element.row][element.col] = element.data);
return array;
}
// Input : N -> Row size, M -> Column size, R -> Number of command
StringTokenizer tokenizer = new StringTokenizer(reader.readLine());
int N = Integer.parseInt(tokenizer.nextToken());
int M = Integer.parseInt(tokenizer.nextToken());
int R = Integer.parseInt(tokenizer.nextToken());
// Input : Base array
int[][] array = new int[N][M];
for (int n = 0; n < N; n++) {
tokenizer = new StringTokenizer(reader.readLine());
for (int m = 0; m < M; m++) {
array[n][m] = Integer.parseInt(tokenizer.nextToken());
}
}
ArrayConverter arrayConverter = new ArrayConverter(array);
// Input : Command Type -> Convert array with by command
tokenizer = new StringTokenizer(reader.readLine());
while (R-- > 0) {
int command = Integer.parseInt(tokenizer.nextToken());
arrayConverter.convert(command);
}
// Get final array after following every command
array = arrayConverter.createArray();
// Output : Print final array
for (int[] nums : array) {
for (int num : nums) result.append(num).append(" ");
result.append('\n');
}
/**
* Do converting calculations of 2D int array
*/
class ArrayConverter {
private final List<Element> elements = new ArrayList<>();
private int rowSize, colSize;
public ArrayConverter(int[][] elements) {
rowSize = elements.length;
colSize = elements[0].length;
for (int r = 0; r < rowSize; r++)
for (int c = 0; c < colSize; c++)
this.elements.add(new Element(r, c, elements[r][c]));
}
/**
* Get array of current state
* @return Current array
*/
public int[][] createArray() {
int[][] array = new int[rowSize][colSize];
elements.forEach(element -> array[element.row][element.col] = element.data);
return array;
}
/**
* Reads command and convert array
* @param command Command type 1, 2, 3, 4, 5, 6
*/
public void convert(int command) {
switch (command) {
case 1 -> invertVertical();
case 2 -> invertHorizontal();
case 3 -> rotateClockwise();
case 4 -> rotateCounterClockwise();
case 5 -> rotateSectionClockwise();
case 6 -> rotateSectionCounterClockwise();
}
}
/**
* Invert array in vertical direction
*/
private void invertVertical() {
elements.forEach(element -> element.row = rowSize - element.row - 1);
}
/**
* Invert array in horizontal direction
*/
private void invertHorizontal() {
elements.forEach(element -> element.col = colSize - element.col - 1);
}
/**
* Rotate array in clockwise based on middle of array
*/
private void rotateClockwise() {
elements.forEach(element -> {
int preRow = element.row;
element.row = element.col;
element.col = rowSize - preRow - 1;
});
int preRowSize = rowSize;
rowSize = colSize;
colSize = preRowSize;
}
/**
* Rotate array in counterclockwise based on middle of array
*/
private void rotateCounterClockwise() {
elements.forEach(element -> {
int preCol = element.col;
element.col = element.row;
element.row = colSize - preCol - 1;
});
int preColSize = colSize;
colSize = rowSize;
rowSize = preColSize;
}
/**
* Rotate array by section (1 -> 2 -> 3 -> 4 -> 1)
*/
private void rotateSectionClockwise() {
elements.forEach(element -> {
switch (checkSection(element)) {
case 1 -> element.col += colSize / 2;
case 2 -> element.row += rowSize / 2;
case 3 -> element.col -= colSize / 2;
case 4 -> element.row -= rowSize / 2;
}
});
}
/**
* Rotate array by section (1 -> 4 -> 3 -> 2 -> 1)
*/
private void rotateSectionCounterClockwise() {
elements.forEach(element -> {
switch (checkSection(element)) {
case 1 -> element.row += rowSize / 2;
case 2 -> element.col -= colSize / 2;
case 3 -> element.row -= rowSize / 2;
case 4 -> element.col += colSize / 2;
}
});
}
/**
* Check the element section
* @param element Element with row and column
* @return Section number (1, 2, 3, 4)
*/
private int checkSection(Element element) {
if (element.row < rowSize / 2 && element.col < colSize / 2) return 1;
else if (element.row < rowSize / 2) return 2;
else if (element.col < colSize / 2) return 4;
else return 3;
}
}
class Element {
int row, col;
final int data;
public Element(int row, int col, int data) {
this.row = row;
this.col = col;
this.data = data;
}
}
너무 좋은 글이네요. 공유해주셔서 감사합니다.