문제
요약
- 5X5 크기의 대기실에 사람들이 대기한다.
- 맨해튼 거리 2 이하로 앉지 않는다.
- 단, 응시자 사이가 파티션으로 막혀 있다면 허용한다.
분류
- 배열
- (dx/dy)
풀이
1. 내 풀이
- 발상 : 그냥 하라는 거 그대로 하는 직관적 풀이다. 사람(P) 의 위치를 모두 찾는다. 2중 FOR 문으로 모든 경우의 수를 순회하며 조건을 만족시키는지 검사한다.
- P의 인덱스를 순회할 때, 개선이 가능하지만 5X5 배열으로 입력의 크기가 한정적이어서 그냥 놔뒀다.
-
1차 풀이
def isNear(a, b, arr): y1, x1 = a y2, x2 = b dis = abs(x1 - x2) + abs(y1 - y2) if dis == 1: return False elif dis == 2 : if x1 == x2 or y1 == y2: return arr[(y1 + y2) // 2][(x1 + x2) // 2] == 'X' return arr[y1][x2] == 'X' and arr[y2][x1] == 'X' else: return True def solution(places): answer = [] cur = 0 for place in places: cur += 1 arr = [] for i in range(5): for j in range(5): if place[i][j] == 'P': arr.append([i, j]) key = False for i in range(len(arr) - 1): for j in range(i + 1, len(arr)): if not isNear(arr[i], arr[j], place): answer.append(0) key = True break if key : break if len(answer) != cur: answer.append(1) print(answer) return answer
-
2차 풀이 (리팩터링을 진행)
```python for i in range(5): for j in range(5): if place[i][j] == 'P': arr.append([i, j]) ``` 이 코드를 ```python arr = [(i, j) for i in range(5) for j in range(5) if place[i][j] == 'P'] ``` 이렇게 한 줄로 개선한다. \+ 알아두기 - 파이썬에서 커스텀 에러를 raise 하는 방법으로 2중 이상의 for문을 한 번에 break 할 수 있다. ```python class BreakLoop(Exception): pass def solution(places): answer = [] for place in places: arr = [(i, j) for i in range(5) for j in range(5) if place[i][j] == 'P'] try: for i in range(len(arr) - 1): for j in range(i + 1, len(arr)): if not is_near(arr[i], arr[j]): answer.append(0) raise BreakLoop # Custom exception to break out of nested loops else: answer.append(1) except BreakLoop: pass return answer ```
-
최종 코드 - all 함수 기억하자 (모두 true 면 true 반환, 아니면 false) - * (asterisk) 를 활용한 언패킹 - 파이써닉 코드…?
```python def is_near(y1, x1, y2, x2, place): dis = abs(x1 - x2) + abs(y1 - y2) return dis > 1 and (dis != 2 or (x1 == x2 or y1 == y2) and place[(y1 + y2) // 2][(x1 + x2) // 2] == 'X' or place[y1][x2] == place[y2][x1] == 'X') def check(place): arr = [(i, j) for i in range(5) for j in range(5) if place[i][j] == 'P'] return all(is_near(*arr[i], *arr[j], place) for i in range(len(arr) - 1) for j in range(i + 1, len(arr))) def solution(places): return [1 if check(place) else 0 for place in places] ```
2. 프로그래머스 좋아요가 많았던 풀이
- dxdy 코드가 많아서 굳이 안 가져왔다. (dxdy를 활용할 만한 문제인지 모르겠다.)