과제 04
https://github.com/wooahan-agile/coding-test-study-3term/pull/47
완주하지 못한 선수 (무조건 Object 타입을 이용하여 풀기)
https://programmers.co.kr/learn/courses/30/lessons/42576
코딩테스트 연습 - 완주하지 못한 선수
수많은 마라톤 선수들이 마라톤에 참여하였습니다. 단 한 명의 선수를 제외하고는 모든 선수가 마라톤을 완주하였습니다. 마라톤에 참여한 선수들의 이름이 담긴 배열 participant와 완주한 선수
programmers.co.kr
멘토님 조언 듣고 푼 코드
function solution(participant, completion) {
const marathon = {};
// 참여자 이름 키로 저장
for (let i in participant) {
marathon[participant[i]] = 0;
}
// 참여자 수 값에 저장
for (let i in participant) {
marathon[participant[i]] += 1;
}
// 참여자에서 완주자 빼기
for (let i in completion) {
marathon[completion[i]] -= 1;
}
// 참여자 수가 1인 참여자 리턴하기
for (let i in marathon) {
if (marathon[i] === 1) {
return i;
};
};
}
위 코드를 리팩토링
function solution(participant, completion) {
const marathon = {};
for (let player of participant) {
player in marathon ? (marathon[player] += 1) : (marathon[player] = 1);
}
for (let finishPlayer of completion) {
marathon[finishPlayer] -= 1;
}
for (let noCompletion in marathon) {
if (marathon[noCompletion] === 1) return noCompletion;
}
}
리뷰
- 변수명 더 신경쓰기
- marathon 은 참가자가 몇 명인지에 대한 객체이기 때문에 marathon이 아니라 players 로 변수명을 적는 게 더 적합
- forEach 사용하기
// 기존 코드
for (let player of participant) {
player in marathon ? (marathon[player] += 1) : (marathon[player] = 1);
}
// 멘토님이 forEach를 사용한 수정 코드
participant.forEach((part) => {
return (part in players) ? (players[part] += 1) : (players[part] = 1);
});
- 멘토님 풀이
// 기존 코드
for (let finishPlayer of completion) {
marathon[finishPlayer] -= 1;
}
for (let noCompletion in marathon) {
if (marathon[noCompletion] === 1) return noCompletion;
}
// 멘토님 코드
for (let comp of completion) {
if (players[comp] > 0) players[comp] -= 1;
if (players[comp] === 0) delete players[comp];
}
return Object.keys(players).toString();
forEach와 map
- forEach
const arr = [1, 2, 3];
const forEachArr = [];
arr.forEach((num) => forEachArr.push(num + 1));
console.log(forEachArr) // [2, 3, 4];
- map
const arr = [1, 2, 3];
const mapArr = arr.map((num) => num + 1);
console.log(mapArr); // [2, 3, 4]
- forEach를 map처럼 사용하면?
const arr = [1, 2, 3];
const forEachArr = arr.forEach((num) => num + 1);
console.log(forEachArr) // undefined
- forEach와 map의 차이는 새로운 배열을 반환하냐 그렇지 않냐에 있다.
- forEach는 빈 배열을 만들고 그 안에 넣는다면, map은 바로 변수에 넣는 방법
- 그렇기 때문에 forEach를 map처럼 빈 배열을 선언하지 않고 사용한다면 정의되지 않았기 때문에 undefined가 출력된다.
로또의 최고 순위와 최저 순위
https://programmers.co.kr/learn/courses/30/lessons/77484
코딩테스트 연습 - 로또의 최고 순위와 최저 순위
로또 6/45(이하 '로또'로 표기)는 1부터 45까지의 숫자 중 6개를 찍어서 맞히는 대표적인 복권입니다. 아래는 로또의 순위를 정하는 방식입니다. 1 순위 당첨 내용 1 6개 번호가 모두 일치 2 5개 번호
programmers.co.kr
function solution(lottos, win_nums) {
const lottoGrade = [6, 6, 5, 4, 3, 2, 1];
const myGrades = [];
const answer = [];
let zeroCount = 0;
let correctAnswerCount = 0;
lottos.forEach((myNumber) => {
win_nums.forEach((winNumber) => {
if (myNumber === winNumber) {
correctAnswerCount += 1;
}
});
if (myNumber === 0) {
zeroCount += 1;
}
});
myGrades.push(lottoGrade[correctAnswerCount]);
if (zeroCount) {
for (let zero = 0; zero < zeroCount + 1; zero++) {
myGrades.push(lottoGrade[correctAnswerCount]);
correctAnswerCount += 1;
}
}
answer.push(Math.min(...myGrades), Math.max(...myGrades));
return answer;
}
리뷰
- 멘토님 풀이 코드
function solution(lottos, win_nums) {
const zero = lottos.filter(lotto=> lotto === 0).length;
const rate = [6, 6, 5, 4, 3, 2, 1]
let correct = 0;
lottos = lottos.filter(lotto => lotto !== 0);
for (let lotto of lottos) {
if (win_nums.includes(lotto)) correct += 1;
}
return [rate[zero + correct], rate[correct]];
}
... 나는 왜 이렇게 코드가 길지...? 역시 더 효율적인 코드가 있었던 거야..
// 내가 작성한 코드 중
lottos.forEach((myNumber) => {
win_nums.forEach((winNumber) => {
if (myNumber === winNumber) {
correctAnswerCount += 1;
}
});
if (myNumber === 0) {
zeroCount += 1;
}
});
- 반복문을 한 번만 사용하고 풀 수 있음. 내가 작성한 코드는 lottos의 원소 하나와 win_nums의 원소 모두를 비교해가며 일치하는 게 있는지 찾는 코드이므로 특정 값이 배열에 존재하는지 찾는 것인데 includes() 메소드를 사용하면 됨
// 내가 작성한 코드 중
if (zeroCount) {
for (let zero = 0; zero < zeroCount + 1; zero++) {
myGrades.push(lottoGrade[correctAnswerCount]);
correctAnswerCount += 1;
}
}
- myGrades에 최고 순위부터 최저 순위까지 중간 순위 전부가 들어있음. 반복해 들어가는 순위도 있음. 이미 위에서 0의 개수와 맞은 숫자들의 개수를 전부 세었으니 조건문과 반복문을 사용하지 않아도 됨. 최저 순위는 correctAnswerCount 만큼 맞췄을 때, 최고 순위는 correctAnswerCount + zeroCount 만큼 맞췄을 때임. 몇 개 맞았을 때 몇 등인지 고민해보기. ⇒ 등수 배열의 인덱스가 맞춘 개수이므로 myGrade 배열 이용하면 됨!
// 내가 작성한 코드
answer.push(Math.min(...myGrades), Math.max(...myGrades));
return answer;
// 멘토님 수정 코드
return [Math.min(...myGrades), Math.max(...myGrades)];
- 굳이 answer 변수를 사용해 push하는 과정을 거칠 필요 없음
TIL
- for ... in 반복문은 인덱스, for ... of 반복문은 배열의 원소가 되는 것
- Spread Operator(전개 연산자)
- ... 점 3개로 표현
- 객체나 배열의 원소들을 하나씩 꺼내어 펼쳐서 리턴
- ex)
- const arr = [1, 2, 3, 4, 5];console.log(Math.max(...arr)); // 5
- 좋은 알고리즘의 분석 기준
- Correctness : 문제를 해결하는가
- Efficiency : 이를 효과적으로 하는가
- 정확성, 작업량, 기억 장소 사용량, 최적성, 복잡도(빅O 표기법)
- includes()
- 문자열이 특정 문자열을 포함하는지 확인하는 메서드
- 대소문자 구분함
- string.includes( searchString, length )
- searchString : 검색할 문자열(필수 요소)
- length : 검색을 시작할 위치(선택 요소, 값이 없으면 전체 문자열을 대상으로 함)
- ex)
const arr = [1, 2, 3, 4, 5];
console.log(Math.max(...arr)); // 5
Lesson Learned
잘한 점
- 문제를 해결할 때까지 자리에서 일어나지 않고 집중했다는 점이 뿌듯했다. 푸는 데 시간이 오래 걸렸지만 포기하지 않았으니까!
아쉬운 점
- 문제를 많이 풀어보지 않았기 때문일까 문제에 어떻게 접근해야 할지 아직 감이 안 잡힌다. 그래서 시간이 오래 걸리는 것 같다.
- 같은 범위에서 반복을 하는 for문이 2개 있어서 그것을 하나로 줄이려고 했는데 의도대로 작동하지 않았었다. 멘토님의 도움을 받아 해결했는데 연산자의 우선순위 때문이었다. 하나하나 꼼꼼하게 보는 습관을 길러야겠다고 느꼈다.
배운 점
- 문제를 풀 때는 먼저 문제를 읽고 이해한 후 노트에 과정을 적어보자. 과정을 적고 코드에 그 과정을 주석으로 치면서 순서대로 코드를 작성하면 풀 수 있다!
'Modern Agile > TIL' 카테고리의 다른 글
Day 07 - 2021.12.14 (0) | 2021.12.15 |
---|---|
Day 06 - 2021.12.13 (0) | 2021.12.13 |
Day 04 Tech Talk Day🎤 - 2021.12.09 (2) | 2021.12.09 |
Day 03 - 2021.12.08 (0) | 2021.12.08 |
Day 02 - 2021.12.07 (0) | 2021.12.07 |