본문 바로가기
알고리즘/삼성

[백준 -실버1] 14891번 톱니바퀴(구현, 파이썬)

by 호리미 2022. 2. 5.

https://www.acmicpc.net/problem/14891

 

14891번: 톱니바퀴

총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴

www.acmicpc.net

<복습 체크>

22/03/05                  
O                  

 

<내 코드 1>

- 회전을 할 때 deque의 rotate를 이용해서 회전했다.

- check_right 함수는 회전하는 톱니바퀴를 기준으로 오른쪽 바퀴들의 회전 여부를 파악하는 함수이다.

  -> k번째 톱니바퀴의 인덱스 2번과 k+1번째 톱니바퀴의 인덱스 6번을 비교해야한다.

  -> 만약 서로 다르다면 원래 회전 방향 d와 반대로 회전해야하기 때문에 d = -d로 변경해주었다

  -> 서로 같은 경우에는 더 이상 회전을 하지 않으므로 리턴했다.

- check_left 함수는 회전하는 톱니바퀴를 기준으로 왼쪽 바퀴들의 회전 여부를 파악하는 함수이다.

  -> k번째 톱니바퀴의 인덱스 6번과 k-1번째 톱니바퀴의 인덱스 2번을 비교해야한다.

- check 리스트는 회전여부를 파악하는 배열이다. 우선 명령의 톱니바퀴 번호 인덱스에 방향을 저장한다.

- 그 후 톱니바퀴 번호에 따라 회전 여부를 파악해서 check 리스트를 업데이트한다.

 

[헷갈린 부분]

- 나는 톱니바퀴가 순차적으로 회전하는 문제라고 생각해서 시간을 많이 썼다.

  -> 1번 바퀴가 회전하는 경우

      -> 1번 바퀴 회전 -> 2번 바퀴랑 겹치는지 확인해서 회전 -> 3번 바퀴 겹치는지 확인해서 회전 

위와 같은 방식으로 동작한다고 착각했다.

- 이 문제는 1번 바퀴가 회전한다고 가정하면, 회전 하기 전의 바퀴들의 맞물림 상태를 확인해서 회전 방향을 미리 결정하는 문제이다.

import sys
from collections import deque
input = sys.stdin.readline

def check_right(num, d):
    for k in range(num-1, 3):
        if gear[k][2] != gear[k + 1][6]:
            d = -d
            check[k + 1] = d
        else:
            return

def check_left(num, d):
    for k in range(num - 1, 0, -1):
        if gear[k][6] != gear[k - 1][2]:
            d = -d
            check[k - 1] = d
        else:
            return

gear = []
for _ in range(4):
    gear.append(deque(map(int, input().strip())))
k = int(input())
order = []
for _ in range(k):
    order.append(list(map(int, input().split())))

for i in range(k):
    num, d = order[i][0], order[i][1]
    check = [0]*4
    check[num-1] = d
    ## 회전 여부 확인 ##
    if num == 1:
        check_right(num,d)

    elif num == 2:
        if gear[num - 1][6] != gear[0][2]:
            check[0] = -d
        check_right(num, d)

    elif num == 3:
        if gear[num - 1][2] != gear[3][6]:
            check[3] = -d
        check_left(num, d)
    else:
        check_left(num, d)
	## 회전 ##
    for i in range(4):
        if check[i]:
            gear[i].rotate(check[i])
## 출력 ##
ans = 0
for i in range(4):
    if gear[i][0] == 1:
        ans += 2**i

print(ans)

 

<내 코드 2>

- 극강의 노가다로 코드를 짰다,, 매번 1시간 미만으로 고민하다가 다른 풀이 참고하면서 익혔는데 오늘은 오기가 생겨서

   끝까지 해봤다,,, 맨처음에는 문제를 잘못 이해했고,, 그 다음엔 중간중간 잘못 생각한 부분이 있었다.

- 3시간 넘게 붙잡고 있었던것같다,, 우선 내 노가다 코드를 올리고 다른 사람 코드 보면서 공부를 더 해야겠다

- 시계 방향, 반시계 방향 회전 함수를 스택을 이용해 직접 구현했다.

# 톱니바퀴
t = []
for _ in range(4):
    t.append(list(map(int, input())))
k = int(input())

orders = []
# 톱니바퀴 번호와 회전방향 입력받음
for _ in range(k):
    num, ro = map(int, input().split())
    orders.append([num, ro])

#회전 함수
def rotation(num, directions):
    if directions == 1:  # 시계 방향
        t[num].reverse()  # 뒤집어줌
        temp = t[num].pop(0)  # 맨앞에꺼 뺌
        t[num].append(temp)  # 맨 뒤에 붙임
        t[num].reverse()  # 다시 뒤집어줌

    elif directions == -1:  # 반시계 방향
        temp = t[num].pop(0)  # 맨앞에꺼 뺌
        t[num].append(temp)  # 맨 뒤에 붙임


for order in orders:
    num, d = order[0] - 1, order[1]

    # 옆 톱니들 확인
    check = [0] * 4
    check[num] = d
    flag = False #연속적으로 회적이 일어나는지 체크해주는 변수
    if num == 0:
        if t[0][2] != t[1][6]:  # 극이 다르다면
            check[1] = -d
            flag = True

        if t[1][2] != t[2][6] and flag == True:
            check[2] = d
        else:
            flag = False

        if t[2][2] != t[3][6] and flag == True:
            check[3] = -d

    elif num == 1:
        if t[1][6] != t[0][2]:
            check[0] = -d

        if t[1][2] != t[2][6]:
            check[2] = -d
            flag = True

        if t[2][2] != t[3][6] and flag == True:
            check[3] = d

    elif num == 2:
        if t[2][2] != t[3][6]:
            check[3] = -d

        if t[2][6] != t[1][2]:
            check[1] = -d
            flag = True
        else:
            flag = False

        if t[1][6] != t[0][2] and flag == True:
            check[0] = d

    elif num == 3:
        if t[3][6] != t[2][2]:  # 극이 다르다면
            check[2] = -d
            flag = True

        if t[2][6] != t[1][2] and flag == True:
            check[1] = d
        else:
            flag = False
        if t[1][6] != t[0][2] and flag == True:
            check[0] = -d
    #회전 동작
    for i in range(4):
        if check[i]:
            rotation(i, check[i])

result = 0
cnt = 1
for i in range(4):
    if t[i][0] == 1:  # s극이면
        result+=cnt
    cnt *= 2

print(result)