[문자열] 백준 - 문서검색(1543), DNA(1969), 비밀 이메일(2999), IPv6(3107), 이름궁합(15312)

iberis2·2023년 6월 24일
0
post-thumbnail

선택 언어 : nodejs
백준 배열 문제 모음 : 🔗 BaaaaaaaaaaarkingDog 부록 A - 문자열 기초

1543번 - 문서검색

  1. 문장에서 단어가 들어간 인덱스 번호를 찾아서
  2. 그 단어 만큼 잘라낸 후 나머지에서 다시 인덱스 번호를 찾음
  3. 인덱스 번호가 더 안나오면 count 끝
let [sentence, word] = require('fs').readFileSync('./input.txt').toString().split('\n')

let count = 0,
  index = sentence.indexOf(word)
while (index >= 0) {
  count++
  sentence = sentence.substring(index + word.length)
  index = sentence.indexOf(word)
}

console.log(count)

1969번 - DNA

풀이 1

문제를 꼼꼼히 안읽어서 어렵게 풀었다. 문제를 잘 읽자!! 😓

  1. 각 문자열을 돌면서 각 N번째의 알파벳의 개수를 모아서 그 중 가장 많이 나온 문자로만 새로 글자를 만든다\
    1-1. 각 문자열 돌기 + 모든 문자열의 N 번째 알파벳을 카운팅하는 객체 만들기 → 2중 for 문
  2. 각 알파벳 객체에서 가장 큰 value로 key를 찾아 배열로 만든다\
    2-1. max value 가 동일한 key 들은 알파벳 순서로 정렬해서 첫 번째를 고른다 ex- F, C, A 중에서 A
  3. 모아진 배열과 기존 글자들을 다시 비교해서 서로 다른 글자만 filter 로 모아서 길이를 잰다
const [numAry, ...input] = require('fs').readFileSync('./input.txt').toString().trim().split('\n')
const [count, DNA_length] = numAry.split(' ').map(Number)

// count: 5 strLength: 8
// input: [ 'TATGATAC', 'TAAGCTAC', 'AAAGATCC', 'TGAGATAC', 'TAAGATGT' ]

let str_count = []

for (let i = 0; i < DNA_length; i++) {
  str_count.push({})
  for (let j = 0; j < count; j++) {
    let cur_DNA = input[j][i]
    str_count[i][cur_DNA] ? str_count[i][cur_DNA]++ : (str_count[i][cur_DNA] = 1)
  }
}

/* str_count: 
[
  { T: 4, A: 1 },
  { A: 4, G: 1 },
  { T: 1, A: 4 },
  { G: 5 },
  { A: 4, C: 1 },
  { T: 5 },
  { A: 3, C: 1, G: 1 },
  { C: 4, T: 1 }
]
*/

// 각 객체에서 values 가 가장 큰 값의 key 를 찾는다
let newArray = str_count.map(obj => {
  let max = Math.max(...Object.values(obj))
  let keys = Object.keys(obj).filter(key => obj[key] === max)
  return keys.sort()[0]
})

let differCount = 0
for (let str of input) {
  let differ = newArray.filter((al, idx) => al !== str[idx])
  differCount += differ.length
}

let newDNA = newArray.join('')

console.log(newDNA)
console.log(differCount)

2차 풀이

  1. DNA 는 A, T, G, C 4가지로 한정되어 있다는 걸 문제에서 제대로 못 봤다..
  2. DNA 가 담겨 있는 객체를 만들고, 알파벳이 나올 때마다 해당 알파벳 key의 value 를 올려준다.
  3. max 값보다 크면 max 를 해당 알파벳으로 바꾼다
  4. max 값보다 작으면 아스키코드 값이 더 작은 알파벳으로 max값을 바꾼다
  5. 새로운 DNA 알파벳 배열과 기존 DNA 들의 알파벳을 비교해 다른 값을 모은 배열을 만들고 그 배열의 길이를 더한다.
const [numAry, ...input] = require('fs').readFileSync('./input.txt').toString().trim().split('\n')
const [count, DNA_length] = numAry.split(' ').map(Number)

// count: 5 strLength: 8
// input: [ 'TATGATAC', 'TAAGCTAC', 'AAAGATCC', 'TGAGATAC', 'TAAGATGT' ]

let maxAry = []

for (let i = 0; i < DNA_length; i++) {
  let counts = { A: 0, T: 0, G: 0, C: 0 },
    max = 'A'
  for (let j = 0; j < count; j++) {
    let cur_DNA = input[j][i]

    counts[cur_DNA]++

    if (counts[max] < counts[cur_DNA] || (counts[max] === counts[cur_DNA] && max > cur_DNA)) {
      max = cur_DNA
    }
  }
  maxAry.push(max)
}

console.log('maxAry:', maxAry)

/* maxAry: [
  'T', 'A', 'A',
  'G', 'A', 'T',
  'A', 'C'
]
*/

let differCount = 0
for (let str of input) {
  let differ = maxAry.filter((al, idx) => al !== str[idx])
  differCount += differ.length
}

let newDNA = maxAry.join('')

console.log(newDNA)
console.log(differCount)

2999번 - 비밀 이메일

풀이 1. 정규표현식 이용

  1. 문자열 길이의 약수 중 가장 중간 값의 약수를 구한다 → R: 작은 수, C: 큰 수
  2. 문자열을 R 개의 길이의 C 번째 문자열마다 모아서 정답을 만든다.
  • 문자열 → 배열 → 문자열로 안바꾸고 2중 for문을 돌려서 처리하고 싶었는데
  • 몇 번 index 번호를 건너뛰고 몇 번째 부터 다시 돌아서 그 다음 index 번호로 갈지 계산하다가 머리 터져서 🤯
  1. 결국 정규표현식으로 길이R인 문자열 C 개로 자른 배열을 만들고 ex - R:2, C:3 ['aa', 'bb', 'cc']
  2. 배열의 각 요소(문자열)에서 같은 위치에 있는 알파벳을 합쳤다. ex - 'abcabc'
const input = require('fs').readFileSync('./input.txt').toString().trim()
let N = input.length
let R = Math.floor(Math.sqrt(N))

while (N % R !== 0) {
  R--
}

let C = N / R

let regex = new RegExp(`.{1,${R}}`, 'g')
let result = input.match(regex)

let answer = ''
for (let i = 0; i < R; i++) {
  for (let j = 0; j < C; j++) {
    answer += result[j][i]
  }
}

console.log(answer)

풀이 2. 배열로 바꾸지 않고 2중 for문으로 해결하는 방법

const input = require('fs').readFileSync('./input.txt').toString().trim()
let N = input.length
let R = Math.floor(Math.sqrt(N))

while (N % R !== 0) {
  R--
}

let C = N / R

let answer = ''
for (let a = 0; a < R; ++a) {
  for (let b = 0; b < C; ++b) {
    answer += input[b * R + a]
  }
}

console.log(answer)

3107번 - IPv6

  1. ':' 기준으로 분리된 배열을 만듦 .split(':')
  2. '::' 연속 된 경우 사이에 '' 공백 문자열이 생긴다.
  3. 분리된 배열의 길이가 8보다 짧은 경우 '' 공백 문자열 뒤에 '' 공백 문자열을 추가한다. (0000은 연속해서만 나오니까) .splice(emptyIdx, 0, '')
  4. 분리된 문자열의 길이가 8보다 긴 경우 '' 공백 문자열을 삭제한다 .splice(emptyIdx, 1)
  5. 모든 문자열을 돌면서 4글자에 맞춰서 앞에 '0'을 추가한다 .padStart(4, '0')
  6. 배열을 ':'로 이어진 문자열로 합친다 .join(':')
const input = require('fs').readFileSync('./input.txt').toString().trim()

let array = input.split(':')

while (array.length < 8) {
  let emptyIdx = array.indexOf('')
  array.splice(emptyIdx, 0, '')
  console.log('중간', array, array.length)
}

while (array.length > 8) {
  let emptyIdx = array.indexOf('')
  array.splice(emptyIdx, 1)
}

let strAry = array.map(str => str.padStart(4, '0')).join(':')
console.log(strAry)

15412번 - 이름궁합

  1. 알파벳이 key 이고 value 가 획순인 객체를 만듦 {A: 3, B: 2, C: 1 ...}
  2. 두 명의 이름 알파벳이 교차로 들어간 배열을 만듦 ex- KIM, PAR -> K P I A M R
  3. 두 글짜씩 획순을 더해줘야 함
  • 각 글자가 알파벳 객체의 키 ex- PARK -> alphabet[P] + alphabet[A] === 2 + 3
  • 일의 자리만 남겨야 하니 % 10 을 해 줌
  1. 두 글 자씩 합쳐서 만든 숫자 배열을 재귀에 넣어서 또 두 글자씩 합침
  2. 배열의 요소가 2개 남을 때 까지 반복
const [A, B] = require('fs').readFileSync('./input.txt').toString().trim().split('\n')

// 알파벳 객체
const alphabetNum = [3, 2, 1, 2, 3, 3, 2, 3, 3, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 1, 1, 1, 2, 2, 1]
const alphabet = {}
for (let i = 65; i <= 90; i++) {
  alphabet[String.fromCharCode(i)] = alphabetNum[i - 65]
}

// 이름에 들어간 알파벳들 획 순을 모은 배열
let nameNum = []
for (let i = 0; i < A.length; i++) {
  nameNum.push(alphabet[A[i]])
  nameNum.push(alphabet[B[i]])
}

const nameTest = ary => {
  // 2 글자만 남았을 때 리턴
  if (ary.length <= 2) return console.log(ary.join('').padStart(2, '0'))

  let i = 1,
    answer = []

  while (ary[i] !== undefined) {
    let a = ary[i] + ary[i - 1]
    answer.push(a % 10)
    i += 1
  }
  return nameTest(answer)
}

nameTest(nameNum)
profile
React, Next.js, TypeScript 로 개발 중인 프론트엔드 개발자

0개의 댓글