4개의 맞물린 톱니바퀴가 있다. 각 톱니에는 자성(N극, S극)이 있고 지정된 톱니가 지정된 명령대로 회전한다. 그 결과를 구하라
문제는 간단하게 생각할 수 있는 문제였다.
확실히 과거 삼성 기출이 지금보다 훨씬 쉬운거 같다..
필요했던 함수는 크게, 톱니를 회전시키는 함수, 회전 가능한지 확인하는 함수, 실제로 한 톱니가 돌았을 때 결과. 세가지가 필요했다.
우선 톱니가 회전한 결과를 반환하는 함수 rotate()
를 작성했다.
def rotate(g : list, direction : int) -> list:
"""
g : gear list
direction : rotate direction, 1 : 시계방향, -1 반시계 방향
return : rotated g
"""
new_g = []
if direction == 1:
new_g = [g[-1]] + g[0:-1]
elif direction == -1:
new_g = g[1:] + [g[0]]
return new_g
여기서 했던 실수중의 하나가,
톱니들이 0번 톱니 (12시 방향)부터 시계방향으로 리스트에 극성이 담긴 형태인데, 슬라이싱을 이용했더니, g[0]
혹은 g[-1]
이 값이어서 브라켓을 씌워서 리스트화 한다음 남은 부분과 더하기 했다. (이 방식이 메모리 측면에서는 좋지 못하다는 정보를 봤다)
다음은 마주보는 톱니를 이용해서, 기준이 되는 톱니 base
와 compare
를 이용해서 기준 톱니 기준 왼쪽인지 오른쪽인지 여부에 따라서 Boolean값을 반환하는 함수 movable
을 작성했다.
def moveable(base : list, compare : list, direction : int) -> bool:
"""
base : 기준이 되는 톱니
compare : 움직일 톱니
direction : base 기준 compare 위치,
1 : 왼쪽,
-1 : 오른쪽
"""
# 왼쪽과 비교
if direction == 1:
return base[6] != compare[2]
# 오른쪽과 비교
elif direction == -1:
return base[2] != compare[6]
return "error"
처음에는 비트 연산 ^
를 사용했는데, 그냥 달라야지만 움직이는 것으로 변경했다. (또 오른쪽 왼쪽 설정한걸 헷갈려서...오류가 있었다)
마지막으로 하나의 톱니가 돌았을때, 양 옆을 보며 톱니를 회전시키는 함수를 작성했다. 우선 오른쪽, 왼쪽을 나눠서 본다. 이때 코드가 중복되어 수정을 해보는 방안을 고민해 봤는데, 굳이 싶어서 그냥 두번 적었다. (사실 이런건 기술부채인가요...)
def iteration(gear : list, command : tuple) -> list:
"""
gear : gear list
command : (gear number, direction) direction, 1 : 시계방향, -1 반시계 방향
"""
g, base_dir = command[0] -1, command[1]
rotation = [(0,0)] * 4
rotation[g] = (1, base_dir)
# g 기준 왼쪽 오른쪽 분리 (인덱스로)
left = [0,1,2,3][:g][::-1] # 역순으로 슬라이싱해서 루프 돌리기 편하게 함
right = [0,1,2,3][g+1:]
base = gear[g]
dir = base_dir
# base 기준 왼쪽
for idx in left:
if moveable(base, gear[idx], 1):
base = gear[idx]
dir = dir * -1
rotation[idx] = (1, dir)
else:
break
# base기준 오른쪽
base = gear[g]
dir = base_dir
for idx in right:
if moveable(base, gear[idx], -1):
base = gear[idx]
dir = dir * -1
rotation[idx] = (1, dir)
else:
break
new_gear = []
for idx, g in enumerate(gear):
if rotation[idx][0]:
new_gear.append(rotate(g, rotation[idx][1]))
else:
new_gear.append(g)
return new_gear
여기서 코드가 중복되면서 발생했던 문제점은,
기존 톱니가 도는 방향을 dir
이라는 변수에 저장했다 (변수명도 적절한 것은 아닌거같다). 이때 왼쪽 기준으로 회전방향에 -1 을 곱해가면서 변경했는데, dir을 다시 기존 방향으로 갱신했어야 하는데 누락되어서 저 멀리 있는 톱니가 돌아가는 불상사가 벌어졌다.
Movable 하지 않으면 바로 루프를 탈출한다.
최종적으로 위의 조건처럼 12시의 톱니를 이용하여 최종 점수를 환산한다.
def sol(gear, K, move):
for i in range(K):
gear = iteration(gear, move[ i])
return gear[0][0] + 2 * gear[1][0] + 4 * gear[2][0] + 8 * gear[3][0]
# 톱니바퀴 https://www.acmicpc.net/problem/14891
import sys
def InputData():
readl = sys.stdin.readline
gear = [[int(x) for x in readl().strip()] for _ in range(4)]
K = int(readl())
move = [tuple(map(int, readl().split())) for _ in range(K)]
return gear, K, move
def rotate(g : list, direction : int) -> list:
"""
g : gear list
direction : rotate direction, 1 : 시계방향, -1 반시계 방향
return : rotated g
"""
new_g = []
if direction == 1:
new_g = [g[-1]] + g[0:-1]
elif direction == -1:
new_g = g[1:] + [g[0]]
return new_g
def moveable(base : list, compare : list, direction : int) -> bool:
"""
base : 기준이 되는 톱니
compare : 움직일 톱니
direction : base 기준 compare 위치,
1 : 왼쪽,
-1 : 오른쪽
"""
# 왼쪽과 비교
if direction == 1:
return base[6] != compare[2]
# 오른쪽과 비교
elif direction == -1:
return base[2] != compare[6]
return "error"
def iteration(gear : list, command : tuple) -> list:
"""
gear : gear list
command : (gear number, direction) direction, 1 : 시계방향, -1 반시계 방향
"""
g, base_dir = command[0] -1, command[1]
rotation = [(0,0)] * 4
rotation[g] = (1, base_dir)
# g 기준 왼쪽 오른쪽 분리 (인덱스로)
left = [0,1,2,3][:g][::-1] # 역순으로 슬라이싱해서 루프 돌리기 편하게 함
right = [0,1,2,3][g+1:]
base = gear[g]
dir = base_dir
# base 기준 왼쪽
for idx in left:
if moveable(base, gear[idx], 1):
base = gear[idx]
dir = dir * -1
rotation[idx] = (1, dir)
else:
break
# base기준 오른쪽
base = gear[g]
dir = base_dir
for idx in right:
if moveable(base, gear[idx], -1):
base = gear[idx]
dir = dir * -1
rotation[idx] = (1, dir)
else:
break
new_gear = []
for idx, g in enumerate(gear):
if rotation[idx][0]:
new_gear.append(rotate(g, rotation[idx][1]))
else:
new_gear.append(g)
return new_gear
def sol(gear, K, move):
for i in range(K):
gear = iteration(gear, move[ i])
return gear[0][0] + 2 * gear[1][0] + 4 * gear[2][0] + 8 * gear[3][0]
gear, K, move = InputData()
print(sol(gear, K, move))