Level
프로그래머스 Lv2
Recruitment
KAKAO Blind
// ' '는 0이 됨. isNaN으로 체크 불가 >> charCodeAt을 사용.
// js sort는 unstable sort임 따라서, 비교 값이 같을 경우 index를 따져줘야함.
// sort문에서, str과 num을 구해놓고 비교 >> 문자가 다를 경우 곧바로 return하면 되는데, 이렇게 구할 피룡가 없음.
// 풀리긴 했지만 비효율적이라 생각

// 시간 복잡도 : O(n[map] * nlogn[sort] * (str.length+str.length+5)*n[map]) = O(n^3logn*`str.length`)
function solution(files) {
  const getStringNumber = (str) => {
    let string = ""; // 처음 등장하는 문자열
    let number = ""; // 처음 등장하는 숫자열
    let foundString = false;

    for (let i = 0; i < str.length; i++) {
      let strCode = str[i].charCodeAt();
      if (strCode > 57 || strCode < 48) {
        // 문자일 떄
        if (foundString) break;
        string += str[i];
      } else {
        // 숫자일 떄
        foundString = true; // 숫자 이후의 문자 순회를 방지
        number += str[i];
      }
    }
    return [string.toUpperCase(), +number];
  };

  return files
    .map((item, i) => ({ item, i }))
    .sort((a, b) => {
      const [strA, numA] = getStringNumber(a.item);
      const [strB, numB] = getStringNumber(b.item);
      // getStringNumber의 비용이 클 거라 생각

      if (strA > strB) return 1;
      if (strA < strB) return -1;
      if (numA > numB) return 1;
      if (numA < numB) return -1;
      if (numA === numB) return a.i - b.i;
    })
    .map((obj) => obj.item);
}

/*

설명 : files의 각 아이템에 대해 첫 문자열과, 첫 숫자열을 찾아 대소비교.
stable한 sort를 위해 file의 item과 index를 객체에 저장하고, sort문에서 item이 동일할 경우 index 비교를 통해 stable을 보장함.

*/

// const alphabet = (str) => 1 or numberIndex;
// const number = (index, str) => 1

// sort문을 바로 실행해, 순차적으로 따져보려 시도해봄.
// +'  ' = 0, stability를 고려해서 다시 풀어봐야할 풀이
function solution(files) {
  return files.sort((a, b) => {
    for (let i = 0; i < a.length; i++) {
      if (isNaN(+a[i])) {
        // 문자일 경우
        if (a[i].toLowerCase() !== b[i].toLowerCase())
          return a[i] > (b[i] || -Infinity); // b가 undefined일 경우, swap
      } else {
        if (isNaN(b[i])) return -1; // a의 str 부분이 모두 일치하고 b가 더 긴 str일 경우
        // a,b 앞문자열 길이가 같을 경우,
        let numA = "";
        let numB = "";

        for (let j = i; j < Math.max(a.length, b.length); j++) {
          if (+a[i] < 10) {
            numA += a[i];
          }

          if (+b[i] < 10) {
            numB += b[i];
            continue;
          }

          if (isNaN(a[i]) && isNaN(+b[i])) return; // a[i], b[i] 모두 숫자가 아닐 떄 for문 종료
        }

        return +numA > +numB;
      }
    }
  });
}