프로그래머스 L1 - 성격 유형 검사하기

2024. 3. 23. 21:18알고리즘/프로그래머스

https://school.programmers.co.kr/learn/courses/30/lessons/118666

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


해석

survey를 가지고 점수 배치표를 완성해야한다. 만일 "AN"이 오게 되면,

매우 비동의 : A - 3

비동의 : A - 2

약간 비동의 : A - 1

모르겠음

약간 동의 : N - 1

동의 : N - 2

매우 동의 : N - 3

다음과 같이 점수 배치표를 완성하고 choices의 값에 따라 성격 유형 점수를 하나씩 올려주면 된다.

function solution(survey, choices) {
    let table = [];
    let options = ["R","T","C","F","J","M","A","N"];
    let ret = "";
    for (let i = 0; i < options.length; i += 2) {
        let obj = {};
        obj[options[i]] = 0;
        obj[options[i + 1]] = 0;
        table.push(obj);
    }
    for(let i = 0; i<survey.length; i++){
        const [a,b] = survey[i].split("");
        const map = new Map();
        for(let i = 1; i<=7; i++){
            if(i<4) map.set(i,[a,4-i]);
            if(i>4) map.set(i,[b,i-4]);
        }
        if(choices[i]===4) continue;
        if(map.get(choices[i])[0]==='R'||map.get(choices[i])[0]==='T'){
            if(map.get(choices[i])[0]==='R') table[0].R+=map.get(choices[i])[1];
            else table[0].T+=map.get(choices[i])[1];
        }
        if(map.get(choices[i])[0]==='C'||map.get(choices[i])[0]==='F'){
            if(map.get(choices[i])[0]==='C') table[1].C+=map.get(choices[i])[1];
            else table[1].F+=map.get(choices[i])[1];
        }
        if(map.get(choices[i])[0]==='J'||map.get(choices[i])[0]==='M'){
            if(map.get(choices[i])[0]==='J') table[2].J+=map.get(choices[i])[1];
            else table[2].M+=map.get(choices[i])[1];
        }
        if(map.get(choices[i])[0]==='A'||map.get(choices[i])[0]==='N'){
            if(map.get(choices[i])[0]==='A') table[3].A+=map.get(choices[i])[1];
            else table[3].N+=map.get(choices[i])[1];
        }
    }
    table.forEach((t)=>{
        let temp = [];
        let max = -1;
        for(const v of Object.values(t)) max = Math.max(max, v);
        for(const [k,v] of Object.entries(t)) if(v===max) temp.push(k); 
        ret+=temp[0];
    })
    return ret;
}

 

    for (let i = 0; i < options.length; i += 2) {
        let obj = {};
        obj[options[i]] = 0;
        obj[options[i + 1]] = 0;
        table.push(obj);
    }

성격 유형 점수를 계산하기 위한 코드이다.

table을 통해서 마지막에 어떤 성격 유형인지 계산할 것이다.

자료형은 현재 [ { R:0, T:0 }, { C:0, F:0 }, { J:0, M:0 }, { A:0, N:0 }, ] 이렇게 구성되어있다. 지표별로 구분하였다.

R 유형이면 R의 값을 하나 올려주고, J 유형이면 J의 값을 하나 올려줄 것이다. 

 

    for(let i = 0; i<survey.length; i++){
        const [a,b] = survey[i].split("");
        const map = new Map();
        for(let i = 1; i<=7; i++){
            if(i<4) map.set(i,[a,4-i]);
            if(i>4) map.set(i,[b,i-4]);
        }
        if(choices[i]===4) continue;
        if(map.get(choices[i])[0]==='R'||map.get(choices[i])[0]==='T'){
            if(map.get(choices[i])[0]==='R') table[0].R+=map.get(choices[i])[1];
            else table[0].T+=map.get(choices[i])[1];
        }
        if(map.get(choices[i])[0]==='C'||map.get(choices[i])[0]==='F'){
            if(map.get(choices[i])[0]==='C') table[1].C+=map.get(choices[i])[1];
            else table[1].F+=map.get(choices[i])[1];
        }
        if(map.get(choices[i])[0]==='J'||map.get(choices[i])[0]==='M'){
            if(map.get(choices[i])[0]==='J') table[2].J+=map.get(choices[i])[1];
            else table[2].M+=map.get(choices[i])[1];
        }
        if(map.get(choices[i])[0]==='A'||map.get(choices[i])[0]==='N'){
            if(map.get(choices[i])[0]==='A') table[3].A+=map.get(choices[i])[1];
            else table[3].N+=map.get(choices[i])[1];
        }
    }

map을 활용해서 survey로 들어온 데이터를 기반으로 점수 배치표를 만든다.

그리고 choices를 map의 key값으로 넣어주면 해당하는 점수표가 반환이 된다.

그리고 table에 해당 유형의 점수를 올려주는 코드이다.

 

    table.forEach((t)=>{
        let temp = [];
        let max = -1;
        for(const v of Object.values(t)) max = Math.max(max, v);
        for(const [k,v] of Object.entries(t)) if(v===max) temp.push(k); 
        ret+=temp[0];
    })

점수가 매겨진 table 요소를 순회하면서 가장 많은 점수를 얻은 유형을 반환한다.

이때 점수가 같다면 사전순으로 먼저 온 유형을 반환하도록 구현했다.


다른 풀이

위의 코드는 굉장히 직관적으로 푼 코드이다.

코드의 길이가 길고, 중복 연산되는 부분이 그리 좋아보이진 않았다.

function solution(survey, choices) {
    const MBTI = {};
    const types = ["RT","CF","JM","AN"];

    types.forEach((type) =>
        type.split('').forEach((char) => MBTI[char] = 0)
    )

    choices.forEach((choice, index) => {
        const [disagree, agree] = survey[index];

        MBTI[choice > 4 ? agree : disagree] += Math.abs(choice - 4);
    });

    return types.map(([a, b]) => MBTI[b] > MBTI[a] ? b : a).join("");
}

정말 감탄이 나오는 코드이다.

 

    types.forEach((type) =>
        type.split('').forEach((char) => MBTI[char] = 0)
    )

이 부분은 같은 지표의 타입을 분리해서 점수표를 만드는 코드이다.

 

    choices.forEach((choice, index) => {
        const [disagree, agree] = survey[index];

        MBTI[choice > 4 ? agree : disagree] += Math.abs(choice - 4);
    });

survey로 들어온 데이터는 앞의 문자가 비동의에 해당하고, 뒤에 문자가 동의에 해당한다.

따라서 choice를 4를 기준으로 나누어 4보다 크다면 동의에 해당하고, 4보다 작다면 비동의에 해당한다.

점수표에 알맞은 점수 배치값을 더해주는 코드이다.

 

return types.map(([a, b]) => MBTI[b] > MBTI[a] ? b : a).join("");

그리고 해당 유형의 점수를 비교해서 큰 값을 리턴하도록 한다.

같은 경우에는 types의 문자들이 사전순으로 배치가 되어있기 때문에 첫번째 요소를 리턴하면 된다.


느낀점

문제에 다음과 같이 나와있다.

survey[i]의 첫번째 캐릭터는 i+1번 질문의 비동의 관련 선택지를 선택하면 받는 성격 유형이다.

survey[i]의 두번째 캐릭터는 i+1번 질문의 동의 관련 선택지를 선택하면 받는 성격 유형이다.

문제를 정확히 이해하면 더 쉬운 방법으로 풀 수 있지 않았을까 하는 생각이 든다.

문제가 길면 요점이 흐려지는 경우가 있다. 방대한 문제의 길이 때문에 핵심 요구사항을 잃어버리게 되는것이다.

무엇을 해결해야하는지에 대한 요점을 놓치지 않고 집중력있게 문제를 이해하는 연습이 필요한 거 같다.