코딩테스트연습/프로그래머스

[프로그래머스 - JAVA] 시저 암호

:)jun 2021. 12. 8. 14:16

https://programmers.co.kr/learn/courses/30/lessons/12926

 

코딩테스트 연습 - 시저 암호

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀

programmers.co.kr

 

공백은 건너뛰고

글자면 대문자면 원래 글자에 + n 한게 'Z' 보다크면 -26 하고 소문자면 원래 글자에 +n 한게 'z'보다 크면 -26하면된다.(대소문자 따로 취급)

 

char[] 배열이 좋을까? 아니면 StringBuffer가 좋을까? 둘 다 해보자.

char배열 에 다 넣어놓고 하나씩 빼면서 확인

 

// 테스트코드
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class Quiz1_CaesarCipherTest {

    Quiz1_CaesarCipher q;

    @BeforeEach
    void setUp() {
        q = new Quiz1_CaesarCipher();
    }

    @Test
    void test1() {
        assertEquals(new String("BC"), q.solution(new String("AB"), 1));
    }

    @Test
    void test2() {
        assertEquals(new String("a"), q.solution(new String("z"), 1));
    }

    @Test
    void test3() {
        assertEquals(new String("e F d"), q.solution(new String("a B z"), 4));
    }
}

//프로덕션코드

public class Quiz1_CaesarCipher {
    public String solution(String s, int n) {

        char[] charArray = new char[s.length()];

        for (int i = 0; i < s.length(); i++) {
            charArray[i] = s.charAt(i);
        }

        char[] newCharArray = new char[s.length()];

        for (int i = 0; i < charArray.length; i++) {
            newCharArray[i] = encrypt(charArray[i], n);
        }

        return new String(newCharArray);


    }

    char encrypt(char element, int n) {
        if (element == ' ') {
            return element;
        }

        int newElement = element + n;

        if (newElement > 'z') {
            newElement -= 26;
            return (char) newElement;
        }

        if ('Z' < newElement && newElement < 'a') {
            newElement -= 26;
            return (char) newElement;

        }
        return (char) newElement;

    }
}

// 히든테스트케이스 중에 통과 안되는 것들이 있네? 뭘 빠뜨렸을까?
// 아? 'Z' 가 57 이고 'a' 가 64 네? 범위를 저렇게 잡아놓으면 포함 안되는 경우들이 존재한다.

//프로덕션코드

public class Quiz1_CaesarCipher {
    public String solution(String s, int n) {

        char[] charArray = new char[s.length()];

        for (int i = 0; i < s.length(); i++) {
            charArray[i] = s.charAt(i);
        }

        char[] newCharArray = new char[s.length()];

        for (int i = 0; i < charArray.length; i++) {
            newCharArray[i] = encrypt(charArray[i], n);
        }

        return new String(newCharArray);


    }

    char encrypt(char element, int n) {
        if (element == ' ') {
            return element;
        }

        int newElement = element + n;

        if ('z' < newElement) {
            newElement -= 26;
            return (char) newElement;
        }

        if (element <= 'Z') {
            if ('Z' < newElement) {
                newElement -= 26;
                return (char) newElement;
            }
        }
        
        return (char) newElement;
    }
}

// 성공! 리팩토링!

public class Quiz1_CaesarCipher {
    public String solution(String s, int n) {

        char[] charArray = new char[s.length()];
        convertStringToCharArray(s, charArray);

        char[] newCharArray = new char[s.length()];
        encryptCharArray(n, charArray, newCharArray);

        return new String(newCharArray);


    }

    private void encryptCharArray(int n, char[] charArray, char[] newCharArray) {
        for (int i = 0; i < charArray.length; i++) {
            newCharArray[i] = encrypt(charArray[i], n);
        }
    }

    private void convertStringToCharArray(String s, char[] charArray) {
        for (int i = 0; i < s.length(); i++) {
            charArray[i] = s.charAt(i);
        }
    }

    char encrypt(char element, int n) {
        if (elementIsSpace(element)) {
            return element;
        }

        int newElement = element + n;

        if (lowerLetterIsOverz(newElement)) {
            newElement -= 26;
            return (char) newElement;
        }

        if (elementIsUpperLetter(element)) {
            if (upperLetterIsOverZ(newElement, 'Z')) {
                newElement -= 26;
                return (char) newElement;
            }
        }

        return (char) newElement;
    }

    private boolean upperLetterIsOverZ(int newElement, int z) {
        return z < newElement;
    }

    private boolean elementIsUpperLetter(char element) {
        return element <= 'Z';
    }

    private boolean lowerLetterIsOverz(int newElement) {
        return 'z' < newElement;
    }

    private boolean elementIsSpace(char element) {
        return element == ' ';
    }
}
// 성공!

 

 

이제 스트링버퍼로 풀어보자!

 

// 프로덕션코드
public class Quiz1_CaesarCipher_2 {
    public String solution(String s, int n) {

        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < s.length(); i++) {
            sb.append(encrypt(s.charAt(i), n));
        }

        return new String(sb);
        
    }

    char encrypt(char element, int n) {
        if (element == ' ') {
            return element;
        }

        int newElement = element + n;

        if (newElement > 'z') {
            newElement -= 26;
            return (char) newElement;
        }

        if (newElement <= 'Z') {
            if (newElement > 'Z') {
                newElement -= 26;
                return (char) newElement;
            }
        }
        return (char) newElement;
    }
}

// 히든 테스트 케이스 실패! 이유가 뭘까? 
// 논리는 똑같은데 StringBuffer를 다루면서 놓친 부분이 있는가보다.
// 아.. encrypt 메소드에서 if(newElement <= 'Z') 가 아니라 if(element <= 'Z') 이다.

// 프로덕션코드

public class Quiz1_CaesarCipher_2 {
    public String solution(String s, int n) {

        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < s.length(); i++) {
            sb.append(encrypt(s.charAt(i), n));
        }

        return new String(sb);

    }

    char encrypt(char element, int n) {
        if (element == ' ') {
            return element;
        }

        int newElement = element + n;

        if (newElement > 'z') {
            newElement -= 26;
            return (char) newElement;
        }

        if (element <= 'Z') {
            if (newElement > 'Z') {
                newElement -= 26;
                return (char) newElement;
            }
        }
        return (char) newElement;
    }
}

// 성공!