[Java] 알고리즘, "시저 암호"

시저 암호

문제 설명

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


제한 조건

- 공백은 아무리 밀어도 공백입니다.

- s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.

- s의 길이는 8000이하입니다.

- n은 1 이상, 25이하인 자연수입니다.


입출력 예

s

 n

 result

AB

 1

 BC

 z

 1

 a

 a B z

4

 e F d


나의 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
  public String solution(String s, int n) {
      String answer = "";
      int z = (int)'z';
      int Z = (int)'Z';
      int a = (int)'a';
      int A = (int)'A';
      char[] temp = s.toCharArray();
      
      for(int i =0; i<temp.length; i++){
          if(temp[i]>=a&& temp[i]<=z){
              //소문자인경우
              temp[i] = (int)temp[i]+> z ? (char)(a+(int)temp[i]+n-z-1) : (char)((int)temp[i]+n); 
          }else if(temp[i]>=A&& temp[i]<=Z){
              //대문자인경우
              temp[i] = (int)temp[i]+> Z ? (char)(A+(int)temp[i]+n-Z-1) : (char)((int)temp[i]+n);
          }else{
              //공백
              temp[i]=temp[i];
          }
      }
      answer = new String(temp);
      return answer;
  }
}
cs


이것은 int형과 char형의 특징을 잘 이해해야만 풀 수 있는 문제입니다. int형과 char형은 서로 형변환이 가능한 타입입니다. 하지만 int형과 char형은 서로 직접적인 연산은 불가합니다. 즉 int형 + char형을 한다고해서 int형이 되거나 char형이 되는 것이 아닙니다. 즉, 어느 한쪽으로 타입변환을 해주어야 합니다. 

저는 이문제를 소문자인 경우, 대문자인 경우, 그리고 공백인 경우로나누었습니다. 공백인 경우는 쉽죠. 그냥 그대로 두어도 됩니다.(코드상에서는 뭐라도적어야 할것같아서 그냥 적었습니다.) 둘 다 흐름은 같아서 요점만 말하면

- n을 더한 값이 z보다 클 때

- n을 더한 값이 z보다 작을 때


두경우를 분리해서 풀었습니다. 삼항 연산자로 표현했습니다. 작을 경우는 그냥 더해주고 타입변환 다시 해주면 됩니다만. 클때는 전체 더한 값에서 z값을 빼주면 이제 남은 값을 a에서부터 더해줍니다. 근데 a에서 적용하는 것은 이미 +1을 적용한 상태이므로 이를 제거해주었습니다.

그리고 String 객체안에 char 배열을 넣어주면 끝납니다~



다른사람의 풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Caesar {
    String caesar(String s, int n) {
        String result = "";
    n = n % 26;
    for (int i = 0; i < s.length(); i++) {
      char ch = s.charAt(i);
      if (Character.isLowerCase(ch)) {
        ch = (char) ((ch - 'a' + n) % 26 + 'a');
      } else if (Character.isUpperCase(ch)) {
        ch = (char) ((ch - 'A' + n) % 26 + 'A');
      }
      result += ch;
    }
        return result;
    }
 
    public static void main(String[] args) {
        Caesar c = new Caesar();
        System.out.println("s는 'a B z', n은 4인 경우: " + c.caesar("a B z"4));
    }
}
cs


알파벳이 대소문자 각각 26글자라는 점을 이용해서 26으로 나눈 나머지로 처리한 것 같습니다. 즉 1부터 a라고 할때, n을 더한 값이 27이라면 다시 a겠지요? 26으로 27을 나눈 나머지가 1이니까요! 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Caesar {
    public String caesar(String s, int _n) {
        return s.chars().map(c -> {
            int n = _n % 26;
            if (c >= 'a' && c <= 'z') {
                return 'a' + (c - 'a' + n) % 26;
            } else if (c >= 'A' && c <= 'Z') {
                return 'A' + (c - 'A' + n) % 26;
            } else {
                return c;
            }
        }).mapToObj(c -> String.valueOf((char)c))
        .reduce((a, b) -> a + b).orElse("");
    }
 
    public static void main(String[] args) {
        Caesar c = new Caesar();
        System.out.println("s는 'a B z', n은 4인 경우: " + c.caesar("a B z"4));
    }
}
cs


이건 진짜 모르겠습니다... 










댓글

Designed by JB FACTORY