문제 정보
핵심
String / StringBuilder 의 문자열 가공 메서드를 잘 인지하고 있는지!
Regular Expression에 대해서도 어느정도 알아야 효율적으로 풀 수 있는 문제 (replaceAll)
풀이
class Solution {
public String solution(String new_id) {
String step1 = new_id.toLowerCase();
StringBuilder step2 = new StringBuilder();
for(int i=0; i<step1.length(); i++) {
char c = step1.charAt(i);
if(Character.isLowerCase(c) || Character.isDigit(c) || c == '-' || c == '_' || c == '.' ) {
step2.append(c);
}
}
String step3 = step2.toString().replaceAll("[.]+", ".");
StringBuilder step4 = new StringBuilder(step3);
if(step4.length() > 0 && step4.charAt(0) == '.')
step4.deleteCharAt(0);
if(step4.length() > 0 && step4.charAt(step4.length()-1) == '.')
step4.deleteCharAt(step4.length()-1);
StringBuilder step5 = (step4.length() > 0) ? step4 : step4.append("a");
StringBuilder step6 = step5;
if(step6.length() >= 16)
step6.setLength(15);
if(step6.length() > 0 && step6.charAt(step6.length()-1) == '.')
step6.deleteCharAt(step6.length()-1);
StringBuilder step7 = step6;
int lastIndex = step7.length() - 1;
while(step7.length() <= 2) {
step7.append(step7.charAt(lastIndex));
}
return step7.toString();
}
public boolean isValidId(String id) {
// Check case 1
if(id.length() < 3 || id.length() > 15) {
return false;
}
// Check case 2
for(int i=0; i<id.length(); i++) {
char c = id.charAt(i);
if(!(Character.isLowerCase(c) || Character.isDigit(c) || c == '-' || c == '_' || c == '.' )) {
return false;
}
}
System.out.println("test");
// Check case 3
if(id.indexOf(0) == '.' || id.indexOf(id.length()-1) == '.')
return false;
int countEndCharacter = 0;
for(int i=0; i<id.length(); i++) {
char c = id.charAt(i);
if(c == '.')
countEndCharacter++;
else
countEndCharacter = 0;
if(countEndCharacter == 2)
return false;
}
return true;
}
}
-> 너무 장황하게 작성한 코드인것 같다
가장 첫번째 잘못된 점은, isValidId() 라는 문제에서 요구하는 유효한 아이디인지 확인하는 규칙이 적용되었는지 판단하는 메서드를 작성했는데 실제로 제출할 때에는 이를 적용하지 않았으나 통과했다
하지만 이는 사실상 먼저 확인하면 효율적이긴 하겠지만 규칙이 적용되지 않은 테스트케이스가 많은 경우에는 굳이 확인해주지 않고 고쳐도 되기 때문에 불필요했던 메서드인것 같다
괜히 코드의 길이만 길어지는 ,,,,, 만일 적용한다면 다음과 같이 적용하면 되지 않을까 싶다
if(isValidId(new_id))
return new_id;
또한 StringBuilder / String 의 문자열 처리 메서드를 잘 인지하고 있지 못했던 것 같다
StringBuilder step2 = new StringBuilder();
for(int i=0; i<step1.length(); i++) {
char c = step1.charAt(i);
if(Character.isLowerCase(c) || Character.isDigit(c) || c == '-' || c == '_' || c == '.' ) {
step2.append(c);
}
}
이렇게 작성한 코드를
s = s.replaceAll("[^a-z0-9._-]", "");
다음과 같은 String의 replaceAll() 메서드와 Regular Expression 를 활용하여 한 줄의 코드로 작성할 수 있었다
문자열의 처음과 끝에 마침표(".") 가 존재하면 이를 삭제하는 코드를 다음과 같이 작성하였지만
if(step4.length() > 0 && step4.charAt(0) == '.')
step4.deleteCharAt(0);
if(step4.length() > 0 && step4.charAt(step4.length()-1) == '.')
step4.deleteCharAt(step4.length()-1);
s = s.replaceAll("^[.]|[.]$", "");
이러한 간단한 Regular Expression으로 처리 가능했다
그리고 자잘하게
StringBuilder step5 = (step4.length() > 0) ? step4 : step4.append("a");
문자열이 비어있는 지 확인하고, 비어있다면 "a"를 추가하는 알고리즘에서도
s = s.isEmpty() ? "a" : s;
사실 이를 기본적으로 비어있는지 확인해 주는 isEmpty() 를 사용하면 되지 않았을까 싶다
풀이를 완료하고, 다른 사람의 풀이를 봤는 데 다음과 같이 Builder Pattern을 사용하여 가독성 있고 간단하게 풀이한 분이 계셔서 출처를 남기고 가져왔다
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;
}
}
}
고찰
Regular Expression에 대하여 공부해 보기
Reference
Source Code on GitHub
댓글