본문 바로가기

내일배움캠프 안드로이드 3기

[TIL] 24.04.18 알고리즘

1. 알고리즘 문제 해결

 

2x2x2 큐브(백준 16939): 

 단순 구현 문제. 이건 사실 왜 골드2로 책정된건지 조금 의아했다. 잘쳐줘도 실버 하위정도의 난이도를 가진 문제같은데..


 한 번 돌려서 풀 수 있는지를 묻고 있기 때문에, 단순 구현으로 빠르게 처리할 수 있다. 각 축에 대해 한 쪽을 시계방향으로 회전하는 경우와 반시계방향으로 회전하는 경우, 그래서 따져봐야하는 경우는 6가지이다.

 축 별로 한쪽 방향 회전을 만들어둔 후, 세 번 반복하면 반대쪽 방향 회전한 결과와 같기 때문에 그걸 이용해서 풀어도 되지만, 그렇게 하려면 각 칸 배열의 수들을 옮기는 회전 함수를 이용해야 한다.

 하지만 굳이 배열에 매번 바뀌는 값을 assign해서 상태를 검사하는 것보단, 단순하게 6가지 케이스들은 초기 배열을 이용해 바로바로 논리연산 해버리는게 빠르다. 구현을 위한 비용을 따져봐도 조건식을 나름의 논리와 규칙을 가지고 나열하면 생각보다 굉장히 빠르게 작성할 수 있다. 그리고 불필요한 assign이 생기는 게 꺼려져서도 있는데, 사실 이러나 저러나 유의미한 차이는 없다. 

 

 그냥 머리에 떠오르는 그대로 구현하면 되는 문제.

 

#include <iostream>
#include <vector>

using namespace std;

class Cube {
public:
    vector<int> faces;

    Cube() {
        faces = vector<int>(24);
    }

    void insertFaces() {
        for(int i=0; i<24; i++) {
            cin >> faces[i];
        }
    }

    bool checkRotate() {

        if(faces[0]==faces[2]&&faces[0]==faces[22]&&faces[0]==faces[20]
        &&faces[4]==faces[6]&&faces[4]==faces[1]&&faces[4]==faces[3]
        &&faces[8]==faces[10]&&faces[8]==faces[5]&&faces[8]&&faces[7]
        &&faces[23]==faces[21]&&faces[23]==faces[9]&&faces[23]==faces[11]
        &&faces[12]==faces[13]&&faces[12]==faces[14]&&faces[12]==faces[15]
        &&faces[16]==faces[17]&&faces[16]==faces[18]&&faces[16]==faces[19]) {
            return true;
        }
        if(faces[0]==faces[2]&&faces[0]==faces[5]&&faces[0]==faces[7]
        &&faces[4]==faces[6]&&faces[4]==faces[9]&&faces[4]==faces[11]
        &&faces[8]==faces[10]&&faces[8]==faces[22]&&faces[8]&&faces[20]
        &&faces[23]==faces[21]&&faces[23]==faces[1]&&faces[23]==faces[3]
        &&faces[12]==faces[13]&&faces[12]==faces[14]&&faces[12]==faces[15]
        &&faces[16]==faces[17]&&faces[16]==faces[18]&&faces[16]==faces[19]) {
            return true;
        }
        if(faces[4]==faces[5]&&faces[4]==faces[18]&&faces[4]==faces[19]
        &&faces[16]==faces[17]&&faces[16]==faces[22]&&faces[16]==faces[23]
        &&faces[20]==faces[21]&&faces[20]==faces[14]&&faces[20]&&faces[15]
        &&faces[12]==faces[13]&&faces[12]==faces[6]&&faces[12]==faces[7]
        &&faces[0]==faces[1]&&faces[0]==faces[2]&&faces[0]==faces[3]
        &&faces[8]==faces[9]&&faces[8]==faces[10]&&faces[8]==faces[11]) {
            return true;
        }
        if(faces[4]==faces[5]&&faces[4]==faces[14]&&faces[4]==faces[15]
        &&faces[16]==faces[17]&&faces[16]==faces[6]&&faces[16]==faces[7]
        &&faces[20]==faces[21]&&faces[20]==faces[18]&&faces[20]&&faces[19]
        &&faces[12]==faces[13]&&faces[12]==faces[22]&&faces[12]==faces[23]
        &&faces[0]==faces[1]&&faces[0]==faces[2]&&faces[0]==faces[3]
        &&faces[8]==faces[9]&&faces[8]==faces[10]&&faces[8]==faces[11]) {
            return true;
        }
        if(faces[0]==faces[1]&&faces[0]==faces[16]&&faces[0]==faces[18]
        &&faces[17]==faces[19]&&faces[17]==faces[9]&&faces[17]==faces[8]
        &&faces[11]==faces[10]&&faces[11]==faces[15]&&faces[11]&&faces[13]
        &&faces[14]==faces[12]&&faces[14]==faces[2]&&faces[14]==faces[3]
        &&faces[4]==faces[5]&&faces[4]==faces[6]&&faces[4]==faces[7]
        &&faces[20]==faces[21]&&faces[20]==faces[22]&&faces[20]==faces[23]) {
            return true;
        }
        if(faces[0]==faces[1]&&faces[0]==faces[15]&&faces[0]==faces[13]
        &&faces[17]==faces[19]&&faces[17]==faces[2]&&faces[17]==faces[3]
        &&faces[11]==faces[10]&&faces[11]==faces[16]&&faces[11]&&faces[18]
        &&faces[14]==faces[12]&&faces[14]==faces[9]&&faces[14]==faces[8]
        &&faces[4]==faces[5]&&faces[4]==faces[6]&&faces[4]==faces[7]
        &&faces[20]==faces[21]&&faces[20]==faces[22]&&faces[20]==faces[23]) {
            return true;
        }    

        return false;   
    }
};

int main() {
    Cube cube = Cube();

    cube.insertFaces();

    cout << cube.checkRotate();
}

 

 

2. 챌린지반 과제

 

 오늘의 대부분은 거의 챌린지반 과제를 하면서 보낸 것 같다. 이번 주에 구현해야 하는 부분은 위에서 보는 것처럼 간단하지만, 결국에 견고한 아키텍처를 목표로 공부하는 것이기 때문에, 멀리 내다보며 설계하는 연습을 하고 있다.

 북마크에 대한 정보를 아직은 어떤 방식으로 저장하게 될 지 몰라서, 일단 나름대로 확장가능성을 생각하면서 기본 구조를 만들고 있다. 늘 해오던 것처럼, presentation - domain - data 계층을 기반으로 인터페이스와 구현체를 분리해 작성하고 있고 이제 sealed class를 이용해 비즈니스 로직에 쓰일 Result를 커스텀 하는 것은 많이 익숙해진 것 같다.

 아직까진 챌린지반 커리큘럼 상 DI 라이브러리 이용까진 나가지 않았기 때문에, 나름대로 app 레이어를 따로 분리해 di를 위한 Injector들을 직접 구현했다. 오늘 대략적인 domain 및 data 레이어 구현은 다 끝냈고, presentation 쪽에서 TabLayout과 ViewPager2를 통해 Fragment들을 전환하는 정도까지 끝내뒀다.

 그리고 Activity와 ViewModel도 늘 하던 방식으로 설계해서 네트워크 통신이 정상적으로 작동하나 확인했는데, 한 번에 문제 없이 작동했다. 내일 중으로 RecyclerView 작업하고 MVVM 패턴 적용해서 뷰에 뿌려줄 수 있도록 하면 그럴듯하게 프로토타입은 나올 것 같다. 조금 더 견고하고 매끄러운 예외 핸들링을 위해 몇 군데 고민해봐야 할 todo를 남겨놨는데, 아마 내일 그걸 고민하면서 또 많은 공부가 될 것 같다.