안녕하세요

[node.js] 문자열 단계 (자바스크립트) 11654 ~ 본문

백준 자바스크립트

[node.js] 문자열 단계 (자바스크립트) 11654 ~

sakuraop 2022. 5. 10. 22:20

"클론코딩을 하면서 부족한 자바스크립트 문법은 백준을 통해서 공부합시다.

초보입니다. 코드 설명은 "참고만" 해주세요.

https://www.acmicpc.net/step/7

 

문자열 단계

정수를 문자열로 입력받는 문제. Python처럼 정수 크기에 제한이 없다면 상관 없으나, 예제 3은 일반적인 정수 자료형에 담기에 너무 크다는 점에 주목합시다.

www.acmicpc.net


11654 아스키 코드

아래와 같이 알파벳 소문자, 대문자, 숫자 0-9중 하나가 주어졌을 때, 주어진 글자의 아스키 코드값을 출력하는 프로그램을 작성하시오.

A

결과

65

제출한 답

const inputNumber = require("fs").readFileSync("dev/stdin").toString();

console.log(inputNumber.charCodeAt(0));

코드 설명

  • String.charCodeAt(index) : charCodeAt() 함수는 문자열을 아스키코드 값으로 변환해줍니다.

+ console.log(String.fromCharCode(inputNumber));
fromCharCode(65, 66, 67) 는 아스키코드를 문자열로 반환해줍니다. (a, b, c)


11720 숫자의 합

아래와 같이 알파벳 소문자, 대문자, 숫자 0-9중 하나가 주어졌을 때, 주어진 글자의 아스키 코드값을 출력하는 프로그램을 작성하시오.

A

결과

65

제출한 답

const inputData = require("fs").readFileSync("dev/stdin").toString().split("\n");

let number = inputData[1].split("");
let sum = 0;

for (i = 0; i < inputData[0]; i++) {
  sum += Number(number[i]);
}
console.log(sum);

코드 설명

  • 문자열을 split("") 함수로 나눈 뒤 for 문을 이용해 sum에 더합니다.

10809 알파벳 찾기

아래와 같이 알파벳 소문자로만 이루어진 단어 S가 주어진다. 각각의 알파벳에 대해서, 단어에 포함되어 있는 경우에는 처음 등장하는 위치를, 포함되어 있지 않은 경우에는 -1을 출력하는 프로그램을 작성하시오.

baekjoon

결과

1 0 -1 -1 2 -1 -1 -1 -1 4 3 -1 -1 7 5 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1

제출한 답 3 - indexOf()

const inputData = require("fs").readFileSync("dev/stdin").toString().split("");

let result = "";

for (i = 97; i < 123; i++) {
  // 97~122 : a to z
  result += inputData.indexOf(String.fromCharCode(i)) + " ";
}

console.log(result);

 

  • indexOf()
    아스키코드로 변환하여 해당하는 숫자를 비교합니다. indexOf() 함수는 찾는 문자가 존재하지 않는다면 -1을 반환합니다. 

 

제출한 답 2 - 틀렸습니다 Set() 함수로 중복되는 문자열 제거 - 문자열의 길이가 달라집니다.

let inputData = new Set(require("fs").readFileSync("dev/stdin").toString().split(""));

inputData = [...inputData];
const string = inputData.join("");

let result = "";

for (i = 97; i < 123; i++) {
  // 97~122 : a to z
  let count = "-1";
  for (j = 0; j < string.length; j++) {
    if (string.charCodeAt(j) == i) {
      count = String(j);
    }
  }
  result += count + " ";
}

console.log(result);

 

제출한 답 1 (최초) - 맞았습니다!! 하지만, 중복되는 문자열("oo")이 연속되어 나타나는 경우에만

const inputData = require("fs").readFileSync("dev/stdin").toString();

let result = "";

for (i = 97; i < 123; i++) { // 97~122 : a to z
  let count = "-1";
  for (j = 0; j < inputData.length; j++) {
    if (inputData.charCodeAt(j) == i) {
      count = String(j);
      break;
    }
  }
  result += count + " ";
}

console.log(result);

코드 설명

  • // 97~122 : a to z : 알파벳 소문자 a to z 는 아스키 코드로 97~122 입니다.

  • for (j = 0; j < inputData.length; j++) {
        if (inputData.charCodeAt(j) == i) {
          count = String(j);
    각각의 문자열(b, a, e, k, j, o, o, n)과 비교해
    현재(j -> b, a, e, k, j, o, o, n) 문자열이
     존재한다면 "j" + " " 를 result 에 추가합니다.

  • let count = "-1";
    그 외에는"-1"을 result 에 추가합니다.

  • break; : break로 for 반복문(j) 을 종료합니다. 문제는 반복되는 문자열이 연속되지 않으면 결과가 다릅니다. 

2675 문자열 반복

아래와 같이 첫째 줄에 테스트 케이스의 개수 T, 반복수 R, 문자열 S를 입력받습니다.

2
3 ABC
5 /HTP

각 문자를 R번 반복해 새 문자열 P를 만든 후 출력하는 프로그램을 작성하시오.

 

AAABBBCCC
/////HHHHHTTTTTPPPPP

제출한 답 - repeat(count) : String을 count만큼 반복합니다. (최대 문자열의 크기를 넘어서면 안됩니다.)

const inputData = require("fs").readFileSync("dev/stdin").toString().split("\n");

for (i = 1; i <= inputData[0]; i++) {
  let result = "";
  let testCase = inputData[i];
  const repeatCount = testCase[0];

  for (j = 2; j < testCase.length; j++) {
    result += testCase[j].repeat(repeatCount);
  }
  console.log(result);
}

코드 설명

  • (j = 2; j < testCase.length; j++)
    "3 ABC" 와 같은 형태로 입력받기 때문에 j=2로 세번째 인덱스(A)부터 문자열의 끝(C)까지 반복합니다.

  •  result += testCase[j].repeat(repeatCount);
    testCase의 각 문자열을 반복 수(repeatCount) 만큼 repeat() 합니다.

1157 단어 공부

아래와 같이 알파벳을 입력받고 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. (단, 대문자와 소문자를 구분하지 않습니다.)

Mississipi
zZa

가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력합니다.

?
Z

제출한 답 - String.toUpperCase(), toLowerCase() 문자열 대/소문자로 변환하기

const word = require("fs").readFileSync("dev/stdin").toString().trim().toUpperCase().split("").sort();

let count = 1;
let maxCount = 0;
let alphabet = "";

for (i = 0; i < word.length; i++) {
  if (word[i] == word[i + 1]) {
    count += 1;
  } else if (word[i] != word[i + 1]) {
    count = 1;
  }

  if (maxCount < count) {
    maxCount = count;
    alphabet = word[i];
  } else if (maxCount == count) {
    alphabet = "?";
  }
}

console.log(alphabet);

코드 설명 - 문자열을 정렬한 후 연속되는 문자열 찾기

  • .sort();
    우선 입력받은 문자열을 리스트로 정렬합니다.
    baaa -> [ 'A', 'A', 'A', 'B' ]
  •  if (word[i] == word[i + 1]) {
        count += 1;
      }
    현재 문자열이 다음 문자열과 같다면(연속된다면) count 를 +1 합니다.

  • else if (word[i] != word[i + 1]) {
        count = 1;
      }
    그렇지 않다면 count를 1로 초기화 합니다.

  • if (maxCount < count) {
        maxCount = count;
    최대로 연속된 문자를 찾기 위해 maxCount 값이 count 값보다 작다면 -> count 값이 됩니다. 

    alphabet = word[i];
    maxCount 값이 갱신될 때 해당하는 현재 문자열(alphabet = word[i];) 을 출력할 것입니다.

  •  else if (maxCount == count) {
        alphabet = "?";
      }
    만일 maxCount 와 동일한 count 값이 나타나고 반복문이 끝난다면 ?(alphabet = "?";) 를 출력할 것입니다.

1152 단어의 개수

아래와 같이 영어 대소문자와 공백으로 이루어진 문자열이 주어집니다.  이 문자열에는 몇 개의 단어가 있는지 출력하시오.

The Curious Case of Benjamin Button

결과

6

제출한 답

const input = require("fs").readFileSync("dev/stdin").toString().trim().split(" ");

if (input == "") {
    console.log(0)
} else {
    console.log(input.length);
}

코드 설명

  • 아무런 문자열도 주어지지 않는 경우에는 0을 출력하도록 합니다.

2908 상수

아래와 같이  734와 893을 입력받는다면 437과 398로 변환한 뒤 비교하여 큰 수를 출력하시오. 수는 세자리 수이며 0이 포함되지 않습니다.

 

734 893

결과

437

제출한 답

let inputData = require("fs").readFileSync("dev/stdin").toString().split("").reverse().join("").split(" ").map(Number);

console.log(Math.max(...inputData));

 

코드 설명 

  • .split("") : 입력받은 문자열("734 893")을 리스트로 만듭니다. ['7', '3', '4', ' ', '8', '9', '3']
  • .reverse() : 리스트를 뒤집습니다. ['3', '9', '8', ' ', '4', '3',  '7']
  • .join("") : 리스트를 하나의 문자열로 합칩니다 ("398 437")
  • .split(" ") : " "을 기준으로 나누어 리스트로 만듭니다. ( ['397', '437'] )
  • .map(number) : 각 요소를 숫자로 변환합니다.
  • console.log(Math.max(...inputData)); : 가장 큰 수를 출력합니다. Math.max(397, 437)

5622 다이얼

숫자 1을 걸려면 총 2초가 필요하고, 한 칸 옆에 있는 숫자를 걸기 위해선 1초씩 더 걸립니다. 어떤 단어를 걸 때, 각 알파벳에 해당하는 숫자를 걸면 됩니다. 전화를 걸기 위해서 필요한 최소 시간을 구하는 프로그램을 작성하시오.

WA

결과

13

제출한 답

삼항연산자도 연습합시다.

const inputData = require("fs").readFileSync("dev/stdin").toString().split("");

const dial = {
  2: "ABC",
  3: "DEF",
  4: "GHI",
  5: "JKL",
  6: "MNO",
  7: "PQRS",
  8: "TUV",
  9: "WXYZ",
};

let time = 0;

for (i = 0; i < inputData.length; i++) {
  for (j = 2; j < 10; j++) {
    dial[j].includes(inputData[i]) ? (time += j + 1) : (time = time);
  }
}

console.log(time);

코드 설명 

  • dial 딕셔너리에 각각의 다이얼 넘버에 해당하는 알파벳을 담습니다.
  • for 문을 통해서 입력된 문자(for(i))가 다이얼 넘버를 순회하며(for (j)) 해당 키 값에 포함되어 있는지(includes()) 확인합니다.
  • 해당 키 값에 포함되어 있다면 time에 해당 키(j)+1초를 한 뒤 결과값을 출력합니다.

2941 크로아티아 알파벳

č c=
ć c-
dz=
đ d-
lj lj
nj nj
š s=
ž z=

아래와 같이 단어가 주어졌을 때, 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력합니다.

ljes=njak

결과

6

제출한 답

let inputData = require("fs").readFileSync("dev/stdin").toString().trim();

inputData = inputData.replace(/c=|c-|dz=|d-|lj|nj|s=|z=/g, "0");

console.log(inputData.length);

코드 설명

  • trim() : 문자열에 보이지 않는 문자열이 포함되어 있는 경우로 추정됩니다. 동일한 출력 결과임에도 틀렸습니다 가 나왔기 때문에 trim()으로 보이지 않는 문자열의 제거를 시도했습니다.
  • .replace(/c=|c-|dz=|d-|lj|nj|s=|z=/g, "0")  : replace() 함수와 정규표현식을 통해서 문자열을 치환합니다.
    replace() 함수는 찾은 최초의 문자열만을 변환하지만 /g 정규식을 통해서 찾은 모든 문자열을 변환할 수 있습니다.
  • /찾는문자열/g
    g 는 global 찾은 모든 문자열에 적용합니다. (전역탐색)
    + i 는 대소문자 구분 없이 입니다.

 

+ replace() 함수는 변수값을 직접 바꿔주지 않았습니다.

inputData를 let 으로 선언했음에도 불구하고 

 

inputData.replace(/c=|c-|dz=|d-|lj|nj|s=|z=/g, "0"); 
위와 같이 inputData 변수값 자체를 변환하는 것은 안됩니다.

 

console.log(inputData); 

>> dz=ak

 

inputData = inputData.replace(/c=|c-|dz=|d-|lj|nj|s=|z=/g, "0");

이처럼 변수를 꼭 할당해야 합니다.


1316 그룹 단어 체커

아래와 같이 단어 N개를 입력으로 받아 그룹 단어의 개수를 출력하는 프로그램을 작성하시오. 그룹 단어란 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 가리킵니다. (aabbbccb는 b가 떨어져서 나타나기 때문에 그룹 단어가 아닙니다.)

5
ab
aa
aca
ba
bb

결과

 

4

제출한 답 - includes() 함수로 현재(j) 배열과 다음(j+1)배열을 비교

const inputData = require("fs").readFileSync("dev/stdin").toString().trim().split("\n");

let count = 0;

for (i = 1; i <= inputData[0]; i++) {
  let wordList = [];
  let word = inputData[i].toString().trim().split("");


  for (j = 0; j < word.length; j++) {
    if (word[j] == word[j + 1]) {
      wordList.push(word[j]);
    } else if (word[j] != word[j + 1] && !wordList.includes(word[j + 1])) {
      wordList.push(word[j]);
    }
  }
  if (wordList.length == word.length) {
    count++;
  }
}

console.log(count);

 

코드 설명

  • let word = inputData[i].toString().trim().split("");
    includes() 함수로 현재 배열과 다음 배열을 비교하기 위해서 단어(happy)를 리스트 형태(["h","a","p","p","y"])로 만들어줍니다.

  •  if (word[j] == word[j + 1]) {
         wordList.push(word[j]);
    현재 비교 중인 알파벳(p)이 다음 알파벳(p)과 같다면 wordList에 추가합니다.

  • else if (word[j] != word[j + 1] && !wordList.includes(word[j + 1])) {
          wordList.push(word[j]);
    현재 비교 중인 알파벳(h)이 다음에 올 알파벳(a)과 다르고(&&) 다음에 올 알파벳이 현재 리스트가 포함되지 않는다면 wordList에 추가합니다.

  •   if (wordList.length == word.length) {
        count++;
    word 와 wordlist의 길이를 비교해 둘의 길이가 같다면 count를 1 더합니다.

 

제출한 답 2 - forEach()문 연습입니다. 내용은 같습니다.

const inputData = require("fs").readFileSync("dev/stdin").toString().trim().split("\n");

let count = 0;

for (i = 1; i <= inputData[0]; i++) {
  let wordList = [];
  let word = inputData[i].toString().trim().split("");

  word.forEach((j, k, arr) => {
    if (j == arr[k + 1]) {
      wordList.push(j);
    } else if (j != arr[k + 1] && !wordList.includes(arr[k + 1])) {
      wordList.push(j);
    }
  });
  if (wordList.length == word.length) {
    count++;
  }
}

console.log(count);


문자열 단계는 여기까지입니다.