📙 1. 문제
Link : https://school.programmers.co.kr/learn/courses/30/lessons/72412?language=javascript
[프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr](https://school.programmers.co.kr/learn/courses/30/lessons/72412?language=javascript)
문제 설명
🌈 2.시작하며
풀이 과정 1 (시간 초과 풀이)
처음에는 객체를 사용하려다가, 객체를 사용하여 javascript,css.. 등 각각 매칭시키면 javascript-backend등 연관을 못시켜서 객체를 사용하지 않고 노가다로 풀었다.
function solution(info, query) {
var answer = [];
info = info.map(it => it.split(' '))
query.forEach(item=>{
const needs = item.split('and').map(it=>it.trim())
const [a,b] = [needs[3].split(' ')[0],needs[3].split(' ')[1]];
needs[3]=a;
needs.push(+b)
let minValue = Infinity
let infoDup = [...info];
for(let i=0;i<5;i++){
if(needs[i]==='-') continue;
if(i===4){
infoDup = infoDup.filter(it=>+it[4]>=+needs[i])
continue;
}
infoDup = infoDup.filter(it=>it[i]===needs[i])
}
answer.push(infoDup.length)
})
return answer;
}
💻 결과
filter를 이용하여 해당하는 요소가 있을 때까지 거르고 걸렀다. 그리고, 걸러진 배열의 크기를 반환하였다. 정확성 테스트는 통과하였지만 역시나 시간초과에 걸려 효율성 테스트는 실패하였다.
풀이 과정 2 : 객체 이용 but 시간초과
시간을 단축시키려면 아무래도 객체 사용하는 것이 최선이라 생각하여 객체를 사용하였다.
function solution(info, query) {
var answer = [];
// 객체로 저장 -> key: 언어+직군+경력+소울푸드 | value : 점수
// key로 검색하여 value로 탐색
const object = {};
info.forEach(it=>{
const arr = it.split(' ');
const score = +arr.pop();
const name = arr.join('')
object[name]=!!object[name]?[...object[name],score]:[score];
})
query.forEach(item=>{
let queryArr = item.split('and').map(it=>it.trim());
const score = +queryArr[3].split(' ')[1]
queryArr[3] = queryArr[3].split(' ')[0]
let keyValues = Object.keys(object);
for(let i=0;i<4;i++){
if(queryArr[i]==='-')continue;
keyValues = keyValues.filter(key=>key.includes(queryArr[i]))
}
let cnt = 0;
keyValues=keyValues.filter(key=>{
object[key].forEach(it=>{
if(it>=score) cnt++;
})
});
answer.push(cnt)
})
return answer;
}
풀이 3 : 다른 사람 풀이
// 이분 탐색입니다. 해당 값이 어느 인덱스에 있을지를 탐색하여 결과를 반환합니다.
const binarySearch = (arr, target) => {
let left = 0;
let right = arr.length - 1;
let mid = Math.floor((left + right) / 2);
while(left <= right) {
if (arr[mid] === target) return mid;
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
mid = Math.floor((left + right) / 2);
}
// 기준이 되는 인덱스는, 여기서 나온 값보다 항상 1이 더 큽니다. 따라서 +1을 해주죠!
return mid + 1;
}
const getInfos = (info) => {
const infos = {}; // object를 생성해줄 거에요.
info.forEach(infoString => { // 이제 object에 `info`를 처리해줘야겠죠?!
const arr = infoString.split(" "); // 먼저 " " 기준으로 string을 분리해줍시다.
const score = parseInt(arr.pop()); // 정수로 바꿔줄 거에요.
const key = arr.join(""); // key를 javabackendjuniorpizza와 같은 형태로 해줄 거에요.
if (infos[key]) infos[key].push(score)
else infos[key] = [score]; // [150]의 형태로 배열에 점수를 넣어줘요.
});
for (const key in infos) {
// 다 처리된 이후에는 각 키의 점수 배열을 정렬해줍니다.
// 이건 이분탐색을 위한 거에요.
infos[key].sort((a, b) => a - b);
}
return infos;
}
const getResult = (infos, query, score) => {
// 키들을 배열 형태로 갖고 옵시다.
const infosKey = Object.keys(infos);
// 여기서 이제 키들에 대해 쿼리 조건을 만족하는 것들을 필터링해서 배열로 반환하고 (filter)
// reduce로 전체 점수 배열의 길이값 - 이분 탐색 결과 인덱스 값을 해줍니다.
// 그러면 결국 값이 같거나 큰 애들의 수만큼 값이 나오겠죠? (정렬되어 있으니까요)
// 이를 누산해줍니다.
return infosKey
.filter(key => query.every(v => key.includes(v)))
.reduce((acc, key) => acc + infos[key].length - binarySearch(infos[key], score), 0);
}
const solution = (info, query) => {
let answer = [];
const infos = getInfos(info); // solution
query
.map(q => q
.split(/ and | |-/i) //' and '와 ' '와 '-'이 들어가 있는 친구들 기준으로 split 처리해줘요.
.filter(v => v !== "") // `split`에 의해 값이 "" 처리가 된 친구들을 없애줍니다.
) // 쿼리 조건들을 필터링해줄 거에요.
.forEach(query => {
const score = query.pop();
const result = getResult(infos, query, score);
answer.push(result) // getResult로 인해 누산된 결과값을, answer에 넣어줍시다.
})
return answer;
}
필요한 요소들을 함수화시켜서 묶었다. 확실히 함수화시켜주니 main함수가 깔끔하다.
- 함수
1. getInfos(info) : 주어진 info배열을 object화 시켜주어 반환하는 함수
2.getResult(infos,query,score) : 결과를 반환하는 함수 (일치하는 값을 반환)
함수의 장점은 함수scope를 갖게되어 기존 값을 변경하지 않는다 : 함수형 프로그래밍 - 불변성
3. binarySearch(arr,target) : 이분 탐색하여 해당 값이 어느 인덱스에 있을지를 탐색하여 결과를 반환 - 정규표현식을 사용하여 손쉽게 split하였다.
.split(/ and | |-/i)
🤔 3. 느낀 점
문제를 풀면서, "이게 무슨 변수지"하면서 위에로 돌아가서 코드를 다시 읽은 것이 한 두번이 아니다. 앞으로는 위의 다른사람 풀이처럼 변수명을 직관적으로 "이 변수!"알 수 있도록 변수명을 짓도록 하자.
그리고, 이전에 함수화 시켜서 문제를 풀다가 풀이가 더 복잡해져서 한동안 하지 않았었는데, 다시보니 깔끔하고 실수가 더 줄것이라고 느꼈다. 상황에 따라 함수화를 잘 시켜보도록 하자.
🤩 4. 한 번 더 짚고 갈 점
어려웠다.. 쉽지 않았다. 다음 번에 꼭 이 문제를 다시 풀도록 하자. 그리고, 위의 young_paleete님의 풀이같은 "좋은 코드"를 자주 보도록 하자. 그리고, 따라하자. 따라하고, 변형하다보면 내 것이 될 것이다.
'코딩 테스트 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] 거리두기 확인하기 (0) | 2023.05.14 |
---|---|
[프로그래머스] 방금 그곡 (1) | 2023.05.13 |
[프로그래머스] 후보키 (0) | 2023.05.12 |
[프로그래머스] 문자열 압축 (0) | 2023.05.11 |
[프로그래머스] 양궁대회 (1) | 2023.04.30 |
[프로그래머스] 게임 맵 최단거리 (0) | 2023.04.29 |
[프로그래머스] 이모티콘 할인행사 (0) | 2023.04.28 |
[프로그래머스] 택배 배달과 수거하기 (0) | 2023.04.27 |