https://www.acmicpc.net/problem/5533

삼중 for문으로 배열을 만들어 해결하려 했다. 이중 for문까지는 각 행을 탐색하고, 삼중 for문에서 각 열에 동일한 숫자가 있는지 확인하는 방법이다. 애초에 for문이 삼중으로 들어가는 논리도 아직 낯설뿐더러 scope 지정에서 문제가 생기고 결정적으로 코드가 너무 더러워 보였다,, for문을 최대한 자제하는 방법으로 찾아보았다.
const [n, ...strs] = require('fs').readFileSync('test.txt').toString().trim().split('\n');
const arr = strs.map(str => str.split(' ').map(Number));
let arrMap = Array.from({length : 3})
.map((_,i) => arr
.map((v) => v[i])
.reduce((acc,k) => (acc[k] ? acc[k]+=1 : acc[k]=1, acc),{}));
let answer = arr
.map((arr) => arr
.map((v,i) => arrMap[i][v] === 1 ? v : 0)
.reduce((acc,v) => acc+v),0);
for(let i =0;i<answer.length;i++) {
console.log(answer[i])
};
1. 구조 분해 할당
처음 input을 받을 때 부터 입력의 첫 번째 요소와 분리한 후 받는다.
const fs = require('fs');
const [n,...strs] = fs.readFileSync('test.txt').toString().trim().split('\n');
console.log(strs) //[ '100 99 98', '100 97 92', '63 89 63', '99 99 99', '89 97 98' ]
2. 각 요소도 배열로 분리
비교를 위해서 각각 배열에 담아 새로운 배열로 만들어야 한다. split()은 string에만 쓸 수 있기 때문에, 1번의 배열 그대로 사용하면 오류가 발생한다. 따라서 매핑해서 각 요소마다 split() 해주는 식으로 나눠야 한다. split()은 문자열을 나눠 배열로 반환하기 때문에, 바로 map() 메서드 사용이 가능하고 각 배열 요소의 자료형을 숫자로 바꿔준다.
const arrs = strs.map(str => str.split(' ').map(Number));
console.log(arrs)
// [
// [ 100, 99, 98 ],
// [ 100, 97, 92 ],
// [ 63, 89, 63 ],
// [ 99, 99, 99 ],
// [ 89, 97, 98 ]
// ]
3. 배열을 게임 단위로 정렬하고 객체에 담기
빈 배열에 각 열의 요소들을 모은다. 첫번째 맵은 인덱스를 제공하기 위한 콜백 함수 이므로 요소 값은 필요 없다(_). 인덱스를 넘겨받은 두 번째 맵의 콜백함수에서 각 열끼리 모은 배열이 완성된다. 즉, 이차원 배열 arr의 가로와 세로를 바꾼 배열이 완성된다. reduce() 메서드를 이용해 중복을 체크한 후 객체로 반환한다. 게임당 객체가 하나 생성될 테고 (3게임, 3객체) n명의 참가자가 있다면 각 객체의 value 합은 n이 된다.
let arrMap = Array.from({length : 3})
.map((_,i) => arr
.map((v) => v[i]) // 여기까지의 과정은 이차원 배열의 가로 세로를 바꾸는 방법이다.
.reduce((acc,k) => (acc[k] ? acc[k]+=1 : acc[k]=1, acc),{}));
console.log(arrMap)
// [
// { '63': 1, '89': 1, '99': 1, '100': 2 },
// { '89': 1, '97': 2, '99': 2 },
// { '63': 1, '92': 1, '98': 2, '99': 1 }
// ]
4. 중복된 숫자를 걸러내고, 결과값의 합계 구하기
첫번째 맵에서 각 요소에 적용할 콜백함수를 정의하고 두 번째 맵에서 객체의 요소가 중복이 없는지 확인한다. 두 번째 맵에서 arrMap [i] 번째 객체를 지정하고, [v]는 객체의 대괄호 표기법으로 키값인 v의 value 값을 가리킨다.
let answer = arr
.map((x) => x
.map((v,i) => arrMap[i][v] === 1 ? v : 0)
.reduce((acc,v) => acc+v),0);
console.log(answer)
//[ 0, 92, 215, 198, 89 ]
5. 요구사항에 맞게 출력
배열에서 각 요소들을 꺼내도록 for문 작성
for(let i of solution(arrs)) {
console.log(i)
}
// 0
// 92
// 215
// 198
// 89
- 백준 문제를 node.js 로 풀 때는 입력받는 것부터 난제다.. 각 문제에 맞게 처음부터 입력을 어떻게 받을지 한참 고민해야 한다. 자료를 원하는 모양으로 받고 배열로, 숫자로 바로 바꿀 수 있을 만큼 연습해야겠다.
- 메서드들의 특징이나, 알맞은 용도에 대해 숙달이 부족했다. split()이 문자열에만 적용되는 줄 몰랐다던지, 객체를 표기할 때 대괄호 표기법을 사용해야만 하는 상황이 있다는 것, new Array와 Array.from()의 차이 등등 꼭 정리하고 넘어가도록 한다.
- 함수형 객체지향 언어를 쓰고 있으면 그에 알맞게 써야한다. 활용하지 못하고 기초문법의 반복이나 재선언으로 작성하려 하면 이해하기 어렵고 보기 더러운 코드가 된다.
'Study > Algorithm' 카테고리의 다른 글
<programmers / JavaScript> 로또의 최고 순위와 최저 순위 (0) | 2022.05.18 |
---|---|
[programmers / JavaScript] K번째 수 (0) | 2022.05.06 |
[programmers / JavaScript] 숫자 문자열과 영단어 (0) | 2022.04.30 |
<BEAKJOON / node.js> 10828 스택 (0) | 2022.04.29 |
<BEAKJOON> 4344 JavaScript (0) | 2022.04.26 |