문제 설명
카카오에 입사한 신입 개발자 네오는 "카카오계정개발팀"에 배치되어, 카카오 서비스에 가입하는 유저들의 아이디를 생성하는 업무를 담당하게 되었습니다. "네오"에게 주어진 첫 업무는 새로 가입하는 유저들이 카카오 아이디 규칙에 맞지 않는 아이디를 입력했을 때, 입력된 아이디와 유사하면서 규칙에 맞는 아이디를 추천해주는 프로그램을 개발하는 것입니다.
다음은 카카오 아이디의 규칙입니다.
- 아이디의 길이는 3자 이상 15자 이하여야 합니다.
- 아이디는 알파벳 소문자, 숫자, 빼기(``), 밑줄(_), 마침표(.) 문자만 사용할 수 있습니다.
- 단, 마침표(.)는 처음과 끝에 사용할 수 없으며 또한 연속으로 사용할 수 없습니다.
"네오"는 다음과 같이 7단계의 순차적인 처리 과정을 통해 신규 유저가 입력한 아이디가 카카오 아이디 규칙에 맞는 지 검사하고 규칙에 맞지 않은 경우 규칙에 맞는 새로운 아이디를 추천해 주려고 합니다.
신규 유저가 입력한 아이디가 new_id 라고 한다면,
1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다. 2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다. 3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다. 4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다. 5단계 new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다. 6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다. 만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다. 7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복
이 문제는 정규표현식을 잘 활용하면 코드가 단순해진다.
나는 그것도 모르고 열심히 머리를 굴렸다. 뭐 코딩테스트 공부하는 과정이니까 시간이 아깝지는 않다..(정말로!)
class Solution {
public String solution(String new_id) {
String answer = "";
new_id = new_id.toLowerCase();
new_id = new_id.replaceAll("[^a-z0-9-_.]", "");
new_id = checkContinuous(new_id);
new_id = check_forth(new_id);
new_id = check_forth2(new_id);
if(new_id.isBlank()){
new_id = "aaa";
}
if(new_id.length() < 3){
char addChar = new_id.charAt(new_id.length() - 1);
while (new_id.length() < 3){
new_id += addChar;
}
}
if(new_id.length()>15){
new_id = new_id.substring(0,15);
}
new_id = check_forth2(new_id);
answer = new_id;
return answer;
}
static public String checkContinuous(String new_id) {
new_id.replace("..",".");
while (new_id.contains("..")){
new_id = new_id.replace("..",".");
}
return new_id;
}
public static String check_forth(String new_id) {
while (!new_id.isEmpty() && new_id.charAt(0) == '.') {
new_id = new_id.substring(1);
}
return new_id;
}
public static String check_forth2(String new_id) {
while (!new_id.isEmpty() && new_id.charAt(new_id.length() - 1) == '.') {
new_id = new_id.substring(0, new_id.length() - 1);
}
return new_id;
}
}
제출은 이 코드로 했는데 메서드 이름을 다시 정하고 분리를 해야겠다.
import java.util.ArrayList;
public class pro_0104 {
public static void main(String[] args) {
Solution solution = new Solution();
String new_id = "...!@BaT#*..y.abcdefghijklm";
String new_id2 = "z-+.^.";
String new_id3 = "=.=";
String new_id4 = "123_.def";
String new_id5 = "abcdefghijklmn.p";
String result = solution.solution(new_id);
System.out.println(result);
String result3 = solution.solution(new_id3);
System.out.println(result3);
}
static class Solution {
public String solution(String new_id) {
new_id = new_id.toLowerCase();
new_id = new_id.replaceAll("[^a-z0-9-_.]", "");
new_id = onlyDot(new_id);
new_id = checkFirstDot(new_id);
new_id = checkLastDot(new_id);
new_id = checkBlank(new_id);
new_id = checkMin(new_id);
new_id = checkMax(new_id);
new_id = checkLastDot(new_id);
return new_id;
}
private String onlyDot(String s) {
s.replace("..", ".");
while (s.contains("..")) {
s = s.replace("..", ".");
}
return s;
}
private String checkFirstDot(String s) {
while (!s.isEmpty() && s.charAt(0) == '.') {
s = s.substring(1);
}
return s;
}
private String checkLastDot(String s) {
while (!s.isEmpty() && s.charAt(s.length() - 1) == '.') {
s = s.substring(0, s.length() - 1);
}
return s;
}
private String checkBlank(String s) {
if (s.isBlank()) {
s = "aaa";
}
return s;
}
private String checkMin(String s) {
if (s.length() < 3) {
char addChar = s.charAt(s.length() - 1);
while (s.length() == 3) {
s += addChar;
}
}
return s;
}
private String checkMax(String s) {
if (s.length() > 15) {
s = s.substring(0, 15);
}
return s;
}
}
}
지난 우테코 6기를 지원할 때 미션 규칙들을 떠올려가며 적용하려 했다. 그때만큼 복잡하지는 않지만 최대한 규칙을 신경쓰려 노력했다.
다른 사람들의 답변
class Solution {
public String solution(String new_id) {
String s = new KAKAOID(new_id)
.replaceToLowerCase()
.filter()
.toSingleDot()
.noStartEndDot()
.noBlank()
.noGreaterThan16()
.noLessThan2()
.getResult();
return s;
}
private static class KAKAOID {
private String s;
KAKAOID(String s) {
this.s = s;
}
private KAKAOID replaceToLowerCase() {
s = s.toLowerCase();
return this;
}
private KAKAOID filter() {
s = s.replaceAll("[^a-z0-9._-]", "");
return this;
}
private KAKAOID toSingleDot() {
s = s.replaceAll("[.]{2,}", ".");
return this;
}
private KAKAOID noStartEndDot() {
s = s.replaceAll("^[.]|[.]$", "");
return this;
}
private KAKAOID noBlank() {
s = s.isEmpty() ? "a" : s;
return this;
}
private KAKAOID noGreaterThan16() {
if (s.length() >= 16) {
s = s.substring(0, 15);
}
s = s.replaceAll("[.]$", "");
return this;
}
private KAKAOID noLessThan2() {
StringBuilder sBuilder = new StringBuilder(s);
while (sBuilder.length() <= 2) {
sBuilder.append(sBuilder.charAt(sBuilder.length() - 1));
}
s = sBuilder.toString();
return this;
}
private String getResult() {
return s;
}
}
}
위 코드를 확인해보면 정규표현식을 사용해서 코드가 깔끔해졌고 메서드 이름이 분명해보인다.
정규표현식을 따로 정리할까 하다가 이미 정리된 좋은 글들이 많기 때문에 생략하기로 했다.
https://hamait.tistory.com/342
정규표현식 (Regex) 정리
정규표현식은 아주 가끔 쓰기때문에 항상 다시 볼때마다 헷갈리곤 하기에 주요 사용예를 내가 나중에 다시 봤을 때 편하도록 정리하여 보았다. 정규 표현식의 용어들정규 표현식에서 사용되는
hamait.tistory.com
코딩테스트 문제를 풀면 풀 수록 우아한테크코스 6기 프리코스에서 얼마나 부족했는지 알게된다.

하핫 이런 좋은 정규표현식을 활용할 줄도 몰랐던 나.. 오늘도 배워갑니다. 꾸벅
'문제풀기 > 프로그래머스 문풀' 카테고리의 다른 글
[프로그래머스] 실패율 (1) | 2025.01.14 |
---|---|
SQL 이진수로 바꾸는 문법 BIN (0) | 2024.12.30 |
[프로그래머스] 작은수, 자료형 크기 (1) | 2023.10.18 |
[프로그래머스] 카드뒤집기 (0) | 2023.10.11 |
[프로그래머스] HashMap을 익혀야해 (1) | 2023.10.07 |