| input | output |
|---|---|
| a | a000 |
| Robert | R163 |
| Ashcraft | A261 |
| Tymczak | T522 |
| Pfister | P236 |
테스트 클래스 SoundEXTest를 작성하고
Caller Create 방식으로 프로덕션 클래스인 SoundEX를 생성한다.
가장 간단한 테스트부터 실행한다.
public class SoundEXTest {
SoundEX se = new SoundEX();
@Test
public void testX() {
assertEquals("a", se.convertName("a"));
}
} |
public String convertName(String inputName) {
return "a";
} |
없음
@Test
public void testX() {
assertEquals("a", se.convertName("a"));
assertEquals("b", se.convertName("b"));
} |
가장 간단하게 통과시키는 것이므로 "b"가 들어왔을때 "b000"을 반환시키도록 한다.
public String convertName(String inputName) {
if (inputName == "b") {
return "b";
}
return "a";
} |
공백에서 중복을 찾아내면 아래와 같다.
public String convertName(String inputName) {
if (inputName == "b") {
return "b";
}
if (inputName == "a") {
return "a";
}
return "";
} |
반환값에 적절한 이름인 result를 붙여준다.
public String convertName(String inputName) {
String result = "";
if (inputName == "b") {
result = "b";
}
if (inputName == "a") {
result = "a";
}
return result;
} |
앞에 나오는 b와 a는 inputName을 붙여준 것이다.
이제 두 if문 안의 내용이 완전히 동일해졌다.
public String convertName(String inputName) {
String result = "";
if (inputName == "b") {
result = inputName;
}
if (inputName == "a") {
result = inputName;
}
return result;
} |
if문 내부의 중복을 제거한다
public String convertName(String inputName) {
String result = "";
result = inputName;
return result;
} |
실패하는 테스트 케이스를 작성할 수 없다.
일반화된 솔루션이 제작되었다고 판단한다. (1글자일 경우에)
@Test
public void testX() {
assertEquals("a", se.convertName("a"));
assertEquals("b", se.convertName("b"));
assertEquals("c", se.convertName("c"));
} |
그렇다면 2글자의 이름을 시도해본다.
doubleNameTest라는 새로운 테스트 케이스를 만든다. (테스트 케이스와 테스트 코드의 차이.. 테스트 케이스는 테스트 메소드인가?)
@Test
public void doubleNameTest() {
assertEquals("a1", se.convertName("ab"));
} |
public String convertName(String inputName) {
String result = "";
if (inputName == "ab") {
result ="a1";
} else {
result = inputName;
}
return result;
} |
아래와 같이 표현할 수 있다.
public String convertName(String inputName) {
String result = "";
if (inputName == "ab") {
result += "a";
result += "1";
} else {
result += inputName;
}
return result;
} |
반복되는 result+="0";을 반복문을 이용하여 표현한다.
public String convertName(String inputName) {
String result = "";
if (inputName == "ab") {
result += "a";
result += "1";
} else {
result += inputName;
}
return result;
} |
result에 맨 처음 더해주는 값은 inputName의 첫번째 알파벳이다.
따라서 아래와 같이 표현한다.
점점 중복의 형태를 띄고 있다.
public String convertName(String inputName) {
String result = "";
if (inputName == "ab") {
result += inputName.charAt(0);
result += "1";
} else {
result += inputName.charAt(0);
}
return result;
} |
위쪽 if문에서 result+="1";은 무엇인가
inputName의 두번째 글자인 b가 치환 요구사항에 따라 치환된 값이다.
따라서 치환 요구사항을 처리해주는 기능을 작성한다.
public String getCode(char ch) {
String result = "";
switch (ch) {
case 'b':
case 'f':
case 'p':
case 'v':
result = "1";
break;
case 'c':
case 'g':
case 'j':
case 'k':
case 's':
case 'x':
case 'z':
result = "2";
break;
case 'd':
case 't':
result = "3";
break;
case 'l':
result = "4";
break;
case 'm':
case 'n':
result = "5";
break;
case 'r':
result = "6";
break;
}
return result;
} |
public String convertName(String inputName) {
String result = "";
if (inputName == "ab") {
result += inputName.charAt(0);
result += getCode(inputName.charAt(1));
} else {
result += inputName.charAt(0);
}
return result;
} |
inputName이 2글자인 경우와 1글자인 경우로 구분한다.
public String convertName(String inputName) {
String result = "";
if (inputName.length() == 2) {
result += inputName.charAt(0);
result += getCode(inputName.charAt(1));
}
if (inputName.length() == 1) {
result += inputName.charAt(0);
}
return result;
} |
aa를 입력하면 getCode에는 모음을 변환하는 기능이 아직 없기 때문에 오류가 난다.
모음과 (h,w)는 중복 제거에서 각각 따로 처리해야 하므로 구분을 해줘야 한다.
@Test
public void doubleNameTest() {
assertEquals("a1", se.convertName("ab"));
assertEquals("a2", se.convertName("ac"));
assertEquals("a3", se.convertName("ad"));
assertEquals("aa", se.convertName("aa")); // 오류
} |
모음인지 h,w인지에 따라 따로 처리를 해줘야 되기 때문에 getCode를 모음이면 "a" (h, w)이면 "h"로 반환하도록 한다. (모음끼리 구별하거나 h,w끼리 구별하는 것은 의미가 없다)
public String getCode(char ch) {
String result = "";
switch (ch) {
case 'b':
case 'f':
case 'p':
case 'v':
result = "1";
break;
case 'c':
case 'g':
case 'j':
case 'k':
case 's':
case 'x':
case 'z':
result = "2";
break;
case 'd':
case 't':
result = "3";
break;
case 'l':
result = "4";
break;
case 'm':
case 'n':
result = "5";
break;
case 'r':
result = "6";
break;
//모음 처리
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
result = "a";
break;
//h, w 처리
case 'h':
case 'w':
result = "h";
break;
}
return result;
} |
3개의 이름을 변환 시도한다.
이름이 3개일 경우의 처리는 아직 프로덕션 코드에 없으므로 테스트 케이스는 실패한다.
@Test
public void threeNameTest() {
assertEquals("a12", se.convertName("abc"));
} |
3글자일때도 이전 방식과 동일하게 적용해준다.
3번째 글자에도 변환 과정을 동일하게 적용해준다.
public String convertName(String inputName) {
String result = "";
if (inputName.length() == 3) {
result += inputName.charAt(0);
result += getCode(inputName.charAt(1));
result += getCode(inputName.charAt(2));
}
if (inputName.length() == 2) {
result += inputName.charAt(0);
result += getCode(inputName.charAt(1));
}
if (inputName.length() == 1) {
result += inputName.charAt(0);
}
return result;
} |
getCode로 변환시키는 중복된 과정을 반복문을 이용하여 바꾸면 아래와 같다.
public String convertName(String inputName) {
String result = "";
if (inputName.length() == 3) {
result += inputName.charAt(0);
for (int i = 1; i < 3; i++) {
result += getCode(inputName.charAt(i));
}
}
if (inputName.length() == 2) {
result += inputName.charAt(0);
for (int i = 1; i < 2; i++) {
result += getCode(inputName.charAt(i));
}
}
if (inputName.length() == 1) {
result += inputName.charAt(0);
for (int i = 1; i < 1; i++) {
result += getCode(inputName.charAt(i));
}
}
return result;
} |
반복문의 최대 반복횟수는 현재 inputName의 길이와 같다.
public String convertName(String inputName) {
String result = "";
if (inputName.length() == 3) {
result += inputName.charAt(0);
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
}
if (inputName.length() == 2) {
result += inputName.charAt(0);
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
}
if (inputName.length() == 1) {
result += inputName.charAt(0);
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
}
return result;
} |
각 if문의 내부가 완전히 동일해졌으므로 통일한다.
public String convertName(String inputName) {
String result = "";
result += inputName.charAt(0);
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
return result;
} |
여러가지 케이스를 시도해봐도 실패하는 테스트 케이스를 찾을 수 없다.
따라서 치환하는 기능에 대한 일반적인 솔루션이 작성되었다고 판단한다.
@Test
public void threeNameTest() {
assertEquals("a12", se.convertName("abc"));
assertEquals("a1a", se.convertName("aba"));
assertEquals("aaa", se.convertName("aae"));
assertEquals("ahh", se.convertName("ahw"));
} |
중복을 제거하는 기능을 작성한다.
@Test
public void removeDuplicationTest() {
assertEquals("a1213", se.removeDuplication("a1122113"));
} |
public String removeDuplication(String duplicatedString) {
String result = "";
if (duplicatedString == "a1122113") {
result = "a1213";
}
return result;
} |
중복이 제거되는 기능은 아래와 같은 과정을 거친다.
public String removeDuplication(String duplicatedString) {
String result = "";
if (duplicatedString == "a1122113") {
result += "a";
result += "1";
result += "2";
result += "1";
result += "3";
}
return result;
} |
public String removeDuplication(String duplicatedString) {
String result = "";
if (duplicatedString == "a1122113") {
result += duplicatedString.charAt(0);
result += duplicatedString.charAt(1);
result += duplicatedString.charAt(3);
result += duplicatedString.charAt(5);
result += duplicatedString.charAt(7);
}
return result;
} |
public String removeDuplication(String duplicatedString) {
String result = "";
if (duplicatedString == "a1122113") {
result += duplicatedString.charAt(0);
result += duplicatedString.charAt(1);
result += duplicatedString.charAt(3);
result += duplicatedString.charAt(5);
result += duplicatedString.charAt(7);
}
return result;
} |
public String removeDuplication(String duplicatedString) {
String result = "";
if (duplicatedString == "a1122113") {
result += duplicatedString.charAt(0);
if (duplicatedString.charAt(1) != duplicatedString.charAt(0)) {
result += duplicatedString.charAt(1);
}
if (duplicatedString.charAt(3) != duplicatedString.charAt(2)) {
result += duplicatedString.charAt(3);
}
if (duplicatedString.charAt(5) != duplicatedString.charAt(4)) {
result += duplicatedString.charAt(5);
}
if (duplicatedString.charAt(7) != duplicatedString.charAt(6)) {
result += duplicatedString.charAt(7);
}
}
return result;
} |
public String removeDuplication(String duplicatedString) {
String result = "";
if (duplicatedString == "a1122113") {
result += duplicatedString.charAt(0);
if (duplicatedString.charAt(1) != duplicatedString.charAt(0)) {
result += duplicatedString.charAt(1);
}
if (duplicatedString.charAt(2) != duplicatedString.charAt(1)) {
result += duplicatedString.charAt(2);
}
if (duplicatedString.charAt(3) != duplicatedString.charAt(2)) {
result += duplicatedString.charAt(3);
}
if (duplicatedString.charAt(4) != duplicatedString.charAt(3)) {
result += duplicatedString.charAt(4);
}
if (duplicatedString.charAt(5) != duplicatedString.charAt(4)) {
result += duplicatedString.charAt(5);
}
if (duplicatedString.charAt(6) != duplicatedString.charAt(5)) {
result += duplicatedString.charAt(6);
}
if (duplicatedString.charAt(7) != duplicatedString.charAt(6)) {
result += duplicatedString.charAt(7);
}
}
return result;
} |
중복을 반복문으로 제거하면 아래와 같다.
public String removeDuplication(String duplicatedString) {
String result = "";
if (duplicatedString == "a1122113") {
result += duplicatedString.charAt(0);
for (int i = 1; i < 8; i++) {
if (duplicatedString.charAt(i) != duplicatedString
.charAt(i - 1)) {
result += duplicatedString.charAt(i);
}
}
}
return result;
} |
8은 duplicationString의 길이를 의미하므로 length로 바꿔주고
duplicationString.charAt(i-1);은 이전 문자와 비교한다는 뜻이므로
previousChar변수를 추가하여 가독성을 명확하게 한다.
public String removeDuplication(String duplicatedString) {
String result = "";
char previousChar;
if (duplicatedString == "a1122113") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.charAt(0)).charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
}
}
return result;
} |
@Test
public void removeDuplicationTest() {
assertEquals("a1213", se.removeDuplication("a1122113"));
assertEquals("a121312", se.removeDuplication("a111112221312"));
} |
이전의 코드를 그대로 써도 통과된다.
public String removeDuplication(String duplicatedString) {
String result = "";
char previousChar;
if (duplicatedString == "a111112221312") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.charAt(0)).charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
}
}
if (duplicatedString == "a1122113") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.charAt(0)).charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
}
}
return result;
} |
if문의 중복된 부분을 통합한다.
public String removeDuplication(String duplicatedString) {
String result = "";
char previousChar;
if (duplicatedString.contains("a")) {
result = "A11";
} else {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
}
}
return result;
} |
a가 들어가있을때는 뒤에 오는 문자를 붙인다.
이 기능을 따로 처리하는 구문이 없기 때문에 테스트 코드는 실패한다.
assertEquals("A11", se.removeDuplication("A1a1")); //오류 |
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a11") {
result = "A11";
}
} |
없다.
assertEquals("A11", se.removeDuplication("A1a1"));
assertEquals("A11", se.removeDuplication("A1a11")); //오류 |
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result = "A11";
}
if (duplicatedString == "A1a11") {
result = "A11";
}
} |
중복이 제거된 문자열이 나오는 과정을 하나씩 보면 아래와 같다.
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += "A";
result += "1";
result += "1";
}
if (duplicatedString == "A1a11") {
result += "A";
result += "1";
result += "1";
}
} |
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
result += duplicatedString.charAt(1);
result += duplicatedString.charAt(3);
}
if (duplicatedString == "A1a11") {
result += duplicatedString.charAt(0);
result += duplicatedString.charAt(1);
result += duplicatedString.charAt(3);
}
} |
비교 대상 문자와 비교하여 일치하지 않을때만 result에 값이 추가된다.
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
if (duplicatedString.charAt(1) != getCode(duplicatedString.toLowerCase().charAt(0)).charAt(0))
{
result += duplicatedString.charAt(1);
}
if(duplicatedString.charAt(3)!=duplicatedString.charAt(2))
{
result += duplicatedString.charAt(3);
}
}
if (duplicatedString == "A1a11") {
result += duplicatedString.charAt(0);
if (duplicatedString.charAt(1) != getCode(duplicatedString.toLowerCase().charAt(0)).charAt(0))
{
result += duplicatedString.charAt(1);
}
if(duplicatedString.charAt(3)!=duplicatedString.charAt(2))
{
result += duplicatedString.charAt(3);
}
if(duplicatedString.charAt(4)!=duplicatedString.charAt(3))
{
result += duplicatedString.charAt(4);
}
} |
가독성을 명확하게 하기 위하여 비교 대상 문자를 previousChar에 저장한다.
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
result += duplicatedString.charAt(1);
previousChar = duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(2);
if (duplicatedString.charAt(3) != previousChar) {
result += duplicatedString.charAt(3);
previousChar = duplicatedString.charAt(3);
}
}
if (duplicatedString == "A1a11") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
result += duplicatedString.charAt(1);
previousChar = duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(2);
if (duplicatedString.charAt(3) != previousChar) {
result += duplicatedString.charAt(3);
previousChar = duplicatedString.charAt(3);
}
if (duplicatedString.charAt(4) != previousChar) {
result += duplicatedString.charAt(4);
}
}
} |
아래의 코드를 보자
A1a1의 3번째 a가 나온 부분에서는 값을 더하지 않고 비교문자만 옮긴 것을 알 수 있다.
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
result += duplicatedString.charAt(1);
previousChar = duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(2); //여기는 왜 순차적으로 더해지지 않았을까?
if (duplicatedString.charAt(3) != previousChar) {
result += duplicatedString.charAt(3);
previousChar = duplicatedString.charAt(3);
}
} |
따라서 아래와 같은 코드가 생략되었다고 볼 수 있다. (A1a11도 마찬가지)
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
result += duplicatedString.charAt(1);
previousChar = duplicatedString.charAt(1);
}
if (duplicatedString.charAt(2) != 'a') { //추가
result += duplicatedString.charAt(2);
}
previousChar = duplicatedString.charAt(2);
if (duplicatedString.charAt(3) != previousChar) {
result += duplicatedString.charAt(3);
previousChar = duplicatedString.charAt(3);
}
}
if (duplicatedString == "A1a11") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
result += duplicatedString.charAt(1);
previousChar = duplicatedString.charAt(1);
}
if (duplicatedString.charAt(2) != 'a') { //추가
result += duplicatedString.charAt(2);
}
previousChar = duplicatedString.charAt(2);
if (duplicatedString.charAt(3) != previousChar) {
result += duplicatedString.charAt(3);
previousChar = duplicatedString.charAt(3);
}
if (duplicatedString.charAt(4) != previousChar) {
result += duplicatedString.charAt(4);
}
}
} |
하지만 들어온 문자가 a임에도 불구하고 여전히 비교 문자는 옮겼음을 알 수 있다.
if (duplicatedString.charAt(2) != 'a') { //추가
result += duplicatedString.charAt(2);
}
previousChar = duplicatedString.charAt(2); |
이를 통해서 비교문자를 옮기는 부분 previousChar = duplicatedString.charAt(2);은 문자가 더해지든 안더해지든 실행됨을 알 수 있다.
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
result += duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(1);
if (duplicatedString.charAt(2) != 'a') {
result += duplicatedString.charAt(2);
}
previousChar = duplicatedString.charAt(2);
if (duplicatedString.charAt(3) != previousChar) {
result += duplicatedString.charAt(3);
}
previousChar = duplicatedString.charAt(3);
}
if (duplicatedString == "A1a11") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
result += duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(1);
if (duplicatedString.charAt(2) != 'a') {
result += duplicatedString.charAt(2);
}
previousChar = duplicatedString.charAt(2);
if (duplicatedString.charAt(3) != previousChar) {
result += duplicatedString.charAt(3);
}
previousChar = duplicatedString.charAt(3);
if (duplicatedString.charAt(4) != previousChar) {
result += duplicatedString.charAt(4);
}
previousChar = duplicatedString.charAt(4);
}
} |
그리고 a를 검사하는 부분도 각 검사 구문에 동일하게 적용된다.
이제 각 if검사구문이 동일해졌음을 알 수 있다. 어서 중복을 제거하고싶다.....어서
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
if (duplicatedString.charAt(1) != 'a')
result += duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(1);
if (duplicatedString.charAt(2) != previousChar) {
if (duplicatedString.charAt(2) != 'a') {
result += duplicatedString.charAt(2);
}
}
previousChar = duplicatedString.charAt(2);
if (duplicatedString.charAt(3) != previousChar) {
if (duplicatedString.charAt(3) != 'a')
result += duplicatedString.charAt(3);
}
previousChar = duplicatedString.charAt(3);
}
if (duplicatedString == "A1a11") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.charAt(1) != previousChar) {
if (duplicatedString.charAt(1) != 'a')
result += duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(1);
if (duplicatedString.charAt(2) != previousChar) {
if (duplicatedString.charAt(2) != 'a') {
result += duplicatedString.charAt(2);
}
}
previousChar = duplicatedString.charAt(2);
if (duplicatedString.charAt(3) != previousChar) {
if (duplicatedString.charAt(3) != 'a')
result += duplicatedString.charAt(3);
}
previousChar = duplicatedString.charAt(3);
if (duplicatedString.charAt(4) != previousChar) {
if (duplicatedString.charAt(4) != 'a')
result += duplicatedString.charAt(4);
}
previousChar = duplicatedString.charAt(4);
}
} |
드디어 반복문을 이용하여 중복을 제거한다!
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
for (int i = 1; i < 4; i++) {
if (duplicatedString.charAt(i) != previousChar) {
if (duplicatedString.charAt(i) != 'a')
result += duplicatedString.charAt(i);
}
previousChar = duplicatedString.charAt(i);
}
}
if (duplicatedString == "A1a11") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
for (int i = 1; i < 5; i++) {
if (duplicatedString.charAt(i) != previousChar) {
if (duplicatedString.charAt(i) != 'a')
result += duplicatedString.charAt(i);
}
previousChar = duplicatedString.charAt(i);
}
}
} |
각 for문의 최대 반복 횟수인 4와 5는, duplicateString.length()와 같다.
if (duplicatedString.contains("a")) {
if (duplicatedString == "A1a1") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
if (duplicatedString.charAt(i) != 'a')
result += duplicatedString.charAt(i);
}
previousChar = duplicatedString.charAt(i);
}
}
if (duplicatedString == "A1a11") {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
if (duplicatedString.charAt(i) != 'a')
result += duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(i);
}
}
} |
이제 두개의 if문 내부가 완전히 동일해졌으므로 if문을 제거하고 코드를 통합한다.
if (duplicatedString.contains("a")) {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0)).charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
if (duplicatedString.charAt(i) != 'a')
result += duplicatedString.charAt(1);
}
previousChar = duplicatedString.charAt(i);
}
} |
현재 removeDuplication 메소드의 코드는 아래와 같다
public String removeDuplication(String duplicatedString) {
String result = "";
char previousChar;
if (duplicatedString.contains("a")) {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0)).charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
if (duplicatedString.charAt(i) != 'a')
result += duplicatedString.charAt(i);
}
previousChar = duplicatedString.charAt(i);
}
} else {
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
result += duplicatedString.charAt(i);
}
previousChar = duplicatedString.charAt(i);
}
}
return result;
} |
a가 포함되어 있을때와 포함되어 있지 않을때의 코드가 거의 같아졌다.
사실 a가 포함되어 있을때만 현재 문자가 a인지 검사하고 더해주는 것이므로 a가 포함되어 있지 않을때와 검사 구문이 똑같다고 할 수 있다.
따라서 두 if else 문도 통합한다.
public String removeDuplication(String duplicatedString) {
String result = "";
char previousChar;
result += duplicatedString.charAt(0);
previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) {
if (duplicatedString.charAt(i) != 'a')
result += duplicatedString.charAt(i);
}
previousChar = duplicatedString.charAt(i);
}
return result;
} |
하지만 코드를 심플하게 하는 데에는 가독성이 굉장히 중요하다고 배워왔다.
위의 코드는 과연 가독성이 좋다고 할 숫 있을까?
아니다.. if문 내부에 if문이 또 있기 때문에 생각이 굉장히 복잡해지게 된다.
따라서 우리는 가독성을 더 좋게 만들 방법에 대하여 생각해봐야 한다.
가드 클로즈라는 말을 아는가?
아래 코드에서 주석 표시한 if문은 != 논리 연산자를 이용했다.
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) != previousChar) { //여기
if (duplicatedString.charAt(i) != 'a') //여기
result += duplicatedString.charAt(i);
}
previousChar = duplicatedString.charAt(i);
} |
이것을 반대로 표현하면 아래와 같다.
아무것도 실행하지 않고 바로 previouseChar = duplicateString.charAt( i );를 실행하는 것이다. 그렇다면 이것을 좀 더 단순하게 표현한다면?
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
//아무것도 하지 않는다.
} else {
if (duplicatedString.charAt(i) == 'a') {
//아무것도 하지 않는다.
} else {
result += duplicatedString.charAt(i);
}
}
previousChar = duplicatedString.charAt(i);
} |
아래처럼 continue를 써서 건너뛴다는 것을 좀더 간단명료하게 표현할 수 있다.
이것을 가드 클로즈라고 한다.
하지만 previouseChar = duplicateString.charAt( i );은 꼭 실행되야 하기 때문에 continue문 위에 들어가야 된다. 이것은 중복 문장이다.
이것을 어떻게 해결하면 좋을까?
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
previousChar = duplicatedString.charAt(i);
continue;
}
if (duplicatedString.charAt(i) == 'a') {
previousChar = duplicatedString.charAt(i);
continue;
}
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
} |
생각해보면 현재 문자열이 이전 문자열과 같을때에는 이전 문자열이 비교 문자열에 들어가 있을 테니까 굳이 현재 문자열을 비교문자열에 넣을 필요가 없다.
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
previousChar = duplicatedString.charAt(i); //불필요하므로 생략
continue;
}
if (duplicatedString.charAt(i) == 'a') {
previousChar = duplicatedString.charAt(i);
continue;
}
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
} |
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
continue;
}
if (duplicatedString.charAt(i) == 'a') {
previousChar = duplicatedString.charAt(i);
continue;
}
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
} |
h, w에 대한 테스트 코드 작성
@Test
public void removeDuplicationTest() {
assertEquals("A1213", se.removeDuplication("A1122113"));
assertEquals("A121312", se.removeDuplication("A111112221312"));
assertEquals("A11", se.removeDuplication("A1a1"));
assertEquals("A11", se.removeDuplication("A1a11"));
//h 비교
assertEquals("A1", se.removeDuplication("A1h1"));
} |
들어온 문자열에 h가 포함되어 있을때 "A1"반환
public String removeDuplication(String duplicatedString) {
String result = "";
result += duplicatedString.charAt(0);
char previousChar = getCode(duplicatedString.toLowerCase().charAt(0))
.charAt(0);
if (duplicatedString.contains("h")) {
result = "A1";
} else {
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
continue;
}
if (duplicatedString.charAt(i) == 'a') {
previousChar = duplicatedString.charAt(i);
continue;
}
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
}
return result;
} |
A1h1에서 A1이 나온 이유는 무엇일까?
h는 a와 똑같은 원리로 사라질 것이다.
하지만 h뒤에 나오는 1이 사라진 이유는?
h전에 나왔던 1과 비교를 한 것이다.
그렇다면 h가 나왔을때 비교대상 문자열을 옮기지 않았다는 것이다.
a였을때의 처리 코드를 그대로 가져와서 'h'와 비교하는 부분과 비교문자열을 옮기는 부분을 수정했다.
if (duplicatedString.contains("h")) {
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
continue;
}
if (duplicatedString.charAt(i) == 'h') {
// previousChar = duplicatedString.charAt(i);
continue;
}
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
} |
이제 두 소스의 형태가 비슷해졌다.
if (duplicatedString.contains("h")) {
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
continue;
}
if (duplicatedString.charAt(i) == 'h') {
continue;
}
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
} else {
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
continue;
}
if (duplicatedString.charAt(i) == 'a') {
previousChar = duplicatedString.charAt(i);
continue;
}
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
} |
두 if문을 합친다.
이렇게 중복을 제거하는 기능도 완료되었다.
public String removeDuplication(String duplicatedString) {
String result = "";
result += duplicatedString.charAt(0);
char previousChar = getCode(duplicatedString.toLowerCase().charAt(0)).charAt(0);
for (int i = 1; i < duplicatedString.length(); i++) {
if (duplicatedString.charAt(i) == previousChar) {
continue;
}
if (duplicatedString.charAt(i) == 'a') {
previousChar = duplicatedString.charAt(i);
continue;
}
if (duplicatedString.charAt(i) == 'h') {
continue;
}
result += duplicatedString.charAt(i);
previousChar = duplicatedString.charAt(i);
}
return result;
} |
converName() 메소드에 방금 완성한 중복 제거 기능을 추가시킨다.
public String convertName(String inputName) {
String result = "";
result += inputName.charAt(0);
inputName = inputName.toLowerCase();
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
result = removeDuplication(result);
return result;
} |
이제 완성된 이름을 4글자로 잘라야 한다.
완성된 이름이 4글자가 안되면 0을 붙인다.
N360이 나와야 하는데 N36이 나온다.
@Test
public void cutNameTest()
{
assertEquals("N360", se.convertName("Nethru"));
} |
public String convertName(String inputName) {
String result = "";
result += inputName.charAt(0);
inputName = inputName.toLowerCase();
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
result = removeDuplication(result);
if (result.length() == 3) {
result += "0";
}
return result;
} |
4글자를 채워야 하므로 결과값의 길이에 따라 0을 더해준다.
public String convertName(String inputName) {
String result = "";
result += inputName.charAt(0);
inputName = inputName.toLowerCase();
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
result = removeDuplication(result);
if (result.length() == 3) {
result += "0";
}
if (result.length() == 2) {
result += "0";
result += "0";
}
if (result.length() == 1) {
result += "0";
result += "0";
result += "0";
}
return result;
} |
중복이 보이지만 아직 한가지 케이스가 더 남아 있으므로 중복 제거를 잠시 보류한다.
그것은 결과값이 4보다 큰 경우이다.
H435이 나와야 하지만 H4536이 나온다 (4보다 크다)
@Test
public void cutNameTest() {
assertEquals("N360", se.convertName("Nethru")); // 문자열의 길이가 4보다 짧을때
assertEquals("H453", se.convertName("HelloNethru")); // 문자열의 길이가 4보다 클때
} |
길이가 4보다 길면 현재에서 4번째 길이까지만 반환한다.
public String convertName(String inputName) {
String result = "";
result += inputName.charAt(0);
inputName = inputName.toLowerCase();
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
result = removeDuplication(result);
if (result.length() == 3) {
result += "0";
}
if (result.length() == 2) {
result += "0";
result += "0";
}
if (result.length() == 1) {
result += "0";
result += "0";
result += "0";
}
if (result.length() > 4) {
result = result.substring(0, 4);
}
return result;
} |
공백에서 중복을 발견하면 아래와 같다.
public String convertName(String inputName) {
String result = "";
result += inputName.charAt(0);
inputName = inputName.toLowerCase();
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
result = removeDuplication(result);
if (result.length() == 3) {
result += "0";
result = result.substring(0, 4);
}
if (result.length() == 2) {
result += "0";
result += "0";
result = result.substring(0, 4);
}
if (result.length() == 1) {
result += "0";
result += "0";
result += "0";
result = result.substring(0, 4);
}
if (result.length() > 4) {
result += "0";
result += "0";
result += "0";
result = result.substring(0, 4);
}
return result;
} |
중복을 제거하면 아래와 같다.
public String convertName(String inputName) {
String result = "";
result += inputName.charAt(0);
inputName = inputName.toLowerCase();
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
result = removeDuplication(result)+"000";
result = result.substring(0, 4);
return result;
} |
이름의 길이를 조절하는 기능은 별개로 adjustNameLength()라는 메소드로 따로 뽑는다.
public String convertName(String inputName) {
String result = "";
result += inputName.charAt(0);
inputName = inputName.toLowerCase();
for (int i = 1; i < inputName.length(); i++) {
result += getCode(inputName.charAt(i));
}
result = adjustNameLength(result);
return result;
}
private String adjustNameLength(String result) {
result = removeDuplication(result) + "000";
result = result.substring(0, 4);
return result;
} |
실패하는 테스트 케이스를 작성할 수 없다.
따라서 일반화된 솔루션이 작성되었다고 판단한다.
@Test
public void finalTest() {
assertEquals("R163", se.convertName("Robert"));
assertEquals("A261", se.convertName("Ashcraft"));
assertEquals("T522", se.convertName("Tymczak"));
assertEquals("P236", se.convertName("Pfister"));
} |
| [Json] 왜 Json을 쓰는가 (0) | 2015.12.06 |
|---|---|
| [데이터 마이닝] 데이터마이닝의 개념 및 어떤 것들이 있는지 알아보자 (0) | 2015.12.06 |
| [Git] Git 기본 명령어 요약정리 (0) | 2015.12.06 |
| [Cucumber] 시나리오 Java 코드로 변환하기 (계좌 예금 및 계좌이체하기) (0) | 2015.12.06 |
| [Cucumber] Scenario Outline 기법을 활용하여 시나리오 중복 제거하기 (0) | 2015.12.06 |
댓글 영역