개인적으로 아주 쉬운 구현문제였습니다.
별 두개를 줘도 될 것 같긴한데 아마 시간이 오래 걸려서 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;
}
}