알고리즘/알고리즘_swea

[Python][SWEA] 11315. 오목 판정 D3

Jerry_K 2024. 5. 8. 07:49
 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com


🗒️ 파이썬 코드 풀이

def omok(N) : 
    di,dj = [0,1,1,1],[1,1,0,-1]
    for i in range(N) :
        for j in range(N): 
            if lst[i][j] == 'o' :
                for k in range(4):
                    cnt = 1
                    for mul in range(1,N):
                        ni = i + di[k] * mul
                        nj = j + dj[k] * mul
                        if 0<=ni<N and 0<=nj<N :
                            if lst[ni][nj] == 'o' :
                                cnt += 1 
                                if cnt == 5 :
                                    return "YES"
                            else :  break  
    return "NO"


T = int(input())
for tc in range(1,T+1) :
    N = int(input())
    lst = [ list(input()) for _ in range(N)]
    ans = omok(N)
    print(f"#{tc} {ans}")

 

1. 이런 방향문제가 나오면 di,dj를 가장 먼저 기억하자

 

2. omok 함수를 만들었다.

 

3. 모든 돌을 다 돌아서 체크를 하는데 그 중 'o' 인 것만 체크하면 된다.

 

4. 네방향 (0,1) / (1,1) / (1,0) / (1,-1)  (3시~7시 방향) 으로 설정했다. 

 

5. 한 방향을 움직일때, 한번에 N번 만큼 되도록 했다. 

(for mul 부분과 for k 부분의 위치가 바뀌면 다른 형상이 되니 주의)

 

6. ni, nj 선언 후 if 문으로 범위 초과를 제한 한다.

 

7. cnt를 누적해서 5로 카운트하고, 5가 될 때 return을 해준다.

 

8.  'o'가 아닌 경우 break를 걸어주는데, 돌 개수의 조건이 연속적이기 때문이다. 

즉, 한번이라도 'o'가 안되면 연속이 아니기 때문에 mul 반복문을 빠져나오고 다른 방향으로 전환한다.

(이 부분 안하면 83번째에 에러 발생하니 주의 !!)

 

 

📌 내가 작성한 코드

T = int(input())
for tc in range(1,T+1) : 
    N = int(input())
    lst = [list(input()) for _ in range(N)]
    di = [0,1,1,1] 
    dj = [1,1,0,-1]    
    state = 0

    for i in range(N) : 
        for j in range(N) :       
            if lst[i][j] == "o" :
                
                for k in range(4) : # 4방향
                    cnt = 0
                    for n in range(N) : # 특정 방향 N만큼 체크
                        
                        ni = i + di[k]*n
                        nj = j + dj[k]*n
                        
                        if 0<=ni<N and 0<=nj<N :                   
                            if lst[ni][nj] == "o":
                                cnt += 1
                                if cnt == 5 :  
                                    state = 1
                            else: 
                                break 
                            
    if state == 1 :
        print(f"#{tc} YES")
    else :
        print(f"#{tc} NO")​

 

전체적인 문제접근은 틀리지 않았지만, 시간을 좀 잡아먹은 것은 di,dj를 실수 한 것이다. 

일단 그래프라 생각해서 위로 가는 방향을 +1로하고 아래로 가는 방향을 -1로 했다. 

이게 당연히 맞다고 생각하니, 여러번봐도 뭐가 틀린지 잘 몰랐다 한참을 로그 찾다 발견했다.

di,dj를 설정할 때, 오늘의 실수를 기억하면서 조심하자 !

 

🔍코드 개선점

다른 코드와 비교해서 좀 아쉬운 점은

 

1. for n in range(N)  ->  사소한 것인데, n보다는 mul이라고해서 좀 더 명확하게 변수를 설정하자

 

2. 이렇게 다중 for문이 나왔을때, 어떻게하면 한번에 break를 할 수 있을까 생각했다. 

그냥 이럴때는 함수를 써서 return하면 훨씬 깔끔해질 것이다.

 


📚 문제

N X N 크기의 판이 있다. 판의 각 칸에는 돌이 있거나 없을 수 있다. 돌이 가로, 세로, 대각선 중 하나의 방향으로 다섯 개 이상 연속한 부분이 있는지 없는지 판정하는 프로그램을 작성하라.

  

[입력]

첫 번째 줄에 테스트 케이스의 수 T가 주어진다.

각 테스트 케이스의 첫 번째 줄에는 하나의 정수 N(5 ≤ ≤ 20)이 주어진다.

다음 N개의 줄의 각 줄에는 길이 N인 문자열이 주어진다. 각 문자는 ‘o’또는 ‘.’으로, ‘o’는 돌이 있는 칸을 의미하고, ‘.’는 돌이 없는 칸을 의미한다.

  

[출력]

각 테스트 케이스 마다 돌이 다섯 개 이상 연속한 부분이 있으면 “YES”를, 아니면 “NO”를 출력한다.