소프티어 [인증평가(3차) 기출] 플레이페어 암호

박원종·2022년 11월 17일
0

Algorithm

목록 보기
6/6
post-thumbnail

소프티어 [인증평가(3차) 기출] 플레이페어 암호

개인적으로 아주 쉬운 구현문제였습니다.
별 두개를 줘도 될 것 같긴한데 아마 시간이 오래 걸려서 3개를 준 것 같습니다.
저도 문제를 푸는데 한시간 정도 소요했던 것으로 기억합니다.

🔍 풀이

1. key를 이용하여 5x5 char 배열 채우기

  • alpha 배열로 알파벳 중복 체크
  • map에 순서대로 저장하기 위해서 idx 변수를 사용
  • key 순서대로 배열에 저장했다면 아직 사용되지 않은 알파벳을 이어서 저장해준다.
0	1	2	3	4
5	6	7	8	9
10	11	12	13	14
15	16	17	18	19
20	21	22	23	24

- 위에 매겨진 번호가 idx
- 행 = idx / 5, 열 = idx % 5 
- ex) 7번째로 채울 map의 행은 7(idx) / 5 = 1 이고,
열은 7(idx) % 5 = 2 이므로 map[1][2] = 7을 만족한다
public static char[][] fillUp(String key) {
        char[][] map = new char[5][5];
        //alpha 배열로 알파벳 중복 체크
        boolean[] alpha = new boolean[26];
        alpha['J' - 'A'] = true;
		
		int idx = 0; //map에 순서대로 저장하기 위해서 idx 변수를 사용
        for (int i = 0; i < key.length(); i++) {
            int item = key.charAt(i) - 'A';
            if (alpha[item]) continue;
            alpha[item] = true;
            map[idx / 5][idx % 5] = key.charAt(i);
            idx++;
        }
		//아직 사용되지 않은 알파벳을 이어서 저장해준다.
        for (int i = 0; i < alpha.length; i++) {
            if (alpha[i]) continue;
            map[idx / 5][idx % 5] = (char) (i + 'A');
            idx++;
        }

        return map;
    }

2. 해당 배열의 알파벳 좌표 Map에 저장하기

public static Map<Character, Point> generateMap(char[][] map) {
        Map<Character, Point> points = new HashMap<>();
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                points.put(map[i][j], new Point(i, j));
            }
        }
        return points;
    }

3. 메세지 2개씩 나누기

  • Queue를 이용하여 메세지를 분할한다
  • 다음 메세지가 존재한다면(q.size() > 0)
    • c1 == q.peek(), c1 != X 경우, c2에 X를 삽입
    • c1 == q.peek(), c1 == X 경우, c2에 Q를 삽입
    • c1 != q.peek() 경우, c2에 q.poll() 삽입
  • 다음 메세지 존재 안한다면 c2에 X 삽입
public static List<String> divide(String message) {
        ArrayList<String> list = new ArrayList<>();
        Queue<Character> q = new LinkedList<>();

        for (int i = 0; i < message.length(); i++) {
            q.offer(message.charAt(i));
        }

        while (!q.isEmpty()) {
            char c1 = q.poll();

			char c2;
            if (q.size() > 0) {
                if (c1 == q.peek() && c1 != 'X') {
                    c2 = 'X';
                } else if (c1 == q.peek()) {
                    c2 = 'Q';
                } else {
                    c2 = q.poll();
                }
            } else {
                c2 = 'X';
            }
            list.add(String.valueOf(c1) + String.valueOf(c2));
        }
        return list;
    }

4. 암호화하기

  • 저장해 놓았던 좌표들을 조건(caseNum)에 따라 암호화하기
    - caseNum == 1 인 경우 : 각 문자 좌표의 오른쪽 문자로 교환
    - caseNum == 2 인 경우 : 각 문자 좌표의 아래 문자로 교환
    - caseNum == 3 인 경우 : 두 문자의 열을 바꾼곳의 문자로 교환
public static void encrypt(List<String> list, char[][] map, Map<Character, Point> points) {
        StringBuilder sb = new StringBuilder();
        for (String s : list) {
            char c1 = s.charAt(0);
            char c2 = s.charAt(1);

            Point p1 = points.get(c1);
            Point p2 = points.get(c2);
            sb.append(exchange(p1, p2, map));
        }
        System.out.println(sb.toString());
    }
    public static String exchange(Point p1, Point p2, char[][] map) {
        int caseNum = getCase(p1, p2);
        StringBuilder sb = new StringBuilder();
        if (caseNum == 1) {
            int ny = (p1.y + 1) % 5;
            sb.append(map[p1.x][ny]);
            ny = (p2.y + 1) % 5;
            sb.append(map[p2.x][ny]);
        } else if (caseNum == 2) {
            int nx = (p1.x + 1) % 5;
            sb.append(map[nx][p1.y]);
            nx = (p2.x + 1) % 5;
            sb.append(map[nx][p2.y]);
        } else {
            sb.append(map[p1.x][p2.y]);
            sb.append(map[p2.x][p1.y]);
        }
        return sb.toString();
    }
    public static int getCase(Point p1, Point p2) {
        if (p1.x == p2.x) {
            return 1;
        } else if (p1.y == p2.y) {
            return 2;
        } else {
            return 3;
        }
    }
profile
잡코딩

0개의 댓글