coding test - python/SAMSUNG SWT(SW역량 테스트)

삼성 SW역량테스트 기출 / 2022 상반기 오전 1번 문제 술래잡기 / Python 파이썬

sillon 2024. 10. 12. 19:27
728x90
반응형

 

*문제 출처는 코드트리에 있습니다.

 

삼멘

문제 제목: 술래잡기

문제 사이트: https://www.codetree.ai/training-field/frequent-problems/problems/hide-and-seek/description?page=4&pageSize=5

 

코드트리 | 코딩테스트 준비를 위한 알고리즘 정석

국가대표가 만든 코딩 공부의 가이드북 코딩 왕초보부터 꿈의 직장 코테 합격까지, 국가대표가 엄선한 커리큘럼으로 준비해보세요.

www.codetree.ai

 


수정 한 뒤에 복사처리를 이상하게해서 계속 헤맸었다;;

문제의 코드

def run_man():
    global maps
    # 동시에 움직인다 술래와의 거리가 3이하면
    new_maps = [[[] for n in range(n)] for i in range(n)]
    for i in range(n):
        for j in range(n):
            if maps[i][j]:
                if abs(sx - i) + abs(sy - j) <= 3: # 술래와의 거리가 3이하면 이동
                    tmp = deque(maps[i][j])
                    while tmp:
                        d = tmp.popleft()
                        ni,nj = i + direct[d][0], j + direct[d][1]
                        if 0 <= ni < n and 0 <= nj < n:
                            if ni == sx and nj == sy:
                                new_maps[i][j].append(d)
                            else:
                                new_maps[ni][nj].append(d)
                        else:
                            if d == 1:
                                d = 0
                            elif d == 0:
                                d = 1
                            if d == 2:
                                d = 3
                            elif d == 3:
                                d = 2
                            ndi,ndj = i + direct[d][0], j + direct[d][1]
                            if ndi == sx and ndj == sy:
                                new_maps[i][j].append(d)
                            else:
                                new_maps[ndi][ndj].append(d)
                else:
                    new_maps[i][j] = maps[i][j][:] # 이렇게 풀면 이전에 넣어놓은 애들이 날아감 ㅠㅠ
                    
                
    maps = new_maps

아래처럼 바꿔줬음

new_maps[i][j] += maps[i][j]

 

 

 

전체 코드

 

from collections import deque

# 하 우 상 좌 반복
n,m,h,k = map(int,input().split())
#nxn,m 술래, h 나무, k 턴
man = [list(map(int,input().split())) for _ in range(m)]
tree = [list(map(int,input().split())) for _ in range(h)]
sx,sy = n//2,n//2
maps = [[[] for n in range(n)] for i in range(n)]
tree_maps = [[False] * n for i in range(n)]

for x,y in tree:
    tree_maps[x-1][y-1] = True

direct = ((0,-1),(0,1),(1,0),(-1,0)) # 0 좌 1 우 2 하 3 상
s_direct = ((1,0),(0,1),(-1,0),(0,-1))
for x,y,d in man:
    maps[x-1][y-1].append(d)

sulae_direct = [[-1] * n for i in range(n)]

def sulae_direct_map():
    global s_direct
    new_direct = [[-1] * n for i in range(n)]
    reverse = False
    if [sx,sy] == [0,0]:
        reverse = True
    if reverse:
        s_direct = ((1, 0), (0, 1), (-1, 0), (0, -1))
    else:
        s_direct = ((-1, 0), (0, -1), (1, 0), (0, 1))

    direction = ((1, 0), (0, 1), (-1, 0), (0, -1))
    queue = deque([[0,0]])
    new_direct[0][0] = 0
    i = 0
    while queue:
        q = queue.popleft()
        qx,qy = q[0],q[1]
        x = qx + direction[i][0]
        y = qy + direction[i][1]
        if 0 <= x < n and 0 <= y < n and new_direct[x][y] == -1:
            if new_direct[x][y] == -1:
                new_direct[x][y] = i
                queue.append([x,y])
        else:
            d = (i + 1) % 4
            nqx =  qx + direction[d][0]
            nqy = qy + direction[d][1]
            if 0 <= nqx < n and 0 <= nqy < n:
                if new_direct[nqx][nqy] == -1:
                    i = d
                    new_direct[nqx][nqy] = i
                    if reverse:
                        new_direct[qx][qy] = i
                    queue.append([nqx,nqy])
    return new_direct
def sulae_move():
    global maps,sx,sy
    d = sulae_direct[sx][sy]
    nsx,nsy = sx + s_direct[d][0],sy + s_direct[d][1]
    sx,sy = nsx,nsy

def get_score():
    # 술래가 바라보는 방향에 3칸 이내 확인
    check = []
    score = 0
    d = sulae_direct[sx][sy]
    dx,dy = s_direct[d][0],s_direct[d][1]
    if [sx,sy] == [0,0]:
        dx,dy = 1,0
    elif [sx,sy] == [n//2,n//2]:
        dx,dy = -1,0

    for i in range(3):
        cx = sx + i * dx
        cy = sy + i * dy
        if 0 <= cx < n and 0 <= cy < n:
            if tree_maps[cx][cy] == False:
                check.append([cx,cy])
    for x,y in check:
        if maps[x][y]:
            score += len(maps[x][y])
            maps[x][y] = []
    return score

def run_man():
    global maps
    # 동시에 움직인다 술래와의 거리가 3이하면
    new_maps = [[[] for n in range(n)] for i in range(n)]
    for i in range(len(maps)):
        for j in range(len(maps)):
            if maps[i][j]:
                if abs(sx - i) + abs(sy - j) <= 3: # 술래와의 거리가 3이하면 이동
                    tmp = deque(maps[i][j])
                    while tmp:
                        d = tmp.popleft()
                        ni,nj = i + direct[d][0], j + direct[d][1]
                        if 0 <= ni < len(maps) and 0 <= nj < len(maps):
                            if ni == sx and nj == sy:
                                new_maps[i][j].append(d)
                            else:
                                new_maps[ni][nj].append(d)
                        else:
                            if d == 1:
                                d = 0
                            elif d == 0:
                                d = 1
                            if d == 2:
                                d = 3
                            elif d == 3:
                                d = 2
                            ndi,ndj = i + direct[d][0], j + direct[d][1]
                            if ndi == sx and ndj == sy:
                                new_maps[i][j].append(d)
                            else:
                                new_maps[ndi][ndj].append(d)
                else:
                    new_maps[i][j] += maps[i][j]
    maps = new_maps
time = 1
answer = 0

while k > 0:
    if [sx,sy] == [n//2,n//2] or [sx,sy] == [0,0]:
        sulae_direct = sulae_direct_map()
    

    run_man()

    sulae_move()

    score = get_score()

    answer += time * score
    k -= 1
    time += 1

print(answer)

 

 

술래가 갈 좌표는 달팽이처럼 업데이트 해주면 된다.

제발!! 실수하지말고!! 복사처리 애매하게 하지말자!!!으아아아악!!!!!

https://sillon-coding.tistory.com/615

 

달팽이 너같은거...

오늘은 달팽이 같은 유형을 코드와 함께 다뤄볼 것이다.시험장에 처음본다면 당황할만하지만, 한번 맛보고 가면 당황스럽지 않다.1. 달팽이 모양으로 들어가기 BFS 처럼 들어가는 방향을 만들어

sillon-coding.tistory.com

 

수정 전 풀이

더보기



from collections import deque
# 하 우 상 좌 반복
n,m,h,k = map(int,input().split())
#nxn,m 술래, h 나무, k 턴
man = [list(map(int,input().split())) for _ in range(m)]
man_num = m # 술래 수
tree = [list(map(int,input().split())) for _ in range(h)]
# 도망자 위치와 이동방법 (x,y,d) //
tree_maps = [[0] * n for _ in range(n)]
for x,y in tree:
    tree_maps[x-1][y-1] = 1
sulae_maps = [[-1] * n for _ in range(n)]
s_direct = ((-1,0),(0,1),(1,0),(0,-1))
sx,sy = n//2,n//2
maps = [[0]*n for _ in range(n)]

def run_man(): # 도망자들
    for i in range(len(man)):
        x,y,d = man[i]
        dist = abs(x - sx) + abs(y - sy)
        dx,dy = d[0],d[1]
        if dist <= 3:
            if 0 <= dx + x < n and 0 <= dy + y < n:
                if [dx+x,dy+y] == [sx,sy]:
                    # 움직이려는 칸에 술래가 있으면 움직이지 않는다
                    continue
                maps[x][y] -= 1
                maps[dx+x][dy+y] += 1
                man[i] = [dx+x,dy+y,d]
            else: # 범위를 벗어나면 방향 틀기
                dx, dy = dx * -1,dy * -1
                if [dx+x,dy+y] == [sx,sy]:
                    # 움직이려는 칸에 술래가 있으면 움직이지 않는다
                    # man[i] = [dx+x,dy+y,d] TODO: 나중에 확인
                    continue
                maps[x][y] -= 1
                maps[dx+x][dy+y] += 1
                man[i] = [dx+x,dy+y,[dx,dy]]
    return
def move_man(): # 술래
    global sx,sy,s_direct, man_num
    if [sx,sy] == [n//2, n// 2 ]:
        s_direct = ((-1,0),(0,-1),(1,0),(0,1))
        # 초기 술래 방향 세팅
        sulae_direction(reverse = False)
    elif [sx,sy] == [0,0]:
        s_direct = ((1, 0), (0, 1), (-1, 0), (0, -1))
        # 반대방향으로 술래 방향 세팅
        sulae_direction(reverse = True)
    d = sulae_maps[sx][sy]
    dx,dy = s_direct[d][0], s_direct[d][1]
    sx,sy = dx + sx, dy + sy
    tmp = []
    cnt = 0
    if maps[sx][sy] > 0 and tree_maps[sx][sy] != 1:
        tmp.append([sx,sy])
        cnt += maps[sx][sy]

    print('술래',sx,sy)
    for i in maps:
        print(i)

    return tmp,cnt

def score(tmp):
    global man
    # 시야 내에 나무가 있는지 확인
    # 시야는 3칸 (술래 위치 포함해서)
    # 술래는 방향을 틀자마자 시야 내에 도망자가 있으면 잡는다
    d = sulae_maps[sx][sy]
    dx,dy = s_direct[d][0], s_direct[d][1]
    cnt2 = 0
    for i in range(1,3):
        nx = sx + dx * i
        ny = sy + dy * i
        if 0 <= nx < n and 0 <= ny < n:
            if tree_maps[nx][ny] != 1 and maps[nx][ny] > 0:
                cnt2 += maps[nx][ny]
                maps[nx][ny] = 0
                tmp.append([nx,ny])
    tmp_man = []
    if tmp:
        for x,y,d in man:
            for tx,ty in tmp:
                if x != tx and y != ty:
                    tmp_man.append([x,y,d])
        man = tmp_man
    return cnt2
def sulae_direction(reverse):
    global sulae_maps
    direction = ((1,0),(0,1),(-1,0),(0,-1))
    queue = deque([[0,0,0]])
    sulae_maps = [[-1] * n for _ in range(n)]
    while queue:
        qx, qy, qd = queue.popleft()
        d = qd % 4
        sulae_maps[qx][qy] = qd
        xx, yy = qx + direction[d][0], qy + direction[d][1]
        if 0 <= xx < n and 0 <= yy < n and sulae_maps[xx][yy] == -1:
            queue.append([xx, yy,qd])
        else:
            d = (qd + 1) % 4
            dx, dy = direction[d][0], direction[d][1]
            if 0 <= qx + dx < n and 0 <= qy + dy < n and sulae_maps[qx + dx][qy + dy] == -1:
                if reverse == True:
                    sulae_maps[qx][qy] = d # 방향 바뀌면 처리
                queue.append([qx + dx, qy + dy, d])

# 초기 도망자 방향 세팅
for i in range(m):
    man[i][0] -= 1
    man[i][1] -= 1
    maps[man[i][0]][man[i][1]] += 1
    if man[i][2] == 1:
        man[i][2] = [0,1]
    elif man[i][2] == 2:
        man[i][2] = [1,0]
time = 1
answer = 0
print('초기맵')
for i in maps:
    print(i)
while k > 0:
    # if 술래 위치 중앙:
    #     방향 튼다 direction =
    # elif 술래 위치 좌상단:
    #     방향튼다
    # TODO: (0,0)에 도착 하자마자 방향이 바뀌어야함
    run_man() # 도망자들
    # print(time,'도망자 이동')
    # for i in maps:
    #     print(i)
    tmp, cnt = move_man() # 술래 움직임
    cnt2 = score(tmp)

    answer += (cnt + cnt2) * time
    man_num -= (cnt + cnt2)
    k -= 1
    time += 1
print(answer)

문제가 된 부분

- 처음에 나무가 있고, 술래가 있고, 도망자가 같이있을때,

나무가 있으면 술래의 시야에 가려져서 도망자는 잡히지 않는다. -> 해결

 

술래는 잘 움직이는데 도망자들이 겹쳐져있을때 로직이 제대로 구현 안됐음 -> 미해결..

 

 

다른 코드는 그냥 도망자의 방향 자체만 계속 리스트에 넣어 업데이트 해주는 형식을 씀

아래처럼..

 

 

다시 풀어보자..

 

 


※ 알아야 할 것

- 복사처리 이상하게 하지말자........................... 리스트는 항상 조심 또 조심

 

728x90
반응형