프로그래머스 알고리즘 풀었던 문제들 복습하기 (1레벨)

REASON·2022년 9월 16일
0

복습

목록 보기
10/12

풀었던 문제를 다시 풀면서 다른 방법으로 풀어보거나 풀었던 문제임에도 막힐 경우 메모해놓고 기억하고자 한다.

자릿수 더하기

이전에 풀었던 코드를 보니 String 타입으로 변경해서 split으로 자른 후 forEach로 반복문을 돌려서 누적 합을 리턴하는 방식으로 풀었었다.
이번에도 문제를 처음 보자마자 split..!이 떠올랐지만 다른 방법으로 풀어볼 수 있을 것 같다는 생각이 문득 떠올랐다. 10으로 나눈 나머지와 몫을 이용하면 되겠다 싶어서 시도했다.

function solution(n)
{
    let result = 0;

    while(n > 0){
        result += n % 10;
        n = Math.floor(n / 10);
    }
    
    return result;
}

자바스크립트에서 몫 연산을 할 때 소수점이 나오는 것을 간과한 탓에 처음에 소수점 자리가 나오는 것을 보고 어???? 왜 틀리지??? 하고 당황했었다. ㅋㅋㅋ

이번 재풀이를 통해 정수형으로 변환해서 사용하거나 소수점 자리를 버리는 방법으로 코드를 풀어야 하는 것을 알게 되었다.

평균 구하기

이전에도 reduce를 사용해서 풀었었고 이번에 풀 때도 가장 먼저 누산..! 하면 reduce 부터 떠올라서 reduce를 사용해서 풀었다.
다만, 이번엔 다른 점은 예전에 무슨 문제 풀 때였는지 기억은 잘 안나지만 reduce의 초기값을 설정하지 않아서 테스트 케이스가 실패했었던 기억이 떠올라서 이번에는 initialValue 값도 지정해서 사용해봤다. (그때는 결국 reduce 대신 다른 것으로 풀었었던 것 같다.)

빈 배열에서 초기값을 설정하지 않은 상태에서 reduce 를 호출하면 오류가 발생할 수 있다.

라는 MDN 공식 문서 글을 읽고 reduce에 대해 조금 더 알게 되었다.

function solution(arr) {
    var answer = 0;
    
    answer = arr.reduce((pre, cur)=> pre + cur, 0) / arr.length;
    
    return answer;
}

사실 이 문제 풀이에서는 initialValue 를 적어주지 않아도 정답처리가 되기 때문에 상관은 없다.

자연수 뒤집어 배열로 만들기

이 문제는 정확히 2주 전에 풀었던 문제였다.
이번에도 풀이 자체는 거의 동일한데 달라진 점이 있다면 체이닝 사용하는 부분에서 차이가 있었다.

function solution(n) {
    return String(n).split('').map(Number).reverse();
}

분명 2주 전엔 이 리턴값이 맞을까 확신을 못해서 체이닝을 함부로 못쓰는 쫄보였었는데 ㅠㅠㅠ

이건 전에 풀었던 코드 ㅋㅋ

answer = String(n).split('').reverse();
answer = answer.map((v) => {
  return Number(v);
});

짧은 코드가 좋은 것은 아니지만 코테에서 시간 단축하기엔 짧게 쓸 수 있을 수록 좋은듯 하다.

문자열 내 p와 y의 개수

어? 정규식!!이 떠오르는 문제였지만 본인.. 정규식 쓸 줄 모름........ㄸㄹㄹ
이참에 정규식 간단하게라도 배워야겠다.

function solution(s){
    let cntP = 0;
    let cntY = 0;
    
    for(let ss of s.toUpperCase()){
        if( ss === 'P' ) cntP++;
        else if ( ss === 'Y' ) cntY++;
    }

    if(cntP === cntY) return true;
    else return false;
}

이번엔 그냥 전부 대문자로 바꿔버리고 반복문을 돌려서 카운트를 세주었다.
신기하게도 8일 전에 푼 코드랑 변수명이 똑같다. ㅋㅋ 과거의 나나 지금의 나나 변수명 짓는 건 여전하네.........

처음 푼 코드

function solution(s) {
  var answer = true;
  let cntP = 0;
  let cntY = 0;

  for (let str of s) {
    if (['Y', 'y'].includes(str)) cntY++;
    else if (['P', 'p'].includes(str)) cntP++;
  }

  if (cntP == cntY) answer = true;
  else if (cntP === 0 && cntY === 0) answer = true; // 아니 이 코드는 왜 또 썼음 ㅋㅋ
  else answer = false;

  return answer;
}

지난 번에는 includes를 사용했었다. 근데 좀 이상한 코드가 보인다.
왜 if문이랑 else if 문에 어차피 동일한 코드를 써놨지.....?
엣지 케이스라는 것에 대해 무지했을 때라 엣지 케이스같은 건 모를테고.. 엣지 케이스를 고려했다 해도 저런 중복코드를 썼다는 건.. 고려한게 아닌게 되는데..

저런 쓸데없는 코드를 왜 한줄 더 써놨는지 지금도 모르겠다. 깔깔..

8일 전의 내 코드보다 지금의 내 코드가 조금 더 나아 보이는 것 같아서 조금 다행인 것도 있다.
예나 지금이나 똑같으면 그건 그거대로 슬플 것 같아서...... 😭

다음 번엔 정규식 배워서 다시 재도전 해보고 싶은 문제이다. ㅎㅎ

하샤드 수

이번에 푼 코드는 삼항연산자를 사용해서 리턴 값을 만들어 보았다.
삼항 연산자에 대한 막연한 두려움으로 자주 사용은 못하고 항상 if else문을 사용하고는 했었는데 이번에 삼항 연산자를 써서 리턴 값을 만들어봐야겠다는 생각에 시도해보았다.

작성 코드

function solution(x) {
    let result = String(x).split('').map(Number).reduce((c, p) => c + p, 0);
    return x % result === 0 ? true : false;
}

▼ 첫 시도에 작성한 코드

function solution(x) {
  var answer = true;

  const num = String(x).split('');
  let result = num.reduce((pre, curr) => {
    return Number(pre) + Number(curr);
  });

  if (x % result != 0) answer = false;

  return answer;
}

이 코드는 약 2주 전에 작성한 코드인데 역시나 if문을 사용했던 나를 발견할 수 있었다. ㅎㅎ

나머지가 1이 되는 수 찾기

예전에 풀었을 때는 잘 풀어놓고 이번에는 제한사항 부분에 최소값이 3인 것을 보고 반복문을 3부터 시작하게 하는 바람에 2번 제출해서 맞췄다.ㅋㅋ 테케 2개가 틀리길래 어? 했는데 제한 사항이 n의 범위였고.. x의 범위가 아니라.....

지문을 꼼꼼하게 읽자. 빨리 풀기 전에 지문! 제대로! 읽기! 를 다시 한번 실천해야 겠다고 느끼게 만들어준 문제였다.

function solution(n) {
    for(let i = 1; i <= n; i++){
        if(n % i === 1) return i
    }
}

지난 번과 풀이 코드는 크게 다르지 않으므로 다음 문제~!

x만큼 간격이 있는 n개의 숫자

이 문제는 지난번 풀이 코드가 음? 하고 바로 안 읽혀져서 뭘 어떻게 통과한거지 하고 다시 살펴보게 만들었다.

function solution(x, n) {
    const list = [];
    
    for(let i = 1; i <= n; i++){
        list.push(x * i);
    }
    
    return list;
}

일단 이건 이번에 푼 것..

지난 번 풀이 코드

function solution(x, n) {
  var answer = [];
  answer.push(x);

  for (let i = 0; i < n - 1; i++) {
    answer.push(answer[i] + x);
  }

  return answer;
}

왜인지 모르겠지만 지금의 나는 예전의 내가 푼 코드를 보고 오..저렇게도 풀 수 있구나 를 느끼는 건 왜인가..
분명 내가 푼 거 맞는데 낯설다.. 😶

핸드폰 번호 가리기

이 문제는 초반에 살짝 헷갈렸던 부분이 폰넘버의 길이가 4일 때 숫자를 다 보여주나? 해서 제출하기 전에 계속 고민하다가 4자리를 제외한 나머지 숫자라고 했으니 숫자를 보여주는 게 맞나보넹ㅎㅎ 했던 문제이다.

repeat 함수가 왜 그땐 생각이 안났는지 ㅋㅋ
이번에는 repeat을 사용해서 풀어보았다.

풀이 코드 !

function solution(phone_number) {
    return '*'.repeat((phone_number.length - 4)) + phone_number.slice(-4);
}

지난번 풀이

function solution(phone_number) {
  var answer = '';

  for (let i = 0; i < phone_number.length - 4; i++) {
    answer += '*';
  }

  answer += phone_number.slice(phone_number.length - 4, phone_number.length);

  return answer;
}

제일 작은 수 제거하기

빈배열을 확인하는 방법이 없을까? 하고 한참 고민해봤던 것 같다. 단순히 비교 연산자나 일치 연산자를 사용해야하나? 또 다른 방법은 뭐가 있을까? 하고 MDN 문서도 뒤적거리고 (물론 다른 방향으로 세버렸지만ㅋㅋ) 구글링도 해봤는데 마땅히 방법이 없는 것 같아서 이번에도 지난 번 풀었던 것과 동일하게 일치 연산자를 사용했다.

풀이 코드

function solution(arr) {
    if(arr.length === 1) return [-1];
    
    let min = arr[0];
    if(arr.length){
        for(let i = 0; i < arr.length; i++){
            if(min > arr[i]) min = arr[i];
        }
        arr.splice(arr.indexOf(min), 1);
        return arr;
    }
}

지난번 풀이 코드

function solution(arr) {
  var answer;
  let min = arr[0];

  if (arr.length === 1) answer = [-1];
  else {
    arr.forEach((v) => {
      if (min > v) min = v;
    });
    answer = arr.filter((v) => v > min);
  }

  return answer;
}

저번에 푼 코드 보니까 filter를 사용해서 풀었었네 이 방법도 괜찮다! 하고 다시금 filter 메서드에 대해 인지하는 중.. 워낙 메서드가 많아서 생각나면 좋은데 생각 안날 때가 많다 ㅠㅠ

0개의 댓글