프로그래머스 문제풀기

프로그래머스 12탄 (코딩 도장 문제 1,2)

Hyeon been 2023. 5. 31. 20:30

한번씩 읽고 가세요.

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90

1.

1차원의 점들이 주어졌을 때, 그 중 가장 거리가 짧은 것의 쌍을 출력하는 함수를 작성하시오. (단 점들의 배열은 모두 정렬되어있다고 가정한다.)예를들어 S={1, 3, 4, 8, 13, 17, 20} 이 주어졌다면, 결과값은 (3, 4)가 될 것이다.

풀이

s = [1, 3, 4, 8, 13, 17, 20]
index = 0
minim = Infinity
for (let i = 1; i < s.length; i++) {
    if (s[i] - s[i-1] < minim) {
        index = i
        minim = s[i] - s[i-1]
    }
}

console.log(s[index], s[index-1])

주어진 배열 s에서 연속된 두 요소 간의 차이가 가장 작은 인덱스를 찾아 그 인덱스와 그 전 인덱스의 값을 출력하는 것입니다.

  1. 먼저, index 변수를 0으로 초기화하고, minim 변수를 양의 무한대(Infinity)로 초기화합니다.
  2. 반복문을 통해 i를 1부터 s의 길이까지 증가시킵니다.
  3. 조건문을 사용하여 s[i] - s[i-1]이 minim보다 작을 경우, index를 i로 업데이트하고 minim을 s[i] - s[i-1]로 업데이트합니다.
  4. 반복문이 종료되면, s[index]와 s[index-1]의 값을 출력합니다.

따라서, s[index]는 연속된 두 요소 간의 차이가 가장 작은 값을, s[index-1]은 그 전 인덱스의 값을 나타냅니다.

두 번째 코드에서는 다른 방법으로 동일한 결과를 얻으려고 합니다. 코드를 단계별로 해석해보면 다음과 같습니다:

  1. s 배열에서 첫 번째 요소를 제외한 새로운 배열 ss를 생성합니다. (s.slice(1))
  2. s 배열의 각 요소와 ss 배열의 동일한 인덱스에 있는 요소를 페어로 매핑합니다. (s.map((v, i) => [v, ss[i]]))
  3. 매핑된 페어들을 연속된 두 요소의 차이 순으로 정렬합니다. (sort((a, b) => (a[1]-a[0]) - (b[1]-b[0])))
  4. 정렬된 페어들 중 첫 번째 페어를 선택합니다. ([0])

결과적으로, 두 번째 코드에서는 s 배열에서 연속된 두 요소 간의 차이가 가장 작은 페어를 반환하는 것입니다. 이 페어의 첫 번째 요소는 연속된 두 요소 중 뒷 요소이고, 두 번째 요소는 그 전 인덱스의 요소입니다.

다른 풀이

s = [1, 3, 4, 8, 13, 17, 20]
ss = s.slice(1)
s.map((v, i) => [v, ss[i]])
s.map((v, i) => [v, ss[i]]).sort((a, b) => (a[1]-a[0]) - (b[1]-b[0]))[0]

2.

문자열을 입력받아서, 같은 문자가 연속적으로 반복되는 경우에 그 반복 횟수를 표시하여 문자열을 압축하기.

입력 예시: aaabbcccccca

출력 예시: a3b2c6a1

 

풀이

const s = 'aaabbcccccca'

let result = s[0]
let count = 0

for (let str of s){
    console.log(str)
    console.log(result)
    if (str == result.slice(-1)){
        count += 1
    }
    else {
        result += count + str
        count = 1
    }
}

result += count
console.log(result)

// ---

const s = "aaabbcccccca";
const reg = /(\w)\1*/g;

[...s.matchAll(reg)]

// ---

var strzip = str => str.replace(/(\D)\1*/g, s => s[0] + s.length);

console.log(strzip("aaabbcccccca"));
console.log(strzip("abcdefg"));
  1. 문자열 s와 압축 결과를 저장할 변수 result를 선언하고, s의 첫 번째 문자를 result에 할당합니다.
  2. 개수를 세기 위한 변수 count를 0으로 초기화합니다.
  3. for...of 루프를 사용하여 문자열 s의 각 문자에 대해 반복합니다.
  4. 현재 문자 str과 result의 마지막 문자를 비교하여 같을 경우, count를 1 증가시킵니다.
  5. 다른 문자일 경우, result에 count와 str을 이어붙이고 count를 1로 초기화합니다.
  6. 반복이 끝나면, 마지막으로 세어지지 않은 연속된 문자열의 개수를 result에 추가합니다.
  7. result를 출력합니다.

이렇게 하면 result에는 주어진 문자열 s가 연속된 문자들을 세어 압축된 형태로 변환된 결과가 저장됩니다.

두 번째 코드는 정규 표현식을 사용하여 문자열 s에서 연속된 문자열을 매칭하는 것입니다.

  1. 정규 표현식 /(\w)\1*/g를 사용하여 s에서 연속된 문자열을 매칭합니다.
  2. matchAll 메서드를 사용하여 정규 표현식에 매칭되는 모든 결과를 가져옵니다.
  3. 반환된 결과는 이터러블 객체이므로 [... ]를 사용하여 배열로 변환합니다.

이렇게 하면 s에서 연속된 문자열을 매칭하여 배열로 얻을 수 있습니다.

세 번째 코드는 문자열을 압축하는 함수 strzip을 정의하고, 해당 함수를 테스트하는 부분입니다.

  1. strzip 함수는 주어진 문자열 str을 인자로 받습니다.
  2. replace 메서드를 사용하여 정규 표현식 /(\D)\1*/g에 매칭되는 부분을 찾아 교체합니다.
  3. 교체할 문자열은 매칭된 문자열의 첫 번째 문자와 길이로 구성됩니다. (s[0] + s.length)
  4. strzip 함수를 사용하여 "aaabbcccccca"와 "abcdefg"에 대한 결과를 출력합니다.

따라서, 세 번째 코드는 주어진 문자열을 압축하는 함수를 정의하고 이를 테스트하는 부분으로 구성되어 있습니다.