문제
풀이

💡Idea

  • 맞닿은 부분이 다른 극이면, 다른 방향으로의 회전이 전달된다.
    1. 왼쪽과 오른쪽으로, 총 어디서부터 어디까지 극이 연결되는지(같이 회전하는지) 확인
    1. 회전될 톱니바퀴들을 한번에 회전.
  • 기본
          0
      7       1
     (L)6       2(R)
      5       3
          4  
    
  • clockwise (-1)
          7
      6       0
      5       1
      4       2
          3  
    
  • counterclockwise (+1)
          1
      8       2
      7       3
      6       4
          5  
    

🔑Code

#include <bits/stdc++.h>
using namespace std;

struct Cogwheel{
    bool initalState[8];
    int rotationCnt = 0;

    void rotate(bool isClockwise){
        if(isClockwise) rotationCnt--;
        else rotationCnt++;
    }

    int applyRotation(int idx){
        int res = (idx + rotationCnt) % 8;
        return (res < 0) ? res + 8 : res;
    }

    bool getTopState(){
        return initalState[applyRotation(0)];
    }

    bool getRightState(){
        return initalState[applyRotation(2)];
    }

    bool getLeftState(){
        return initalState[applyRotation(6)];
    }

    Cogwheel(string state_str){
        for(int i = 0; i < 8; i++){
            initalState[i] = (state_str[i] == '1');
        }
    }

    static void rotateCogwheel(vector<Cogwheel>& cogwheels, int cogNum, bool isClockwise){
        // 왼쪽 연결된 부분의 끝 찾기
        int l = cogNum;
        for(int cur = cogNum; cur-1 >= 0; cur--){
            bool rightCogState = cogwheels[cur].getLeftState();
            bool leftCogState = cogwheels[cur-1].getRightState();
            if(rightCogState ^ leftCogState) l = cur-1;
            else break;
        }

        // 오른쪽 연결된 부분의 끝 찾기
        int r = cogNum;
        for(int cur = cogNum; cur+1 <= 3; cur++){
            bool leftCogState = cogwheels[cur].getRightState();
            bool rightCogState = cogwheels[cur+1].getLeftState();
            if(rightCogState ^ leftCogState) r = cur+1;
            else break;
        }

        // l 에서의 회전 방향 정하기
        bool isCurCogClockwise = ((cogNum - l) & 1) ? !isClockwise : isClockwise;

        // l~r까지 다 회전시키기
        for(int i = l; i <= r; i++){
            cogwheels[i].rotate(isCurCogClockwise);
            isCurCogClockwise = !isCurCogClockwise;
        }
    }

    static int getScore(vector<Cogwheel>& cogwheels){
        int score = 0;
        for(int i = 0; i < 4; i++){
            if(cogwheels[i].getTopState()) score += (1 << i);
        }
        return score;
    }
};

int main(void){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    string state_str;
    vector<Cogwheel> cogwheels;
    for(int i = 0; i < 4; i++){
        cin >> state_str;
        cogwheels.emplace_back(state_str);
    }

    int K;
    cin >> K;
    for(int i = 0; i < K; i++){
        int cogNum, dir;
        cin >> cogNum >> dir;
        cogNum--; // 0-index
        Cogwheel::rotateCogwheel(cogwheels, cogNum, dir == 1);
    }    

    cout << Cogwheel::getScore(cogwheels);

    return 0;
}

🗨️ Side Notes

C++에서 음수 % 연산을 사용할 때 주의할 점

c++에서 음수에서 %(mod) 연산을 적용할 때, 음수가 나오는 것을 유의해야 한다.

다음 함수를 구현할 때, 주의가 필요했다.

int applyRotation(int idx){
	int res = (idx + rotationCnt) % 8;
	return (res < 0) ? res + 8 : res;
}

C++ vs Python 비교

Python은 항상 0 이상의 나머지를 반환하지만, C++에서는 왼쪽 피연산자의 부호를 그대로 유지한다.

  • c++
    cout << -3 % 8;
    // 출력값: -3
    
  • python
    print(-3 % 8)
    # 출력값: 5