알고리즘
[삼성 코테 기출 - 시뮬레이션] 루돌프의 반란
김치말이삼겹살
2024. 4. 13. 02:00
import sys
sys.stdin = open('input.txt', 'r')
# rudolph's dxs, and dys
dxs = [0, 1, 1, 1, 0, -1, -1, -1]
dys = [1, 1, 0, -1, -1, -1, 0, 1]
# santa's dxs, and dys
sdxs = [-1, 0, 1, 0]
sdys = [0, 1, 0, -1]
def select_santa(cow):
'''
:param cow: 현재 루돌프의 위치를 넣는다. [x,y] 형태
:return: 선택한 산타의 인덱스와, 방향 리턴하지 않을까? -> 아니네... 산타의 위치를 함께 리턴한다.
코드 자체는 그리 도움될 것 같지는 않은데... 뭐랄까?
코드를 읽기 쉽게 짜시려고 한 것 같음. 나라면 방향 리턴할 듯?
'''
r1, c1 = cow
close_dis = int(1e9)
# 산타 id와, 위치 초기화
select_santa_num = 0
select_santa_loc = [0, 0]
# santa 딕셔너리 순회
for i in santa:
# i번째 산타의 row, col 입력받음
r2, c2 = santa[i]
# 크기
dis = (r1 - r2) ** 2 + (c1 - c2) ** 2
# 작으면
if dis < close_dis:
# 현재 번호로 업데이트
select_santa_num = i
select_santa_loc = [r2, c2]
close_dis = dis
# 같으면
elif dis == close_dis:
# 현재의 row가 더 작으면
if r2 > select_santa_loc[0]:
select_santa_num = i
select_santa_loc = [r2, c2]
close_dis = dis
# 현재의 col이 더 작으면
elif r2 == select_santa_loc[0]:
if c2 > select_santa_loc[1]:
select_santa_num = i
select_santa_loc = [r2, c2]
close_dis = dis
return select_santa_num, select_santa_loc
def Interaction(crush_new_santa_num, dict_x, dict_y):
'''
상호작용을 다룬 함수
:param crush_new_santa_num: 들이 받혔을 때 산타의 위치 [x,y]
:param dict_x: x의 위치
:param dict_y: y의 위치
:return: 따로 없음
'''
#들이 받힌 산타의 위치
x, y = santa[crush_new_santa_num]
# 새로운 y로 만들어.
new_x = x + dict_x
new_y = y + dict_y
if not in_range(new_x, new_y):
del santa[crush_new_santa_num] # 보드 밖으로 나감
faint[crush_new_santa_num] = 0
else:
TF, p_num = check(crush_new_santa_num, new_x, new_y) # 새 위치에 산타가 있는지 없는지 확인
if not TF: # 있는경우 상호작용
Interaction(p_num, dict_x, dict_y)
santa[crush_new_santa_num] = [new_x, new_y] # 상호작용이랑 상관없이 이동할건 해야지
def cow_crash(cow_loc, x1, y1, p_num, x2, y2):
'''
:param cow_loc: 기존 루돌프의 위치: [x,y]
:param x1: 바뀐 루돌프의 위치
:param y1: 바뀐 루돌프의 위치
:param p_num: 들이 받힌 산타의 id
:param x2: 산타의 위치
:param y2: 산타의 위치
:return: 사실 리턴할 것은 없어보인다.
'''
# 우선 들히 받힌 산타의 점수 C만큼 올려주고
santa_score[p_num] += C
# 방향을 받는다. -> 현재 위치 - 기존 위치
dict_x = x1 - cow_loc[0]
dict_y = y1 - cow_loc[1]
# x2와 y2에 각각 C 만큼 더해준다.
x2 += dict_x * C
y2 += dict_y * C
# 이것도 좋은 함수 인듯? -> 함수명의 중요성
# x2,y2가 범위내에 없으면
if not in_range(x2, y2):
del santa[p_num] # 보드 밖으로 나감 -> 그냥 딕셔너리에서 해당 value값 삭제해버림.
# del 문법은 또 처음 보네
# 죽어랏!! -> faint는 0 아니면 2인가?
faint[p_num] = 0
else:
faint[p_num] = 2 # 기절 # 두턴뒤에 풀림 -> 얘는 산타 턴 돌면 무조건 1 까이니까 2로 둔 것 같다 !!!
TF, crush_new_santa_num = check(p_num, x2, y2)
if not TF:
# 상호작용 crush_new_santa_num
# 또 들이 받힌 산타가 있을 것 아녀
Interaction(crush_new_santa_num, dict_x, dict_y)
santa[p_num] = [x2, y2] # 상호작용이랑 상관없이 이동할건 해야지
def santa_crash(p_num, x1, y1):
'''
:param p_num: 산타의 id
:param x1: 산타의 위치
:param y1: 산타의 위치
:return:
'''
# 현재 산타의 점수에 D만큼 더함
santa_score[p_num] += D
# 아... 아직 업데이트를 안했구나...
dict_x = santa[p_num][0] - x1
dict_y = santa[p_num][1] - y1
x1 += dict_x * D
y1 += dict_y * D
if not in_range(x1, y1):
del santa[p_num] # 보드 밖으로 나감
faint[p_num] = 0
else:
faint[p_num] = 1 # 기절 # 두턴뒤에 풀림 -> 근데 얘는 왜 1로 하고, 아까꺼는 2로 했지? -> 얘는 바로 돌며 ㄴ되니까..
TF, crush_new_santa_num = check(p_num, x1, y1)
if not TF:
# 상호작용 crush_new_santa_num
Interaction(crush_new_santa_num, dict_x, dict_y)
santa[p_num] = [x1, y1] # 상호작용이랑 상관없이 이동할건 해야지
def in_range(x, y):
return 0 < x < N + 1 and 0 < y < N + 1
def check(p_num, x1, y1):
'''
:param p_num: 산타 id
:param x1: 산타 x값
:param y1: 산타 y값
:return: 겹치는 다른 산타가 있는지 여부, 그 index
'''
for i in santa:
if i == p_num:
continue
if santa[i] == [x1, y1]:
return False, i
return True, 0
def santa_move_rule(p_num, x1, y1, x2, y2):
'''
:param p_num: 산타 id
:param x1: 산타 위치
:param y1: 산타 위치
:param x2: 루돌프 위치
:param y2: 루돌프 위치
:return: 업데이트 한 산타의 위치
'''
dis = (x1 - x2) ** 2 + (y1 - y2) ** 2
new_x, new_y = x1, y1
# for dx, dy in zip(sdxs, sdys):
for i in range(4):
nx = x1 + sdxs[i]
ny = y1 + sdys[i]
if in_range(nx, ny):
new_dis = (nx - x2) ** 2 + (ny - y2) ** 2
# 거리 줄었나?
if new_dis < dis:
# 다른 산타 있는지 없는지 여부
TF, _ = check(p_num, nx, ny)
if TF:
# 없어야 이동.
dis = new_dis
new_x, new_y = nx, ny
return new_x, new_y
def cow_move_rule(x1, y1, x2, y2):
'''
갠적으로 미;친 거 아니신지... 하는 코드이다. -> 이게 될 수 있는 이유?? 루돌프가 8개 방향 다 쓸 수 있어서임.
:param x1: 루돌프 x
:param y1: 루돌프 y
:param x2: 산타 x
:param y2: 산타 y
:return: 바뀐 루돌프 위치 [x1,y1] 이 되어야 하지 않을까?
'''
# 거리 가까워지기 위함. 우선 x부터
if x1 > x2:
# 크면 x를 빼고
x1 -= 1
elif x1 < x2:
# 작으면 x를 더해줌
x1 += 1
else:
# 같으면 현상 유지
x1 = x1
# y의 경우에도
if y1 > y2:
#y1이 크면 y1를 1 뺴줌
y1 -= 1
# y1이 작으면
elif y1 < y2:
# y1을 1 더해줌.
y1 += 1
else:
y1 = y1
return x1, y1
# 루돌프 움직임 추적
def cow_move(cow_loc):
'''
:param cow_loc: 입력받은 루돌프 위치 [x,y] 리스트 형태로 되어 있음
:return: 변경한 루돌프 위치. [x,y] 형태.
'''
# cow 위치 받고
x1, y1 = cow_loc
# 산타 고른다.
p_num, [x2, y2] = select_santa(cow_loc)
# 고른 산타대로 이동 -> x1,y1 => 루돌프 위치, x2,y2 => 산타 위치
# 바뀐 루돌프 위치 받고
x1, y1 = cow_move_rule(x1, y1, x2, y2)
# 만약 루돌프가 산타랑 충돌할때
if [x1, y1] == [x2, y2]:
# 루돌프로 충돌 조건.
cow_crash(cow_loc, x1, y1, p_num, x2, y2)
# 충돌 -> 상호작용까지 마무리 후 종료
return [x1, y1]
# 산타 움직임
def santa_move(cow_loc, k):
'''
:param cow_loc: 루돌프의 위치 [x2,y2]
:param k: 의미 없음.
:return: 없음. -> 산타 배열로 처리하므로.
'''
x2, y2 = cow_loc
for i in range(1, P + 1):
# santa의 해당 인덱스에 머가 없으면
if santa.get(i) == None:
continue
# faint위치에 서 1 빼주고. 근데 이러면 1 빼줘야 하는 거 아닌가?
if faint[i] != 0: # 기절한 산타는 움직임 없음
faint[i] -= 1
continue
# 현 산타의 위치
x1, y1 = santa[i]
# 산타의 move_rule 보러 가자 -> 바뀐 산타 위치
x1, y1 = santa_move_rule(i, x1, y1, x2, y2)
# 산타가 움직였는데 루돌프랑 부딪칠 경우
if [x1, y1] == [x2, y2]:
santa_crash(i, x1, y1)
else:
# 아니면 걍 산타 위치~
santa[i] = [x1, y1]
if __name__ == "__main__":
# main 문 안으로 들어옴으로써, 얘네가 전역 변수로 인정 받게 되는 느낌인건가보네
# 이런 코드 패턴 짜야겠다 !!! -> c에서의 메인 함수 느낌인가보네...
# 만약 이거 없었으면, santa dictionary, n, m, p, c, d, faint, santa_score 다 전역 변수로 받아야겠네??
# N:게임격자, M: 게임턴수, P:산타개수, C:루돌프 힘, D: 산타의 힘
N, M, P, C, D = map(int, input().split())
# 루돌프 위치 받기 -> 루돌프 위치를 리스트로 받은 이유는?
# 쌍으로 관리하고자 + 값 변경 용이하게 하고자 !!
cow_loc = list(map(int, input().split()))
# 딕셔너리로 관리
santa = {}
# 이건 좀 좋은 아이디어 같음 -> 키에 대한 값들을 쉽게 받을 수 있어서
for _ in range(P):
p, p_x, p_y = map(int, input().split())
santa[p] = [p_x, p_y]
# 기절 상태 기록 -> P + 1인 이유? 머겠나요 1번부터 p번까지 저장하려고지
faint = [0] * (P + 1)
santa_score = [0] * (P + 1)
# 이건 왜한거지?? 의미 없어보이는 변수 선언이다.
# total_score = 0
# 게임 플레이수 M
for k in range(1, M + 1):
# 루돌프 움직이는 것.
cow_loc = cow_move(cow_loc)
if len(santa) == 0:
break
# 1번 산타부터 P번산타까지 산타들 움직임 -> 산타 움직임
santa_move(cow_loc, k)
if len(santa) == 0:
break
# 모든 산타에 대해 점수+1
for pid in santa:
santa_score[pid] += 1
print(*santa_score[1:])
내가 손 댄 코드는 1도 없어서 부끄러운데... 그래도 일단 올립니다...
모듈화가 진짜 중요하다는 것을 느낀 코드였고...
작년 오후 1번이었다는데 나 이거 풀 수 있으려나 ???
input, output 바로 팅팅 안 나오는 게 당연함 !! 그런거 디버깅하라고 4시간이나 주는 거겠지...
if __name__ == "__main__" 기억해두고 전역변수 최대한 안 쓰는 방향으로 코드 짜보면 좋을 것 같기도 ???? ㅎㅎㅎㅎ
내일 일찍 일어나서 코테 공부해야하니까 오늘은 이만... 자야겠당
내일은 아침 9시부터 코테 시작해서 오후 1시까지 코드트리 기출 1문제 붙잡는 게 목표 !!
그리고 그 이후는 기초 dfs, bfs 문제랑 구현 1문제씩 풀고 풀었던 거 복습하고 !!
마지막으로 순열, 조합 구현하는 거 코드짜기 4번 연습하고 자야겠당 ㅎㅎ
반응형