문제
https://school.programmers.co.kr/learn/courses/30/lessons/120866?language=python3
🐍파이썬
❌ 실패한 코드
def solution(board):
newlist = [[i,j] for i in range(len(board)) for j in range(len(board[i])) if board[i][j] == 1]
answer = len(newlist)
for n in newlist:
for i in [-1, 0, 1]:
for j in [-1, 0, 1]:
if n[0]+i < len(board[0]) and n[1]+j < len(board[1]):
if board[n[0]+i][n[1]+j] == 0:
board[n[0]+i][n[1]+j] = 1
answer += 1
return len(board[0])**2 - answer
- 7번 라인 0 <= 바운더리 설정하지 않아서
- 테스트케이스 1번 오류 발생
- 테스트9 런타임에러 발생
def solution(board):
newlist = [[i,j] for i in range(len(board)) for j in range(len(board[i])) if board[i][j] == 1]
answer = len(newlist)
for n in newlist:
for i in [-1, 0, 1]:
for j in [-1, 0, 1]:
if 0 <= n[0]+i < len(board) and 0 <= n[1]+j < len(board):
if board[n[0]+i][n[1]+j] == 0:
board[n[0]+i][n[1]+j] = 1
answer += 1
return len(board)**2 - answer
1️⃣ newlist에 지뢰의 위치를 저장한다.
2️⃣ answer에는 안전지대가 아닌 지역의 갯수를 저장한다. 따라서 newlist에서 구한 지뢰의 갯수를 넣어 answer을 초기화해준다.
3️⃣ 지뢰의 위, 아래, 좌우, 대각선의 좌표를 이중 for문으로 돌며 각 좌표를 방문한다.
i = -1 -> j = -1, 0, 1 ☞ 위/왼쪽대각선, 위, 위/오른쪽대각선
i = 0 -> j = -1, 0, 1 ☞ 좌, 지뢰, 우
i = 1 -> j = -1, 0, 1 ☞ 아래/왼쪽대각선, 아래, 아래/왼쪽대각선
---총 9회 반복한다.
4️⃣ 지뢰의 위, 아래, 좌우, 대각선 좌표가 배열의 바운더리를 벗어난 경우 방문하지 않게 하기 위해 0 <= n[0]+i < len(board) and 0 <= n[1]+j < len(board) 조건을 추가한다.
5️⃣ 각 좌표를 방문하면서 안전지대 표시를 1(비안전지대)로 바꾸고 그때마다 안전지대가 아닌 지역을 카운팅하기 위해 answer에 1을 더해준다.
6️⃣ 모든 좌표 방문이 끝났다면 전체 배열 길이에서 비안전지대 갯수를 빼서 안전지대 갯수를 구한다.
def solution(board):
newlist = [[i,j] for i in range(len(board)) for j in range(len(board[i])) if board[i][j]==1]
answer = len(newlist)
x_arr = [-1, -1, -1, 0, 0, 1, 1, 1]
y_arr = [-1, 0, 1, -1, 1, -1, 0, 1]
for x, y in newlist:
for i in range(8):
new_x = x + x_arr[i]
new_y = y + y_arr[i]
if 0 <= new_x < len(board) and 0 <= new_y < len(board):
if board[new_x][new_y] == 0:
board[new_x][new_y] = 1
answer += 1
return len(board)**2 - answer
1️⃣ newlist에 지뢰의 위치를 저장한다.
2️⃣ answer에는 안전지대가 아닌 지역의 갯수를 저장한다. 따라서 newlist에서 구한 지뢰의 갯수를 넣어 answer을 초기화해준다.
3️⃣ x_arr과 y_arr에는 방문해야 할 x, y 좌표를 각각 저장했다. 순서대로 위/왼쪽대각선, 위, 위/오른쪽대각선, 좌, 우, 아래/왼쪽대각선, 아래, 아래/왼쪽대각선 이다. (지뢰를 0,0으로 표시했을 때를 기준으로 한다.)
4️⃣ 현재 지뢰의 좌표에 x_arr과 y_arr 배열의 좌표를 더한 뒤 지뢰를 기준으로 8개의 좌표를 순서대로 방문한다.
5️⃣ 지뢰의 위, 아래, 좌우, 대각선 좌표가 배열의 바운더리를 벗어난 경우 방문하지 않게 하기 위해 0 <= n[0]+i < len(board) and 0 <= n[1]+j < len(board) 조건을 추가한다.
6️⃣ 좌표를 방문하면서 안전지대 표시를 1(비안전지대)로 바꾸고 그때마다 안전지대가 아닌 지역을 카운팅하기 위해 answer에 1을 더해준다.
7️⃣ 모든 좌표 방문이 끝났다면 전체 배열 길이에서 비안전지대 갯수를 빼서 안전지대 갯수를 구한다.
다른 풀이 방법
def solution(board):
n = len(board)
danger = set()
for i, row in enumerate(board):
for j, x in enumerate(row):
if not x:
continue
danger.update((i+di, j+dj) for di in [-1,0,1] for dj in [-1, 0, 1])
return n*n - sum(0 <= i < n and 0 <= j < n for i, j in danger)
enumerate의 i, j 부분은 각 원소의 인덱스이다.
enumerate를 통해 for문을 돌면서 지뢰의 위치를 찾아 좌표를 더해 비안전지대를 체크하는 것까지 한 번에 수행하고 있다. 바운더리 계산없이 우선 비안전지대를 체크한 뒤 추후 바운더리 체크 조건에 해당하는 값만 sum()으로 합해서 전체 board길이에서 빼주었다.
def solution(board):
answer = 0
for col in range(len(board)):
for row in range(len(board[col])):
if board[row][col] == 1:
for j in range(max(col-1,0),min(col+2,len(board))):
for i in range(max(row-1,0),min(row+2,len(board))):
if board[i][j] == 1:
continue
board[i][j] = -1
for i in board:
answer += i.count(0)
return answer
바운더리 처리를 min, max로 진행했다.
🐥자바스크립트
function solution(board) {
let arr = [];
for (let i = 0; i < board[0].length; i++){
for (let j = 0; j < board[0].length; j++){
if (board[i][j] === 1){
arr.push([i,j]);
}
}
}
let answer = arr.length;
for (let k of arr){
for (let l of [-1, 0, 1]){
for (let m of [-1, 0, 1]){
if ((0 <= (k[0]+l) && (k[0]+l) < board[0].length) && (0 <= (k[1]+m) && (k[1]+m) < board[0].length)){
if (board[k[0]+l][k[1]+m] === 0){
board[k[0]+l][k[1]+m] = 1
answer++;
}
}
}
}
}
return board.length ** 2 - answer;
}
* 파이썬 1번 풀이와 동일하게 풀었다.
1️⃣ newlist에 지뢰의 위치를 저장한다.
2️⃣ answer에는 안전지대가 아닌 지역의 갯수를 저장한다. 따라서 newlist에서 구한 지뢰의 갯수를 넣어 answer을 초기화해준다.
3️⃣ 지뢰의 위, 아래, 좌우, 대각선의 좌표를 이중 for문으로 돌며 각 좌표를 방문한다.
i = -1 -> j = -1, 0, 1 ☞ 위/왼쪽대각선, 위, 위/오른쪽대각선
i = 0 -> j = -1, 0, 1 ☞ 좌, 지뢰, 우
i = 1 -> j = -1, 0, 1 ☞ 아래/왼쪽대각선, 아래, 아래/왼쪽대각선
---총 9회 반복한다.
4️⃣ 지뢰의 위, 아래, 좌우, 대각선 좌표가 배열의 바운더리를 벗어난 경우 방문하지 않게 하기 위해 (0 <= (k[0]+l) && (k[0]+l) < board[0].length) && (0 <= (k[1]+m) && (k[1]+m) < board[0].length) 조건을 추가한다.
5️⃣ 각 좌표를 방문하면서 안전지대 표시를 1(비안전지대)로 바꾸고 그때마다 안전지대가 아닌 지역을 카운팅하기 위해 answer에 1을 더해준다.
6️⃣ 모든 좌표 방문이 끝났다면 전체 배열 길이에서 비안전지대 갯수를 빼서 안전지대 갯수를 구한다.
다른 풀이 방법
function solution(board) {
let outside = [[-1,0], [-1,-1], [-1,1], [0,-1],[0,1],[1,0], [1,-1], [1,1]];
let safezone = 0;
board.forEach((row, y, self) => row.forEach((it, x) => {
if (it === 1) return false;
return outside.some(([oy, ox]) => !!self[oy + y]?.[ox + x]) ? false : safezone++;
}));
return safezone;
}
이중 forEach문, !!, ?. 사용.
?.부분이 이해가 안 간다...
💫 참고
❗ forEach()
형태: arr.forEach((처리할 현재 요소, 처리할 현재 요소의 인덱스, forEach를 호출한 배열) => {각 요소에 대해 실행할 함수})
출처: https://tinyurl.com/2zucpb7r
❗❗ some()
배열 안의 요소가 주어진 판별 함수를 적어도 하나라도 통과하면 true 그렇지 않으면 false를 반환한다.
callbak 함수는 3가지 인자를 갖는다.
- element 처리할 배열 내 현재 요소
- index 처리할 현재 요소의 인덱스
- array some()을 호출한 배열
❗❗❗ 느낌표 두개 (Double Exclamation Operation)
object를 boolean 형으로 변환하는 연산자
[undefined, "", 0] 일 경우 결과는 false, 그 외의 결과는 모두 true
- !! 0 –> false
- !! null –> false
- !! undefined –> false
- !! 48 –> true
- !! “hello” –> true
- !! [1, 2, 3] –> true
출처: https://www.codingem.com/javascript-double-exclamation-operator/
❗❗❗❗ ?. (optional chaining)
- 프로퍼티가 없는 중첩 객체를 에러 없이 안전하게 접근하기 위한 문법 ☞ 즉, 존재하지 않는 요소(null, undefined)에 접근해 정보를 가져오려 할 때 오류가 발생하는 문제를 해결하기 위한 문법
- ?.'앞’의 평가 대상이 undefined나 null이면 평가를 멈추고 undefined를 반환
//기존 방법
let nestedProp = obj.first && obj.first.second;
//optional chaining
let nestedProp = obj.first?.second;
- obj.first?.second : obj.first가 존재하면 obj.first.second을 반환, 그렇지 않으면 undefined를 반환함
출처
https://ko.javascript.info/optional-chaining
function solution(b) {
const directions = [[0,0],[0,1],[0,-1],[1,1],[1,0],[1,-1],[-1,-1],[-1,0],[-1,1]]
let bombSet = new Set();
for(let i = 0; i < b.length; i++) {
for(let j = 0; j < b[i].length; j++) {
if(b[i][j] == 1) {
directions.forEach(el => {
let [nextX, nextY] = el;
[nextX, nextY] = [i+nextX, j+nextY];
if(nextX >= 0 && nextX < b.length && nextY >= 0 && nextY < b[i].length) {
bombSet.add(nextX+' '+nextY);
}
})
}
}
}
return b.length * b[0].length - bombSet.size;
}
'Problem Solving > 프로그래머스' 카테고리의 다른 글
[프로그래머스 | 파이썬 / 자바스크립트] 모음제거(코딩테스트 입문/ level 0) (0) | 2023.02.22 |
---|---|
[프로그래머스 | 파이썬 / 자바스크립트] 둘만의 암호(연습문제/ level 1) (0) | 2023.02.22 |
[프로그래머스 | 파이썬 / 자바스크립트] 순서쌍의 개수(코딩테스트 입문/ level 0) (0) | 2023.02.22 |
[프로그래머스 | 파이썬 / 자바스크립트] 자릿수 더하기(코딩테스트 입문/ level 0) (0) | 2023.02.21 |
[프로그래머스 | 파이썬 / 자바스크립트] n의 배수 고르기(코딩테스트 입문/ level 0) (2) | 2023.02.21 |
[프로그래머스 | 파이썬 / 자바스크립트] 최댓값 만들기 (2)(코딩테스트 입문/ level 0) (0) | 2023.02.21 |