저번에 팩맨 문제를 풀때
3중포문에서 재귀함수를 사용하다 정신 나갔던 적이있다.
코드트리쌤한테 질문을 해서 코드를 수정을했엇는데
왼쪽에서 오른쪽으로 바뀌었다. 코쌤말로는 deepcopy()를 쓰지않기위해 저렇게 처리했다고 하셨다.
코드를 자세히보면, 처음에 방문한 delete1 을 선언하고 delete1 체크 후, for j 문으로 넘어가고
temp2 에다가 현재까지온 delete1 2차원배열을 저장. 그다음 for z 문 넘어가서 temp3에 delete1 2차원배열을 저장.
for문 수행이 다끝나면 다시 아까 저장했던 배열을 delete1[nx3][ny3] = temp3 으로 해준다.
즉, 선택이 끝나고 다시 불러와주는것. 나는 deepcopy 를통해 delete배열을 새로 만들어 줬다.
그렇다면 코쌤이 말씀하신대로 재귀 함수를 통해 이함수를 만들어 보면 어떨까?
한번 써보기로했다.
def pacman_move():
global monster_cnt, monster_arr,r1,c1
#상좌 하우의 우선순위를 가지고
#3칸을 이동하는데. 몬스터를 가장 많이 먹을 수 있는 경우의 수다.
#이동칸에 몬스터를 다 먹어치우고 시체를 남긴다.
#알은안먹음. 움직이기전에 같은 칸에있는 몬스터 안먹고, 이동하는 과정중만 먹는다.
#팩맨이잇는자리에 알이 태어날경우를 말하는듯.
dx=[-1,0,1,0]
dy=[0,-1,0,1]
x,y=r1,c1 # r1,c1이 팩맨의 위치다.
moving = []
for i in range(4):
for j in range(4) :
for z in range(4) :
(power,moving_arr,real_x,real_y) = lets_search(i,j,z) # 얘가 최대값을 리턴해줘야한다.
moving.append((power,i,j,z,moving_arr,real_x,real_y))
#print(where_is_64_pac_go)
moving.sort(key=lambda x:(-x[0],x[1],x[2],x[3]))
# 몬스터 먹은개수, 처음이동, 2번째 이동, 3번째이동, 각 경로를 담은 배열
#이게 과연 좌우상하를 가지고 됐을까?
eat,first,second,third,moving_arr,last_x,last_y = moving[0]
#팩맨위치 갱신
r1,c1 = last_x,last_y
pacman_update()
#여기서 경로상에 있는 몬스터들 다 지우고, 그녀석들만큼 시체에 넣는다.
#이거 배열끼리 비교해서 어떻게 안전하게 값 같을때 해당 배열 지우는지 블로그 글쓰기 <<<<<<<<<<<<<<
#몬스터들 잡아먹히고 난다음 갱신, 시체 갱신
for item in moving_arr:
q,p = item
#안에있는놈 다 날려버리기.
if len(monster_3d_arr[q][p] ) > 0 :
monster_3d_arr[q][p] = []
monster_body_arr[q][p] = 3
#초기화 하고 다시 넣어준다.
monster_arr= []
for i in range(n) :
for j in range(n) :
if len(monster_3d_arr[i][j]) > 0 :
for item in monster_3d_arr[i][j] :
monster_arr.append((i,j,item))
"""
for item in moving_arr:
q,p = item
for (q1,p1,dir1) in (monster_arr):
if q==q1 and p == p1 : #해당하는 위치에 똑같은값들이 있다면,
monster_body_arr[q1][p1] = 3 #두턴이 3인? ㅋㅋ
if not (q,p,dir1) in temp_monster_arr : continue
idx = temp_monster_arr.index((q1,p1,dir1))
temp_monster_arr.pop(idx) #그 값을 빼버린다.
#그 장소에 시체를 2턴간 남긴다.
continue
monster_arr = temp_monster_arr.copy()
"""
return
|
위와같이 수정했다. 기존에 내가 했던 방식 ( key=lambda x:(x[0) .. ) 이방식을 유지하고
재귀함수만 사용해봤다. 근데 이방식은 -1이 들어올때 moving 배열에 넣지않는게 배열 sort할때 시간이 덜 줄어들 것같다.
def lets_search(i,j,k) :
dx=[-1,0,1,0]
dy=[0,-1,0,1]
global r1,c1 # 팩맨의 위치
x,y = r1,c1
already_visited = []
power = 0
for move_dir in [i,j,k] :
nx,ny = x+dx[move_dir],y+dy[move_dir]
if not in_range(nx,ny) :
return (-1,[],-1,-1)
if not (nx,ny) in already_visited :
already_visited.append((nx,ny))
power += monster_cnt[nx][ny]
x,y = nx,ny
real_x = x
real_y = y
return (power,already_visited,real_x,real_y)
|
잘써먹은건 저 배열값하나하나 가져온다음에 탐색하고, 이미 방문한 배열이지 않으면 power값 가져오고
해당한걸 리턴.
그리고 리턴한 값을 sort로 정렬 해서 풀었다.
만약 내가 현장에서 풀어야한다면, 함수화-함수화-함수화 하는 버릇을 들여서
최대한 실수가 나지않게 만드는게 중요할꺼같다.
계속 코딩하다보면 뭔가 함수화하면 또 변수선언해야 하고 귀찮으니까 계속 디버깅하면서 구멍나는 부분을 메꾸려고하는데
거기서 시간오래걸리고 잡아먹힐시간에 함수화해서 문제날때 return 해버려서
그걸 버려버리게 하는게 좋을거같다.
'코딩 테스트' 카테고리의 다른 글
파이썬에서 에러가 발생했을때 찾는법, 어디까지 들어가나 break 거는법 (0) | 2023.10.12 |
---|---|
[코드트리챌린지] 2022 삼성 코딩테스트 하반기 오후 2번 코드트리 - 산타의 선물 공장 2 파이썬 리뷰 (1) | 2023.10.11 |
[2022 삼성 코딩테스트 상반기 오전 2번] 코드트리 - 팩맨 파이썬 리뷰 (1) | 2023.10.09 |
2차원 배열 특정 부분 반시계, 시계 방향 회전 알고리즘 파이썬 (0) | 2023.10.06 |
[2022 삼성 코딩테스트 상반기 오전 2번] 코드트리 - 예술성 파이썬 리뷰 (1) | 2023.10.06 |