[java] 정올 - 전화번호 속의 암호
업데이트:
문제
정올 - 전화번호 속의 암호
숫자 더미를 가지고 주어진 조건에 따라서 암호를 만드는 문제
< 처리조건 >
(1) 핸드폰 번호, 각 자리에 더해질 숫자, 숫자 더미의 위치를 입력받는다.
(2) 입력된 핸드폰 번호에서, 각 숫자 더미사이의 구분은 하이픈(-)으로 하고, 번호는 0이상 9이하의 자연수만 들어온다.
(3) 숫자 더미는 앞에서부터 자동적으로 1번부터 매겨지며, 그 수의 제한은 없다.
즉 반드시 abc-defg-hijk 형태의 3개의 숫자더미를 가지는 전화번호만이 있는 것은 아니다.
(4) 원하는 숫자더미에서 각 자리의 숫자를 더한다. 이때 더한 값이 9를 넘을 경우에는 그 중 일의 자리 값만을 취한다.
(5) 각 숫자더미는 4자리를 넘어서는 안된다.
(6) 각 숫자 더미의 크기가 4자리가 안될 경우에는 전체를 4자리로 한 후, 앞에 그 비는 자리 수만큼 0을 붙인다.
-
제한 사항
전화번호를 기억할 스트링 s : 100자 이내
각 자리에 더해질 숫자 p : 1 <=p
<= 9 -
예시
입력 :111-2222-3412-5432 2 4
s = “111-2222-3412-5432”
p = 2
m = 4
우선 m번째 숫자더미는 앞에서부터 1이므로 5432
이다
각 숫자에 p를 더하는데 9를 넘어가는 경우 일의 자리만 남긴다
5
+ 2 = 7
4
+ 2 = 6
3
+ 2 = 5
2
+ 2 = 4
만약에 8
+ 2였다면 10을 뺀 0이 되어야 한다
=> 예시 답 : 5432
풀이
음 ~ 처음에 쉬운 줄 알았는데 푸는데 짜증나 죽는줄알았음..
물론 내가 반례나 그런 여러 예외상황을 제껴버리고 내맘대로 막장코딩을 해서 그렇긴 하지만,, 후 ^^
다각도에서 생각해야한다는 것을 느끼게 해주는 문제였다
입력 문자열 처리
입력받은 문자열을 숫자더미로 쪼개기 위해서 ‘-‘를 기준으로 split한다
이때 s = 3232-
처럼 자릿수가 없는 숫자더미를 입력받았을 때
s.split("-")
를 하면 원하는 결과인 [3232, ]
를 얻을 수 없다
그냥 [3232]
로 끝나버리기때문에, s의 마지막 char가 ‘-‘라면 ‘0’을 덧붙여줬다
Split 한 이후 처리
split한 다음, 숫자더미가 알맞게 갈라졌으면
4자리를 넘는 수가 있는지 확인해야 한다
쪼갠 각각의 숫자더미의 크기가 4자리를 넘어선 안된다. (조건 5)
split한 배열을 반복하면서 4자리가 넘는다면 그냥 에러출력하고 종료
m번째 숫자더미에 p를 더하기
1) 자릿수가 4자리인 경우
위에서 String으로 숫자를 저장해놨기 때문에
char를 순환하면서 p(더해야 하는 수)를 더해준다
이때 선택한 숫자더미 : “1234”, p : 7 이라면
“1234”를 1부터 4까지 char단위로 반복한다
연산할 때 1은 char형의 ‘1’이므로 그냥 p를 더하면 안된다
‘1’ - ‘0’ 이런식으로 먼저 연산을 통해 int형으로 변환 후 p와 연산을 해줘야 원하는 결과가 나온다
또한 문제 조건에 따라 '4' - '0' + p
를 하면 11이 나오므로 1의 자리인 1을 결과에 반영해야한다
-> ('4' - '0' + p) %10
2) 자릿수가 4자리보다 작은 경우
4자리보다 작다면, 앞에 0을 붙여서 4자리로 만들어준다(조건 6)
예를들어, 숫자더미의 자릿수가 3개인 [222]라면,
0을 앞에 붙여서 [0222]로 만들어줘야한다
숫자더미의 자릿수가 0이라면[], [0000]이 되어야 한다
고냥 4자리 - 현재 자릿수만큼 p를 StringBuilder에 추가하고,
나머지 자릿수에 대해서 (num.charAt(i) - '0' + p ) % 10
해주면 된다
시행착오
심지어 3개
음 나의 시행착오가 무려 3 + a인 것 같은데 적어보자면
1) 배열의 크기, index문제
입력받은 문자열이 1-2-3-4-5
라고 하면 나는 이걸 ‘-‘를 기준으로 split했다
String [] tmp = [1, 2, 3, 4, 5]
이런식으로 놓고 m번째 숫자를 불러왔는데
m이 배열의 크기를 넘어가면 안되는데 그 검사에서 <=
해야되는걸 <
로 해버려서 범위오류났음..
이런 기본적인 실수를 할 줄이야 ^^..
2) 조건 이해를 잘못함(문제 이해 부족)
조건 (5)에서 각 숫자더미는 4자리를 넘어서는 안된다. 라고 명시되어있다
근데 나는 tmp[m] (연산해야하는 대상)만 4자리 초과면 오류를 출력하게 했는데,
그냥 연산 상관없이 4자리가 넘으면 “INPUT ERROR!”를 출력하게 해야했다
그러니까 “111
-222222
-3
2 4” 에서 나는 마지막 숫자더미인 3
에 4(M=4)을 이용해서 암호를 만들어야하지만,
입력받은 숫자더미 중 “2222222
“이 자릿수에서 조건을 만족하지 않기때문에 그냥 에러를 반환해야한다
3) 그냥 생각이 짧았음
문제 이해와도 관련이 있는데 조건(6)에서 각 숫자 더미의 크기가 4자리가 안될 경우에는 전체를 4자리로 한 후, 앞에 그 비는 수만큼 0을 붙인다. 라고 명시되어있다.
않이,, 나는 이게 3
이면 0003
이렇게 앞에 0을 추가해서 4자리를 만드는거라고 생각했는데,(물론 맞음)
ㅤ
일때 0000
을 만드는 것인줄은 생각치도 못했다..ㄴㅇㄱ
정올 장점인 틀린 테케 확인에서 봤는데
입력 : 0-6-6-6-5-121-1-5854- 3 9
(답 : 3333) 이걸 확인하고나서야 제대로 문제를 이해한 것 같다.. 자릿수가 0인 경우도 생각을 해야했는데..
마찬가지로 0-6-6-6-5-121-1-5854-- 3 10
도 마찬가지다
s = 0-6-6-6-5-121-1-5854--
를 모든 자리에 0을 붙여 4자리를 만든다면,
0000-0006-0006-0006-0005-0121-0001-5854-0000-0000
이렇게 !!
약간 여러모로 배신당한 기분이면서도 내가 너무 단순하게만 풀려고 하는구나 싶고 복합적인 기분을 느끼게 하는 문제였다..
소스코드
import java.io.*;
import java.util.*;
public class j1620_전화번호속의암호 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
String input = st.nextToken();
if (input.charAt(input.length() - 1) == '-') // 마지막자리 -인지 확인
input += "0";
String[] tmp = input.split("-");
for (int i = 0; i < tmp.length; i++) {
int len = tmp[i].length();
if (len > 4) { // 4자리 넘는거 있으면 종료
System.out.println("INPUT ERROR!");
return;
}
}
int p = Integer.parseInt(st.nextToken()); // 각 자리에 더해질 숫자
int m = Integer.parseInt(st.nextToken()) - 1; // 숫자 더미의 번호
// m이 숫자더미 길이를 벗어날 경우
if (tmp.length <= m) {
System.out.println("INPUT ERROR!");
return;
}
StringBuilder sb = new StringBuilder();
// 0 채우기
for (int j = 0; j < 4 - tmp[m].length(); j++) {
sb.append(p);
}
for (int i = 0; i < tmp[m].length(); i++) {
int tp = tmp[m].charAt(i) - '0' + p;
sb.append(tp % 10);
}
System.out.println(sb.toString());
}
}
댓글남기기