안녕하세요

우테코 프리코스 1주차 - 문제 4 (리팩토링O) 본문

우테코 프리코스/1주차

우테코 프리코스 1주차 - 문제 4 (리팩토링O)

sakuraop 2022. 10. 29. 03:05

https://github.com/youngentry/javascript-onboarding/blob/main/docs/PROBLEM4.md

 

 

 

🚀 기능 요구 사항

어느 연못에 엄마 말씀을 좀처럼 듣지 않는 청개구리가 살고 있었다. 청개구리는 엄마가 하는 말은 무엇이든 반대로 말하였다.

엄마 말씀 word가 매개변수로 주어질 때, 아래 청개구리 사전을 참고해 반대로 변환하여 return 하도록 solution 메서드를 완성하라.

ABCDEFGHIJKLMNOPQRSTUVWXYZ

Z Y X W V U T S R Q P O N M L K J I H G F E D C B A

제한사항

  • word는 길이가 1 이상 1,000 이하인 문자열이다.
  • 알파벳 외의 문자는 변환하지 않는다.
  • 알파벳 대문자는 알파벳 대문자로, 알파벳 소문자는 알파벳 소문자로 변환한다.

실행 결과 예시

wordresult

"I love you" "R olev blf"

 


좋았던 점

  • 함수를 작게 나누어 depth를 최대 2까지로 만듭니다.

 

 

아쉬운 점

  • 여전히 반복되는 코드가 많이 보이며, 함수로 만든 코드의 재사용성이 낮습니다.
  • 매개변수를 잘 이용한다면 조건 코드를 반으로 줄일 수 있을 것 같지만 방법을 못 떠올리겠습니다.

 
 
// 1. 문자열을 배열로 전환합니다.
// 2. 알파벳을 아스키코드로 전환합니다.
// 3. 알파벳의 거리를 이용하기 위해 알파벳의 인덱스를 구합니다.

// 4. if (A인 경우)
// (1) 알파벳인덱스  1~13인 경우  : 아스키변환값 + (변환 목표까지의 거리)
// (2) 알파벳인덱스  14~26인 경우 : 아스키변환값 - (변환 목표까지의 거리)
// 5. if (a인 경우)에도 마찬가지로 (1)과 (2)를 실행합니다.

// 6. 배열의 요소들을 문자열로 전환합니다.
// 7. 배열을 문자열로 합친 결과를 리턴합니다.

 

function problem4(word) {
    // 1. 각각의 문자를 아스키코드로 변환하기 위해서 split메서드로 문자열을 배열로 만듭니다.
    const arr = word.split("");

    // 2. 알파벳을 아스키코드로 변환합니다.
    const arrCode = arr.map((el) => el.charCodeAt());

    // 3.  a:1, b:2, c:3, ... , m:13, n:14, ... , x:24, y:25, z:26
    let alphabetIdx;
    const A_Code = "A".charCodeAt();
    const a_Code = "a".charCodeAt();

    /** 정반대 위치의 알파벳에 해당하는 아스키코드로 변환하는 함수입니다. */
    const alphaChange = () => {
        // 정반대 위치의 알파벳에 해당하는 아스키코드 = 아스키변환값 + (중앙에서부터 변환 목표까지의 거리 * 2) -1
        // 알파벳인덱스가 1~13일 때
        if (alphabetIdx < 14) {
            arrCode[i] += (14 - alphabetIdx) * 2 - 1;
        }
        // 알파벳인덱스가 14~26일 때
        if (alphabetIdx >= 14) {
            arrCode[i] -= (alphabetIdx - 13) * 2 - 1;
        }
    };

    for (i = 0; i < arrCode.length; i++) {
        // 띄어쓰기는 변환 대상에서 제외하기 위해 배열의 요소가 32가 아닌 경우에만 실행합니다.
        if (arrCode[i] === 32) {
            continue;
        }

        // 4. 대문자(A)일 때
        if (arrCode[i] < a_Code) {
            // ※알파벳인덱스(alphabetIdx)를 구합니다.
            alphabetIdx = (arrCode[i] + 1) % A_Code;
            // 정반대 위치의 알파벳에 해당하는 아스키코드로 변환합니다.
            alphaChange();
        }
        // 5. 소문자(a)일 때
        if (arrCode[i] >= a_Code) {
            alphabetIdx = (arrCode[i] + 1) % a_Code;
            alphaChange();
        }
    }

    // 6. 배열의 요소들을 아스키코드에서 문자열로 전환합니다.
    const resultArr = arrCode.map((el) => String.fromCharCode(el));

    // 7. 배열을 문자열로 합친 결과를 리턴합니다.
    console.log(resultArr.join(""));
    return resultArr.join("");
}

problem4("R olev blf");


리팩토링 전 코드

 
function problem4(word) {
    const arr = word.split("");
    const arrCode = arr.map((el) => el.charCodeAt());
    let alphabetIdx;
    const A_Code = "A".charCodeAt();
    const a_Code = "a".charCodeAt();

    const alphaChange = () => {
        if (alphabetIdx < 14) {
            arrCode[i] += (14 - alphabetIdx) * 2 - 1;
        }
        if (alphabetIdx >= 14) {
            arrCode[i] -= (alphabetIdx - 13) * 2 - 1;
        }
    };

    for (i = 0; i < arrCode.length; i++) {
        if (arrCode[i] === 32) {
            continue;
        }

        if (arrCode[i] < a_Code) {
            alphabetIdx = (arrCode[i] + 1) % A_Code;
            alphaChange();
        }
        if (arrCode[i] >= a_Code) {
            alphabetIdx = (arrCode[i] + 1) % a_Code;
            alphaChange();
        }
    }

    const resultArr = arrCode.map((el) => String.fromCharCode(el));

    return resultArr.join("");
}

problem4("R olev blf");

리팩토링 후 코드

  • 함수를 두 개로 분리
  • 대문자일 때와 소문자일 때를 한 번에 처리하도록 개선
function problem4(word) {
    const getAlphabetIndex = (asciiAlphabet) => {
        if (asciiAlphabet < 97) {
            return asciiAlphabet % 64;
        }
        if (asciiAlphabet >= 97) {
            return asciiAlphabet % 96;
        }
    };

    const changeAlphabet = (asciiAlphabet, alphabetIndex) => {
        if (alphabetIndex < 14) {
            return asciiAlphabet + (14 - alphabetIndex) * 2 - 1;
        }
        if (alphabetIndex >= 14) {
            return asciiAlphabet - (alphabetIndex - 13) * 2 + 1;
        }
    };

    const asciiAlphabetArray = word.split("").map((el) => el.charCodeAt());

    for (i = 0; i < asciiAlphabetArray.length; i++) {
        let asciiAlphabet = asciiAlphabetArray[i];

        if (asciiAlphabet === 32) {
            continue;
        }
        if (asciiAlphabet < 65 || asciiAlphabet > 122) {
            continue;
        }
        if (asciiAlphabet > 90 && asciiAlphabet < 97) {
            continue;
        }

        let alphabetIndex = getAlphabetIndex(asciiAlphabet);
        asciiAlphabetArray[i] = changeAlphabet(asciiAlphabet, alphabetIndex);
    }

    const result = asciiAlphabetArray.map((el) => String.fromCharCode(el)).join("");

    return result;
}

module.exports = problem4;