본문 바로가기

알고리즘

프로그래머스 알고리즘 스터디 [문37-40]

728x90

문제 37

주어진 숫자 중 3개의 수를 더했을 때 소수가 되는 경우의 개수를 구하려고 합니다. 숫자들이 들어있는 배열 nums가 매개변수로 주어질 때, nums에 있는 숫자들 중 서로 다른 3개를 골라 더했을 때 소수가 되는 경우의 개수를 return 하도록 solution 함수를 완성해주세요.제한사항

  • nums에 들어있는 숫자의 개수는 3개 이상 50개 이하입니다.
  • nums의 각 원소는 1 이상 1,000 이하의 자연수이며, 중복된 숫자가 들어있지 않습니다.

나의코드

function solution(nums) {
    let answer = 0;
    const len = nums.length;
    for (let i = 0; i < len; i++){
        for (let j = i+1; j < len; j++){
            for (let k = j+1; k < len; k++) {
                const number = nums[i]+nums[j]+nums[k];
                if (isPrime(number))
                    answer++;
            }
        }
    }
    function isPrime(number){
        if (number < 2) return true;
        for (let i = 2; i < number; i++){
            if (number % i == 0) return false;
        }
        return true;
    }
    
    return answer;
}

나의풀이

isPrime <- 소수를 판별하는 함수를 다른 곳에서 참고하여 작성하였다. 소수란 1과 자기 자신으로 밖에 나누어 떨어지지 않는 2,3,5,7,11,13,17,19,23,31등과 같은 숫자를 의미한다. 2는 가장 작은 소수이다.  2이면 반드시 true를 반환하고, 2부터 숫자까지 숫자를 i로 나누어 떨어지는게 있으면 false를 반환한다. isPrime함수를 밑에서 작성하고 위의 3중 for문에서 isPrime을 실행시켜도 작동이 되는이유는 hoisting이 되어서 함수의 선언이 가장 위로 올라와있기 때문이다. 3중 for문의 경우 각각 다른 인덱스 번호의 숫자를 골라 더한 모든 경우의 수를 추출하기 위함이고, 경우의수이기 때문에 중복 제거 처리를 하면 안된다. 만약 isPrime에서 number를 넣었을 때 참이 나오면 answer=answer+1을 넣어줘 소수의 개수가 하나씩 올라가도록 처리한다.

 

문제38 : 문자열과 영단어

 

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.

다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.

  • 1478 → "one4seveneight"
  • 234567 → "23four5six7"
  • 10203 → "1zerotwozero3"

이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.

참고로 각 숫자에 대응되는 영단어는 다음 표와 같습니다.

숫자                                                                   영단어

0 zero
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine

천재의 풀이

function solution(s) {
    let numbers = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
    var answer = s;

    for(let i=0; i< numbers.length; i++) {
        let arr = answer.split(numbers[i]);
        answer = arr.join(i);
    }

    return Number(answer);
}

어려운 식 하나도 없이 내가 아는 for문과 split join등을 이용하여 풀었는데 arr.join(i)를 for문이 돌아갈 때마다 넣어주는 부분이 정말 놀라운 코드다

let s="one4seveneight"
arr=s.split("one")
console.log(arr)
console.log(arr.join(1))

onew4seveneight 라는 문자열이 있고 이를 "one"을 기준으로 나누어주면 ["",4seveneight]가 된다. 이를 1로 join해주면 14seveneight이 되는 원리이다​

 

내가 이해할 수 있는 풀이

function solution(s) {
    while(isNaN(+s)) {
        s = s.replace('zero',0)
        s = s.replace('one',1)
        s = s.replace('two',2)
        s = s.replace('three',3)
        s = s.replace('four',4)
        s = s.replace('five',5)
        s = s.replace('six',6)
        s = s.replace('seven',7)
        s = s.replace('eight',8)
        s = s.replace('nine',9)
    }
    return +s
}

가장 쉽게 이해할 수 있었던 풀이이다. s.replace(a,b)를 하면 s라는 문자열에서 a를 찾아 b로 치환해준다. 

 

문제39:시저암호

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.제한 조건

  • 공백은 아무리 밀어도 공백입니다.
  • s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
  • s의 길이는 8000이하입니다.
  • n은 1 이상, 25이하인 자연수입니다.

나의 코드

function solution(s, n){
    return s.split("").map(value => {
        if (value === " ") return value;
        return value.toUpperCase().charCodeAt() + n > 90
        ? String.fromCharCode(value.charCodeAt() + n - 26)
        : String.fromCharCode(value.charCodeAt() + n)
    }).join("");
}

나의 풀이

console.log("A".charCodeAt())//65
console.log("Z".charCodeAt())//90

알파벳은 총 26자로 26을 기준으로 순환한다. map()은 배열의 내장함수이기 때문에 사용하기 위해서 먼저 문자열은 공백을 기준으로 배열에 하나씩 넣어준다. 공백의 경우에는 공백을 그대로 리턴한다. 각 요소들을 toUpperCase()에서 n만큼을 더한 값의 아스키코드가 90을 넘어가면(Z를 넘어가면) 26을 뺀 만큼의 숫자 값을 아스키코드에서 문자열로 변환해야한다. 

console.log(String.fromCharCode(65))//A
console.log(String.fromCharCode(90))//Z

String.fromCharCode()는 ()안의 아스키코드를 문자열로 반환해준다. 리턴문 안에는 for if문등의 작성은 불가능하지만 삼항연산자 코드는 입력이 가능하기 떄문에 삼항연산자에 익숙해지도록 노력하자!

728x90