본문 바로가기
JS/백준

[백준/JS] 20920. 영단어 암기는 괴로워

by GiraffePark 2023. 12. 2.

안녕하세요. 박기린 입니다.

백준 20920번 영단어 암기는 괴로워 문제를 풀어보겠습니다.

 


문제 링크

https://www.acmicpc.net/problem/20920

 

20920번: 영단어 암기는 괴로워

첫째 줄에는 영어 지문에 나오는 단어의 개수 $N$과 외울 단어의 길이 기준이 되는 $M$이 공백으로 구분되어 주어진다. ($1 \leq N \leq 100\,000$, $1 \leq M \leq 10$) 둘째 줄부터 $N+1$번째 줄까지 외울 단

www.acmicpc.net

 

 

 

 


문제 해석

주어진 단어들의 출현 빈도수를 체크합니다.

 

 

 

 

만약 단어의 길이가 M보다 짧을 경우, 지워버립니다.

예제에서는 M이 4였기 때문에, 글자수가 3개인 ant는 제외됩니다.

 

 

 

 

 

 

출현 빈도수가 높은 순서대로 정렬을 합니다.

 

 

 

 

 

출현 빈도수가 같을 경우, 글자수가 더 많은 단어를 앞에 세웁니다.

예를 들어, father과 apple이 각각 동일한 빈도수로 등장했을 경우, father의 글자수가 6개로 더 크기 때문에 father을 앞에 둡니다.

 

 

 

 

 

출현 빈도수와 글자수 모두 동일하다면, 사전 순서로 줄을 세웁니다.

예를 들어, append와 father이 출현 빈도수와 글자수 모두 동일한 상태로 등장했다면, append의 사전 순서가 더 빠르기 때문에 append를 앞에 둡니다.

 

 

 

 


정답 코드

const fs = require("fs");
const [NnM, ...words] = fs
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n");
const [n, m] = NnM.split(" ").map(Number);

const list = [];
const dict = {};

// 사전 순 정렬
const setOrder = (a, b, n) => {
  for (let i = 0; i < n; i++) {
    if (a[i] !== b[i]) {
      return a[i].charCodeAt() - b[i].charCodeAt();
    }
  }
};

words.forEach((e) => {
  if (e.length >= m) {
    if (dict[e]) {
      dict[e]++;
    } else {
      dict[e] = 1;
      list.push(e);
    }
  }
});

list.sort((a, b) => {
  // 빈도수
  if (dict[a] < dict[b]) return 1;
  
  else if (dict[a] === dict[b]) {
    // 빈도수가 같다면 길이를 비교
    if (a.length < b.length) return 1;
    
    else if (a.length === b.length) {
      // 길이까지 같다면 사전 순으로 나열
      return setOrder(a, b, a.length);
      
    } else return -1;
    
  } else return -1;
});


console.log(list.join("\n"));

 

 

 

 


정답 코드 풀이

const fs = require("fs");
const [NnM, ...words] = fs
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n");
const [n, m] = NnM.split(" ").map(Number);

 

fs모듈로 입력을 받습니다.

n과 m에 각각 N과 M 값을 저장하고, words 배열에 영단어를 전부 담습니다.

 

 

 

const list = [];
const dict = {};

list : 입력받은 영단어들이 저장될 배열입니다. 중복되는 값 없이, set처럼 영단어를 한 번씩만 저장합니다.

dict : 영단어의 출현 빈도수를 저장할 딕셔너리입니다.

 

 

 

 

// 사전 순 정렬
const setOrder = (a, b, n) => {
  for (let i = 0; i < n; i++) {
    if (a[i] !== b[i]) {
      return a[i].charCodeAt() - b[i].charCodeAt();
    }
  }
};

setOrder 함수는 두 단어의 사전 순 정렬을 도와주는 함수입니다.

 

a : 앞 단어

b : 뒤 단어

n : 단어의 길이

 

앞 단어(a)가 사전 순으로 뒤에 있을 경우 음수를, 아니면 양수를 return 합니다.

 

 

 

 

words.forEach((e) => {
  if (e.length >= m) {
    if (dict[e]) {
      dict[e]++;
    } else {
      dict[e] = 1;
      list.push(e);
    }
  }
});

입력 받언 영단어들이 저장된 words 배열을 forEach()로 접근합니다.

영단어의 길이가 m보다 클 경우에만 dict와 list에 담습니다.

 

만약 dict에 해당하는 영단어가 없을 경우, 

- dict에는 해당 영단어를 label로 한 후 1을 담아줍니다.

- list에 해당 영단어를 push합니다.

 

반대로 dict에 해당하는 영단어가 있을 경우, dict[영단어] 안에 담긴 숫자를 +1 해줍니다.

 

 

 

 

 

list.sort((a, b) => {
  // 빈도수
  if (dict[a] < dict[b]) return 1;
  
  else if (dict[a] === dict[b]) {
    // 빈도수가 같다면 길이를 비교
    if (a.length < b.length) return 1;
    
    
    else if (a.length === b.length) {
      // 길이까지 같다면 사전 순으로 나열
      return setOrder(a, b, a.length);
    
    } else return -1;
  
  } else return -1;
});

 

Array.prototype.sort()를 이용해서 list를 정렬합니다.

 

1. dict를 통해 영단어의 빈도수를 비교합니다.

2. 두 영단어의 길이를 비교합니다.

3. setOrder() 함수를 통해 사전 순서를 비교합니다.

 

 

 

 

console.log(list.join("\n"));

 

정렬된 list 배열을 join() 메소드를 이용해서 출력하면 끝입니다.

 

 

 

 

 

반응형

'JS > 백준' 카테고리의 다른 글

[백준/nodeJS] 28279. 덱 2  (0) 2023.12.21
[백준/JS] 12789. 도키도키 간식드리미  (1) 2023.12.07
[백준/JS] 2738. 행렬 덧셈  (0) 2023.11.23
[백준JS] 16139. 인간-컴퓨터 상호작용  (0) 2023.06.26
[백준JS] 1037. 약수  (0) 2023.04.25