알고리즘 - [백준] 1181번 단어 정렬

Seong Hyeon Kim·2022년 9월 2일
0

알고리즘

목록 보기
16/20

문제


풀이과정

// 단어 정렬
const fs = require("fs");
    const input = fs
    .readFileSync(process.platform === "linux" ? "/dev/stdin" : "input.txt")
    .toString()
    .trim()
    .split("\n")
    .map((e) => e.replaceAll('\r', '')); /// \r 지운는법
   
    input.shift()

    let result = []
 
    let inputArr = [...new Set(input)]		///중복제거
    // console.log(inputArr)
    
    let sortInput = inputArr.sort((a,b)=>{		///내림차순 정렬
        return a.length - b.length
    })
    // console.log(sortInput)

우선 내 스스로 푼 곳은 여기까지이다.
new Set() 함수로 우선 중복값을 미리 제거한 후
그다음 sort() 함수를 사용해서 정렬을 했다.

저기까지만 했을때 sortInput 의 콘솔 값을 찍어보면 다음과 같이 나온다

  'i\r',        'no\r',
  'it\r',       'im\r',
  'but\r',      'wont\r',
  'more\r',     'wait\r',
  'yours',      'cannot\r',
  'hesitate\r'

여기서부터는 여러가지 이유로 멘붕이였는데 순서대로 말하자면

  1. 우선 sort()를 사용했는데도 어째서 저런 형태일까 하는 의문과
  2. \r 을 지우는 방법을 몰라서 열심히 구글링 했지만 기본적으로 \r을 지우는 방법 같은건 나와있지 않았다.

다행히 1번은 알파벳 혹은 사전순서대로 정렬하는 법으로 구글링을 해보니 답을 찾을순 있었는데,
여전히 코드를 작성하기에는 좀 힘들었다.

2번 항목은 스터디 진행하면서 같은 팀원이 \r 을 replaceAll() 함수로 지울수 있다는 것을 듣고 이 부분은 나중에 진행하였다.

.map((e) => e.replaceAll('\r', ''));

이걸 처음부분에 추가해 놓으면 된다.



이후 꽤 오랫동안 여러가지 방법들을 찾아보긴 했지만 원하는 답을 찾지 못해서 결국
관련 reference 들을 찾다가 참고하기 좋은 코드를 찾았다.

https://wonyoung2257.tistory.com/46


    for(let i =1; i<=sortInput[sortInput.length-1].length; i++){
        let temp = sortInput.filter((el)=>el.length === i);
        // console.log(temp)
        result.push(...temp.sort());
    }
    // console.log(result)

위 reference 의 이부분을 참고했으며 코드를 부분부분 해석하자면 이렇다

우선 내가 잘 모르는 filter() 를 사용해서 그것에 관해 찾아보았다.

간단히 설명하자자면 주어진 조건을 통과하는 요소들을 새롭게 만들어줘서 배열로 만들어주는
내입장에서 편하게 생각하자면 빠르게 돌리는 조건문 + 결과값을 배열로까지 만들어주는

꽤나 혜자스러운 메서드 였다.

temp 라는 함수의 콘솔을 찍어보면

[]
[ 'i\r' ]
[ 'no\r', 'it\r', 'im\r' ]
[ 'but\r' ]
[ 'wont\r', 'more\r', 'wait\r', 'yours' ]
[]
[ 'cannot\r' ]
[]
[ 'hesitate\r' ]

다음과 같은 콘솔값이 나온다.
즉 filter 를 사용해서 반복문 i의 값과 길이가 같은 것들을 묶어놔서 새롭게 배열을 만들어준 값을 반환한다.

이 새롭게 만들어준 배열을 result.push(...temp.sort()); 를 통해서
미리 만들어준 result 라는 빈배열에 push 를 해줌으로써

[
  'i\r',        'im\r',
  'it\r',       'no\r',
  'but\r',      'more\r',
  'wait\r',     'wont\r',
  'yours',      'cannot\r',
  'hesitate\r'
]

라는 내가 원하는 값이 담긴 배열이 나오게 된다.



아 그리고 여기서 사용된 ... 은

확장연산자(스프레드 문법) 이라고 하는데
https://justmakeyourself.tistory.com/entry/javascript-spread-operator

해당 래퍼런스를 참고하였으며

다음과 같은 설명이 있지만 오늘 문제를 예시로 간단히 설명하자면
...temp 라고 하면 그냥 쉽게 생각해서 temp 라는 변수명에 담긴 배열값을 전부 들고온다 라고 이해하면 편할것 같다.

하지만 문제에서 요구하는 출력값은 배열이 아니여서 이 값을 배열에서 빼내야 하는데

    for (let word of result) { // 정답 출력
        // console.log(word);
      }

이 부분 덕분에 result 라는 배열에서 word 즉 단어만 빼내서 콘솔로 보여주는 반복문을 만들면
다음과 같은 원하는 결과값이 나온다.

i
im
it
no
but
more
wait
wont
yours
cannot
hesitate

다른 풀이

이 코드의 내용을 자세히보면 11번째 줄에
localCompare 라는 함수를 사용한게 있는데
이 함수가 대소문자 구분없이 알파벳 순서대로 정렬 이라는
아주아주 편한 함수이다.

아마 이걸 사용했으면 내 코드도 더 줄일 수 있었을 것 같다.

그리고 이 코드중 sort() 안에 || 를 사용한 부분이 있는데

mdn 을 참고하던중 이런 부분이 있는걸 보고 이렇게도 쓸수 있구나 라고 참고했다고 한다.

저렇게 코드를 짜게 되면 내림차순으로 정렬 후 알파벳 순서대로 정렬 이라는 순차적인 처리가 가능해진다.

그래서 이것을 토대로 나의 10줄 짜리 코드를

3줄컷이 가능하다는 것을 알게 되었다... ㄷㄷㄷㄷ

새로 알게된 것들

  • .map((e) => e.replaceAll('\r', '')); ==> 이걸 사용하면 \r 을 지울 수 있다.

  • filter() 함수를 사용하면 주어진 조건을 통과하는 요소들을 새롭게 만들어줘서 배열로 만들어준다.

  • ...arr 은 확산연산자로서 스프레드문법이며 간단하게 말해서 arr이라는 변수 값을 전부 불러온다 라고 생각하면 지금단계에서 사용하는 것에서는 편할 것 같다.

  • for of word 문을 사용하면 해당 배열의 모든 단어? 들을 가져올 수 있다.

  • sort() 문 내부에서 || (or연산자) 를 사용할 수 있다. 위 코드를 예시로 들자면 내림차순으로 정렬 후 알파벳 순서대로 정렬 이라는 순차적인 처리가 가능해진다.

  • 역시 매서드는 많이 알아두면 편할 것 같고 코드를 짤 때 시간소모를 줄일 수 있고 다채로운 코드를 작성할 수 있을 것 같다.

profile
삽질도 100번 하면 요령이 생긴다. 부족한 건 경험으로 채우는 백엔드 개발자

0개의 댓글