일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- Queue
- 서버중단
- 논리학
- dfs
- 알고리즘
- github cli
- LiveTemplate
- OVH
- 명제
- Leetcode
- 서버오류
- thymeleaf
- 코테
- 코딩테스트
- char[]
- 자료형
- 백준
- elasticbeanstalk
- Java
- JAVA기초
- 큐
- 통신대란
- springboot
- string
- AWS
- 데이터센터
- Intellij
- 자동완성
- github
- linux
- Today
- Total
Midnight Coder's Lounge
[JavaScript] .slice()에 음수를 넣을 땐 0을 조심하세요 (백준 18110 solved.ac 3% 반례) 본문
[JavaScript] .slice()에 음수를 넣을 땐 0을 조심하세요 (백준 18110 solved.ac 3% 반례)
AtomicLiquors 2025. 2. 20. 13:48요약
- 배열을 자르는 메서드에 .slice(-N), .splice(-N)처럼 음수 인덱스를 넣으면, 배열 맨 끝에서 N번째 항목을 가리키게 할 수 있다.
- 하지만 N = 0이라면? 배열 맨 끝이 아니라 맨 처음을 가리키게 된다. .slice(-N) = .slice(-0) = .slice(0)이기 때문이다.
상세
JavaScript로 백준 18110번 문제 "solved.ac"를 풀고 있었습니다. 주어진 N의 15%에 해당하는 갯수만큼 배열에서 최댓값 / 최솟값을 각각 제외하고 나머지 수들에 대해 평균을 내는 문제입니다. 그렇기 때문에 입력받은 배열을 정렬하고, N의 15%에 해당하는 값(변수명 offset)만큼 배열의 앞뒤에서 slice하는 방식으로 문제를 풀고자 합니다.
따라서 다음과 같이 코드를 작성했습니다.
/* 오답 코드 */
const fs = require('fs');
const input = fs.readFileSync(0, 'utf-8').trim().split('\\n');
const N = Number(input[0]);
if(N === 0){
console.log(0);
return;
}
const offset = Math.round(N * 0.15);
const difficulties = input.slice(1, N+1).map(Number).sort((a, b) => a - b);
const sliced = difficulties.slice(offset, -offset);
const sum = sliced.reduce((acc, e) => acc + e, 0);
console.log(Math.round(sum / (N - offset * 2)));
[제출 결과]
3%에서 오답이 나옵니다.
반올림 연산을 잘못한 건가? 평균값을 잘못 구한 건가?
한참 엉뚱한 데서 반례를 찾다가 결국 아래 코드에 문제가 있다는 걸 알게 되었습니다.
const sliced = difficulties.slice(offset, -offset);
N의 15%가 0이 되는 경우 변수 offset의 값은 0이 됩니다.
예를 들면, 다음과 같이 N이 3인 반례를 들 수 있겠습니다.
[반례]
3
1
2
3
[정답]
2 // slice의 결과는 [1, 2, 3]이 되고 출력 결과는 (1 + 2 + 3) / 3 = 2가 되어야 한다.
[오답]
0 // slice의 결과는 빈 배열 []이 되고 출력 결과는 0으로 나오고 있다.
원래 구상했던 로직대로라면 배열의 앞뒤에서 0만큼을 제외하고 나머지 부분에 대해 평균을 구해야 합니다.
문제는 offset의 값이 0이 되면 .slice(offset, -offset) 은 .slice(0, -0) ⇒ .slice(0, 0) 이 되어 버린다는 겁니다. "배열의 앞에서 0만큼 떨어져서 출발, 뒤에서 0만큼 떨어져서 끝"이 아니라, 그냥 0에서 시작해서 0에서 끝나 버리는 겁니다.
따라서 .slice(offset, -offset) 의 결과는 빈 배열 []가 되어 버립니다.
그렇기 때문에 문제가 되는 코드를 아래와 같이 고쳐야 합니다. 배열 길이인 N에서 offset을 뺀 값, 다시 말해 배열 끝에서 N만큼 떨어진 지점을 사용하겠다는 것을 JavaScript에게 확실하게 알려줘야 합니다.
const sliced = difficulties.slice(offset, N - offset); //-offset에서 N-offset으로 수정.
/* 정답 코드 */
const fs = require('fs');
const input = fs.readFileSync(0, 'utf-8').trim().split('\\n');
const N = Number(input[0]);
if(N === 0){
console.log(0);
return;
}
const offset = Math.round(N * 0.15);
const difficulties = input.slice(1, N+1).map(Number).sort((a, b) => a - b);
const sliced = difficulties.slice(offset, N - offset)
const sum = sliced.reduce((acc, e) => acc + e, 0);
console.log(Math.round(sum / (N - offset * 2)));
[제출 결과]
저는 한참 헤맸지만 멋쟁이 개발자이신 여러분은 이런 실수 때문에 버그를 내는 일이 없기를 바랍니다.
'Algorithm' 카테고리의 다른 글
[JavaScript][백준] 객체는 틀리고, Set은 맞는 이유 (백준 25192번 node.js 풀이 75% 반례) (2) | 2025.02.15 |
---|---|
[백준][JAVA] 2667 - 단지번호붙이기 (11612KB, 64ms, Java 8) (0) | 2024.12.24 |
[백준][JAVA] 2504 - 괄호의 값 (0) | 2024.07.16 |
[백준][JAVA] 3273 - 두 수의 합 (0) | 2024.07.08 |
[백준][JAVA] 3190 - 뱀 (0) | 2023.03.09 |