본문 바로가기
개발 기초 다지기

내일배움캠프 20일차 : 알고리즘 문제 정리(콜라츠 추측, 서울에서 김서방 찾기, 음양 더하기, 핸드폰 번호 가리기)

by 너의고래 2024. 5. 15.
반응형

<문제1 : 콜라츠 추측>

1937년 Collatz란 사람에 의해 제기된 이 추측은, 주어진 수가 1이 될 때까지 다음 작업을 반복하면, 모든 수를 1로 만들 수 있다는 추측입니다. 작업은 다음과 같습니다.

1-1. 입력된 수가 짝수라면 2로 나눕니다. 

1-2. 입력된 수가 홀수라면 3을 곱하고 1을 더합니다. 

2. 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다. 

예를 들어, 주어진 수가 6이라면 6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1 이 되어 총 8번 만에 1이 됩니다. 위 작업을 몇 번이나 반복해야 하는지 반환하는 함수, solution을 완성해 주세요. 단, 주어진 수가 1인 경우에는 0을, 작업을 500번 반복할 때까지 1이 되지 않는다면 –1을 반환해 주세요.

 

제한 사항

  • 입력된 수, num은 1 이상 8,000,000 미만인 정수입니다.

입출력 예

n result
6 8
16 4
626331 -1

입출력 예 설명

입출력 예 #1
문제의 설명과 같습니다.

입출력 예 #2
16 → 8 → 4 → 2 → 1 이 되어 총 4번 만에 1이 됩니다.

입출력 #3
626331
500번을 시도해도 1 되지 못하므로 -1 리턴해야 합니다.

 

- 내가 푼 방법

function solution(num) {
    var answer = 0;
    for(let i=0; i<500; i++){
    if (num != 1){
        num = num%2==0? num/2 : num*3+1
    } else {
        return i
    }
    }
    return answer = -1;
}

 

1이 될 대까지 계속 돌려야하기 때문에 for문을 사용했다.

for문 내에 조건문을 두어 i번재의 num이 1일 경우와 1이 아닐 경우를 나누어주었다.

1이 아닐 경우 주어진 연산을 하도록 만든 후 다시 계속 돌아가도록 한다

1일 경우는 i 값을 반환하여 작업을 몇 번 반복했는지 구한다

for문의 조건에 맞지 않는 500회 이상 반복했을 때는 -1 값을 반환하도록하였다.

 

- 다른 풀이

function collatz(num) {
    var answer = 0;
    while(num !=1 && answer !=500){
        num%2==0 ? num = num/2 : num = num*3 +1;
    answer++;
  }
    return num == 1 ? answer : -1;
}
// 아래는 테스트로 출력해 보기 위한 코드입니다.
console.log( collatz(6) );

 

while문을 통해 num이 1이 아니고 500번 반복하지 않을 때까지 조건을 넣었다 

  • while :반복이 시작되기 전에 조건문은 ,거짓을 판단받게 된다. 만약 조건문이 참이라면, while 안의 문장들이 실행된다. 거짓이라면, 문장은 그냥 while 반복문 후로 넘어간다.

- 다른 풀이

const solution = (num) => collatzGuessCount(num, 0);

const collatzGuessCount = (num, acc) => 
  (num === 1) ? ((acc > 500) ? -1 : acc) : collatzGuessCount(processCollatz(num), acc + 1);

const processCollatz = (num) => (num % 2 === 0) ? (num / 2) : (num * 3 + 1);

 

 

 

<문제2 : 서울에서 김서방 찾기>

String형 배열 seoul의 element중 "Kim"의 위치 x를 찾아, "김서방은 x에 있다"는 String을 반환하는 함수, solution을 완성하세요. seoul에 "Kim"은 오직 한 번만 나타나며 잘못된 값이 입력되는 경우는 없습니다.

 

제한 사항

  • seoul은 길이 1 이상, 1000 이하인 배열입니다.
  • seoul의 원소는 길이 1 이상, 20 이하인 문자열입니다.
  • "Kim"은 반드시 seoul 안에 포함되어 있습니다.

입출력 예

seoul return
["Jane", "Kim"] "김서방은 1 있다"

 

- 내가 푼 풀이

function solution(seoul) {
    var answer = '';
    
    for(let i=0; i<seoul.length; i++){
       if( seoul[i] === "Kim"){
          return answer = `김서방은 ${i}에 있다`
       }
    }
}

 

answer이 문자형이기 때문에 answer을 빈 문자열로 정의했다.

kim의 배열 속 위치를 찾기 위해 seoul 배열의 길이만큼 for문을 돌려 'kim'의 위치를 찾는다.

조건문을 통해 값이 kim과 위치할 때 i 값을 반환하도록 한다.

 

- 다른 풀이

function findKim(seoul){
  var idx = seoul.indexOf('Kim');

  return "김서방은 " + idx + "에 있다";
}

// 실행을 위한 테스트코드입니다.
console.log( findKim(["Queen", "Tod", "Kim"]));

 

특정 문자열의 위치를 찾는 index of를 통해 바로 kim의 위치를 찾고 그 값을 반환

  • index of(string.indexOf(searchvalue, position)) :문자열(string)에서 특정 문자열(searchvalue)을 찾고, 검색된 문자열이 '첫번째' 나타나는 위치 index 리턴

- 다른 풀이

function findKim(seoul) {
    return "김서방은 " + seoul.indexOf('Kim') + "에 있다";
}

 

같은 개념이나 index of를 바로 return에 주어 한 줄로 풀이를 끝냄

 

 

 

<문제3 : 음양 더하기>

어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes와 이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다. 실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.

 

제한사항

  • absolutes의 길이는 1 이상 1,000 이하입니다.
  • signs의 길이는 absolutes의 길이와 같습니다.

 

입출력 예

absolutes signs result
[4,7,12] [true,false,true] 9
[1,2,3] [false,false,true] 0

입출력 예 설명

입출력 예 #1

  • signs가 [true,false,true] 이므로, 실제 수들의 값은 각각 4, -7, 12입니다.
  • 따라서 세 수의 합인 9를 return 해야 합니다.

입출력 예 #2

  • signs가 [false,false,true] 이므로, 실제 수들의 값은 각각 -1, -2, 3입니다.
  • 따라서 수의 합인 0 return 해야 합니다.

- 내가 푼 방법

function solution(absolutes, signs) {
    var answer = 0;
    
    for (let i = 0; i < absolutes.length; i++) {
        if (signs[i] === true) {
            answer = answer + absolutes[i];
        } else if (signs[i] === false) {
            answer = answer - absolutes[i];
        }
    }    
    return answer;
}

 

for문을 사용하여 각 배열의 위치(i)를 하나씩 적용하는 방법으로 풀이.

for문은 절댓값 배열의 길이만큼 반복되도록 했으며,  signs의 불리언 값에 따라 answer 값에 더해줄지 빼줄지를 결정하여 실제 정수들의 합을 구하도록 풀이.

 

- 다른 풀이

function solution(absolutes, signs) {

    return absolutes.reduce((acc, val, i) => acc + (val * (signs[i] ? 1 : -1)), 0);
}

 

누산기능인 reduce를 통해 짧게 풀이.

signs의 불리언 값에 따라 삼항연산자를 통해 true면 1을 곱해주고 false면 -1을 곱해 정수 값을 만들어 정수의 합을 구하도록 풀이

 

function solution(absolutes, signs) {
    let answer = 0;
    absolutes.forEach((v, i) => {
        if (signs[i]) {
            answer += v;
        } else {
            answer -= v;
        }
    })
    return answer;
}

 

forEach를 통해 변수와 인덱스 값을 사용하여 풀이.

signs값이 true일 경우 더하고 그 외의 경우 빼서 배열을 모두 돌려 정수의 합을 반환하도록 풀이

 

 

 

 

<문제4: 핸드폰 번호 가리기>

 

프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 고객들의 전화번호의 일부를 가립니다.
전화번호가 문자열 phone_number로 주어졌을 때, 전화번호의 뒷 4자리를 제외한 나머지 숫자를 전부 *으로 가린 문자열을 리턴하는 함수, solution을 완성해주세요.

 

제한 조건

  • phone_number는 길이 4 이상, 20이하인 문자열입니다.

입출력 예

phone_number return
"01033334444" "*******4444"
"027778888" "*****8888"

 

- 내만 만든 코드

function solution(phone_number) {
    var answer = '';
    let len = phone_number.length
    answer = "*".repeat(len-4) + phone_number.slice(-4);
    
    
    return answer;
}

 

우선 len이라고 phone_number의 자릿수를 정의한다.

전체 길이의 4를 뺀만큼 *을 반복하고, phone_number의 뒤에서 4번째까지를 추출해 붙여 넣는다.

  • string.repeat() : 문자열을 주어진 수만큼 반복
  • str.slice(beginIndex[, endIndex]) : beginIndex부터 endIndex 직전까지 추출. endIndex 없을 경우 끝까지 추출

 

- 다른 풀이

const solution = n => [...n].fill("*",0,n.length-4).join("")

 

문자열 n 을 배열로 바꾼다.

배열의 첫번째부터 마지막에서 4번째 전 배열크기만큼 * 로 채운다.

join 하여 string으로 반환한다.

  • array.fill(value, start, end) :배열의 인덱스 범위 내에 있는 모든 요소를 정적 값으로 변경합니다. 그리고 수정된 배열을 반환
  • join() : 배열의 모든 요소를 쉼표나 지정된 구분 문자열로 구분하여 연결한 문자열을 만들어 반환
반응형

댓글