프로그래머스 알고리즘 문제 복습

REASON·2022년 9월 16일
0

복습

목록 보기
11/12

최댓값과 최솟값

프로그래머스 레벨2 문제 중 쉬운 난이도인 최댓값과 최솟값 문제 다시 풀었을 때 더 나은 풀이로 풀 수 있었다.

문제 푸는 도중 아까 MDN 뒤적거리다가 발견한 Array.of가 생각났다 ㅎㅎ

풀이 코드

function solution(s) {
  let numbers = s.split(' ').map(Number);
  return Array.of(Math.min(...numbers), Math.max(...numbers)).join(' ');
}

이전 풀이 코드

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

  let max = Number.MIN_SAFE_INTEGER;
  let min = Number.MAX_SAFE_INTEGER;

  s.split(' ')
    .sort((a, b) => a - b)
    .forEach((v) => {
      if (max < Math.abs(v)) max = v;
      if (min > Math.abs(v)) min = v;
    });

  if (max < 0 && Math.abs(max) > Math.abs(min)) [min, max] = [max, min];

  answer = `${min} ${max}`;

  return answer;
}

예전에는 엄청 길게 풀었었네... 그와중에 템플릿 리터럴을 이번 풀이에서는 생각을 못하고 있었다! join 해야지!만 생각하고 있었는데 ㅋㅋㅋ
아마 저 첫풀이 했을 때가 오늘로부터 8일 전인데 그때 Number.MIN_SAFE_INTEGER 이런거 어디서 주워들어와가지고 써본다고 했었던 기억이 어렴풋이 난다.

이번 풀이 코드에서 템플릿 리터럴 썼어도 됐을텐데 ㅠㅠ 배열 보자마자 머릿속에선 "join 써라" 가 지배했던 것 같다. ㅋㅋㅋ

아무튼 전에는 꽤 오래 고민했던 것 같은데 지금은 풀이 시간이 단축된 것이 체감된다. 정확히 재보진 않았지만..

가운데 글자 가져오기

가운데 문자를 가져오는 방법이 s의 length를 2로 나눈 몫을 가지고 연산하는 거 말고는 없을까..를 한참 고민했던 문제이다. 관련 메소드는 뭐가 있을까..도 고민해봤는데 마땅히 방법이 생각이 안나서 이전에 풀었던 방식과 비슷하게 가되, 이번에는 substring 이라는 string 메서드를 사용해보았다.

풀이 코드

function solution(s) {
  if (s.length % 2 === 0) {
    let idx = Math.floor(s.length / 2);
    return s.substring(idx - 1, idx + 1);
  } else {
    let idx = Math.floor(s.length / 2);
    return s[idx];
  }
}

s가 짝수 길이 일 때 가운데 두개의 문자를 반환해야하기 때문에 substring을 사용했다.
처음 사용해봤다..! sutstr 을 써도 가능했을텐데 MDN에서 substr은 바람직하지 않은 특징이 있다고 사용을 지양한다고 적혀있었다.

이전 풀이 코드

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

  if (s.length % 2 === 0) {
    answer += s[Math.floor(s.length / 2) - 1];
    answer += s[Math.floor(s.length / 2)];
  } else answer = s[Math.floor(s.length / 2)];

  return answer;
}

JadenCase 문자열 만들기

정답률 80%의 레벨 2문제.. 많이 어렵진 않을 것 같다고 생각하고 들어갔다가 공백지옥에 갇혔던 기억이 있다. ㅋㅋㅋ

풀이 코드

function solution(s) {
  let result = '';
  let rememberIdx;

  s.toLowerCase()
    .split('')
    .forEach((v, i) => {
      if (i === 0 || rememberIdx === i) result += v.toUpperCase();
      else result += v;
      if (v === ' ') {
        rememberIdx = i + 1;
      }
    });

  return result;
}

이번에도 공백 처리를 어떻게 해야하나 고민하다가 아싸리 공백을 만났을 때 다음 index를 저장해놓고 그 인덱스를 만났을 때 대문자로 바꾸는 방식을 선택했다.
이렇게 하니 공백처리에는 신경을 전혀 쓰지 않아도 돼서 머리를 싸매지 않아도 된다는 장점이 있었다.
처음에는 배열에 인덱스를 push 해놨다가 나중에 바꿀까 했는데 오히려 이게 더 복잡한 것 같아서 생각해낸 방법이었다. ㅎㅎ

지난번 풀이 코드

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

  s.toLowerCase()
    .split(' ')
    .forEach((v, i) => {
      if (v === '') {
        answer += ' ';
        answer += v.slice(1);
      } else {
        answer += v[0].toUpperCase();
        answer += v.slice(1);
        answer += ' ';
      }
    });

  answer = answer.trimEnd();
  if (s[s.length - 1] === ' ') answer += ' ';

  return answer;
}

문자열 내림차순으로 정렬하기

이 문제를 처음 풀 때 대문자는 소문자보다 작은 것으로 간주한다기에 아스키코드로 풀어야겠다고 떠올렸었다.
그래서 덕분에 여러번의 반복문을 사용했었던 기억이 있다..ㅋㅋㅋ sort함수를 제대로 사용할 줄 몰랐어서 sort 함수로 풀어야지! 라는 생각은 아예 못했었다.
당시엔 "아스키코드" 에 꽂혀서 charCodeAt이랑 fromCharCode를 사용해서 풀었기 때문이다.

얼마 전에 sort 관련 문제가 있어서 그거 풀면서 sort 함수를 조금 더 알게된 계기가 있었는데 그래서인지 이번에는 sort를 사용해서 풀 수 있었다!

풀이 코드

function solution(s) {
  return s
    .split('')
    .sort((a, b) => {
      if (a > b) return -1;
      else if (a < b) return 1;
      else return 0;
    })
    .join('');
}

지난번 풀이 코드

function solution(s) {
  var answer = '';
  const arr = [];
  const arr2 = [];

  for (let c of s) {
    arr.push(c.charCodeAt());
  }

  arr.sort((a, b) => b - a);

  for (let a of arr) {
    arr2.push(String.fromCharCode(a));
  }

  answer = arr2.join('');

  return answer;
}

문자열 다루기 기본

이 문제는 전에도 당해놓고 또 당했다.. ㅋㅋㅋ
테케 11이 자꾸 실패하길래 뭐지 하고 제한 사항을 다시 꼼꼼히 읽어보는데 아 맞다 'e' !!!!

풀이 코드

function solution(s) {
  if ([...s].includes('e')) return false;
  if (Number.isNaN(Number(s))) return false;
  if (s.length === 4 || s.length === 6) return true;

  return false;
}

아무튼 다시금 상기하게 되는 'e' ..
처음 풀었을 때는 아무리 생각해도 모르겠어서 구글링해서 풀었었는데 이번에는 그래도 정말 한참 뒤에 생각은 나서 다행(?)이라고 생각한다.
같은 거로 또 구글링했으면 자괴감 들었을 것 같음.
그때도 당해놓고 또 당하냐! 이런 느낌

지난번 풀이 코드

function solution(s) {
  var answer = false;

  let tf = Number.isNaN(Number(s));

  for (let i = 0; i < s.length; i++) {
    if (s[i] === 'e') return false;
  }

  if (tf) {
    answer = false;
  } else if (s.length == 4 || s.length == 6) {
    answer = true;
  }

  return answer;
}

코드는 첫 풀이때보다는 간결해진 느낌이 듭니다.

이진 변환 반복하기

이번에는 replace 써보고 싶어서 간단한 정규표현식을 사용해보았다.
드디어 처음 써보는 정규 표현식이다..!

지난 번 첫 풀이와 다른 점이라하면 이번에는 루프 안에 어떤 것들이 반복 되는지 생각을 해보고 코드를 작성했다는 점이다.

이 문제는 0 카운트하고, 0 없애고, 현재 길이만큼 2진변환하고 를 반복적으로 수행하고 있기 때문에 while문 안에 해당 코드를 작성해주면 된다.

풀이 코드

function solution(s) {
  let cnt = 0;
  let eraseCnt = 0;

  // 
  while (s != 1) {
    for (let i = 0; i < s.length; i++) {
      if (s[i] == 0) eraseCnt++;
    }
    s = s.replace(/0/g, '');
    s = s.length.toString(2);
    cnt += 1;
  }

  return [cnt, eraseCnt];
}

되게 별거 아닌데도 정규표현식 처음 써봐서 그런가 너무 뿌듯.. 정규 표현식 잘 쓰시는 분들 보면 와.. 저 외계어를 어떻게 구사하시지.. 싶다.
제2언어가 외계어인가 싶기도 하고...

지난번 풀이 코드

function solution(s) {
  var answer = [];
  let n = s;
  let count = 0; // 제거한 0 카운트
  let r = 0; // 루프 횟수

  while (n != '1') {
    n = n
      .split('')
      .filter((v) => {
        if (v === '0') count++;
        return v !== '0';
      })
      .join('');

    n = n.length.toString(2);
    r++;
  }

  answer.push(r);
  answer.push(count);

  return answer;
}

확실히 지난 번이랑 비교해봐도 간결해진 코드! 정규표현식 잘 쓰고 싶당!

최솟값 구하기

프로그래머스 레벨 2 문제인데 쉬운 난이도이다.
그럼에도 나는 바보인가....ㅜㅜㅜ 전에 잘 풀어놓고 이번에 완전 헤매고 헤매다가 너무 안돼서 다른 방법이 뭐가 있을까...하고 어? 어차피 최소 * 최대 구하는 거니까 sort 해서 하면 되는거 아닌가? 를 뒤늦게 알아챘다. ㅋㅋㅋ
계속 splice로 풀려고 했더니 산으로 갔다. 그렇게 어려운 문제도 아니었는데 ㅠㅠ
풀이는 결국 첫번째 풀이랑 똑같이 풀어졌더라.
그나마 2번째 풀이떄는 구글링을 안하고 스스로 삽질하다가 알아챘다는 것..

풀이 코드

function solution(A,B){
    let result = 0;

    A.sort((a, b) => a - b);
    B.sort((a, b) => b - a);
    A.forEach((v, i)=>{
        result+= v * B[i];
    })
    return result;
}

0개의 댓글