[ 백준 ] 16935 배열 돌리기 3

codesver·2023년 7월 18일
0

Baekjoon

목록 보기
59/72
post-thumbnail

📌 Problem

주어진 N x M 크기의 정수 배열을 명령 순서대로 변환시킨 최종 형태를 반환하면 된다. 명령은 1 ~ 6으로 총 6가지이다. 각각의 명령은 다음과 같다.

  1. 배열을 수직으로 뒤집는다. Ex) (0, 0)은 (N - 1, 0)이 된다.
  2. 배열을 수평으로 뒤집는다. Ex) (0, 0)은 (0, M - 1)이 된다.
  3. 배열의 중심을 기준으로 +90° 회전시킨다. Ex) (0, 0)은 (0, N - 1)이 된다.
  4. 배열의 중심을 기준으로 -90° 회전시킨다. Ex) (0, 0)은 (M - 1, 0)이 된다.
  5. 배열의 각 구역들을 시계방향으로 평행이동 한다. (1 - 2 - 3 - 4 - 1)
  6. 배열의 각 구역들을 반시계방향으로 평행이동 한다. (1 - 4 - 3 - 2 - 1)

배열의 구역은 배열을 일정한 크기로 4등분 하였을 때 다음과 같은 형태로 구역이 나뉜다.

📌 Solution

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;
}

📌 Code

// 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;
    }
}
profile
Hello, Devs!

1개의 댓글

comment-user-thumbnail
2023년 7월 18일

너무 좋은 글이네요. 공유해주셔서 감사합니다.

답글 달기