題目地址:http://cyber-dojo.org/setup_default_start_point/show/?from=individual , 第二題。題目如下:
Write a program to generate all potential anagrams of an input string.For example, the potential anagrams of “biro” are
biro bior brio broi boir bori
ibro ibor irbo irob iobr iorb
rbio rboi ribo riob roib robi
obir obri oibr oirb orbi orib
說白了就是給定一個字符串進行排列組合。咋一看確實很難做,有點難度。**這裏我們一步步剖析TDD的實現。讓你清清楚楚明白TDD。**TDD實現這個題目是水到渠成的。
一、TDD之前我們先建立兩個類:test和要解決上述問題的答案代碼
我們先建立測試類,也建立調用的方法。
測試類AnagramsTest框架:
public class AnagramsTest {
@Test
public void testOnlyOneLetter() {
//given
//when
//then
}
}
業務類AnagramsProblem 框架:
public class AnagramsProblem {
public List<String> getAnagrams(String givenString) {
return null;
}
}
二、當只有一個字母的時候
當傳入的字符串只有一個字符時,代碼如下:
測試類:
public class AnagramsProblemTest {
@Test
public void testOnlyOneLetter() {
//given(入參)
String strGiven = "b";
//引用anagramsProblem指向新AnagramsProblem對象,使用引用調用 排列組合 的實現方法
AnagramsProblem anagramsProblem = new AnagramsProblem();
//when(調用方法)
List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
//then(驗證)
Assert.assertEquals(Arrays.asList("b"), strReturn);
}
}
業務類:
public class AnagramsProblem {
public List<String> getAnagrams(String givenString) {
List<String> strList = new ArrayList<>();//java 1.8 新特性
strList.add(givenString);
return strList;
}
}
運行測試代碼,成功,說明返回值跟預期的一樣。
三、當有兩個字母的時候
測試類:
public class AnagramsProblemTest {
@Test
public void testOnlyOneLetter() {
//given(入參)
String strGiven = "b";
AnagramsProblem anagramsProblem = new AnagramsProblem();
//when(調用方法)
List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
//then(驗證)
Assert.assertEquals(Arrays.asList("b"), strReturn);
}
@Test
public void testTwoLetters() {
//given
String strGiven = "bi";
AnagramsProblem anagramsProblem = new AnagramsProblem();
//when
List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
//then
Assert.assertEquals(Arrays.asList("bi", "ib"), strReturn);
}
}
業務類:
public class AnagramsProblem {
public List<String> getAnagrams(String givenString) {
List<String> strList = new ArrayList<>();//java 1.8 新特性
if(givenString.length() == 1) {
strList.add(givenString);
return strList;
}
if(givenString.length() == 2) {
strList.add("" + givenString.charAt(0) + givenString.charAt(1));
strList.add("" + givenString.charAt(1) + givenString.charAt(0));
return strList;
}
return null;
}
}
三、當有三個字母的時候
測試類:
package cs.anagrams;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
public class AnagramsProblemTest {
@Test
public void testOnlyOneLetter() {
//given(入參)
String strGiven = "b";
AnagramsProblem anagramsProblem = new AnagramsProblem();
//when(調用方法)
List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
//then(驗證)
Assert.assertEquals(Arrays.asList("b"), strReturn);
}
@Test
public void testTwoLetters() {
//given
String strGiven = "bi";
AnagramsProblem anagramsProblem = new AnagramsProblem();
//when
List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
//then
Assert.assertEquals(Arrays.asList("bi", "ib"), strReturn);
}
@Test
public void testThreeLetters() {
//given
String strGiven = "bir";
AnagramsProblem anagramsProblem = new AnagramsProblem();
/** 這裏需要排序,不然他會按順序比較指定位置的字符串,可能會出錯 */
List<String> strExpect = Arrays.asList("bir", "bri", "ibr", "irb", "rbi", "rib");
Collections.sort(strExpect);
//when
List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
Collections.sort(strReturn);
//then
Assert.assertEquals(strExpect, strReturn);
}
}
業務類:
package cs.anagrams;
import java.util.ArrayList;
import java.util.List;
public class AnagramsProblem {
public List<String> getAnagrams(String givenString) {
List<String> strList = new ArrayList<>();//java 1.8 新特性
if(givenString.length() == 1) {
strList.add(givenString);
return strList;
}
if(givenString.length() == 2) {
//重複代碼
strList.add("" + givenString.charAt(0) + givenString.charAt(1));
strList.add("" + givenString.charAt(1) + givenString.charAt(0));
return strList;
}
if(givenString.length() == 3) {
//重複代碼
strList.add("" + givenString.charAt(0) + givenString.charAt(1) + givenString.charAt(2));
strList.add("" + givenString.charAt(0) + givenString.charAt(2) + givenString.charAt(1));
strList.add("" + givenString.charAt(1) + givenString.charAt(0) + givenString.charAt(2));
strList.add("" + givenString.charAt(1) + givenString.charAt(2) + givenString.charAt(0));
strList.add("" + givenString.charAt(2) + givenString.charAt(0) + givenString.charAt(1));
strList.add("" + givenString.charAt(2) + givenString.charAt(1) + givenString.charAt(0));
return strList;
}
return null;
}
}
找規律:
if(givenString.length() == 3) {
String str = givenString.replace(givenString.charAt(0) + "", "");
strList.add("" + givenString.charAt(0) + givenString.charAt(1) + givenString.charAt(2));
strList.add("" + givenString.charAt(0) + givenString.charAt(2) + givenString.charAt(1));
String str1 = givenString.replace(givenString.charAt(1) + "", "");
strList.add("" + givenString.charAt(1) + givenString.charAt(0) + givenString.charAt(2));
strList.add("" + givenString.charAt(1) + givenString.charAt(2) + givenString.charAt(0));
String str2 = givenString.replace(givenString.charAt(2) + "", "");
strList.add("" + givenString.charAt(2) + givenString.charAt(0) + givenString.charAt(1));
strList.add("" + givenString.charAt(2) + givenString.charAt(1) + givenString.charAt(0));
return strList;
}
重構代碼:
if(givenString.length() == 3) {
for (int i = 0; i < givenString.length(); i++) {
String str = givenString.replace(givenString.charAt(i) + "", "");
strList.add("" + givenString.charAt(i) + str.charAt(0) + str.charAt(1));
strList.add("" + givenString.charAt(i) + str.charAt(1) + str.charAt(0));
}
return strList;
}
查找規律:
if(givenString.length() == 3) {
for (int i = 0; i < givenString.length(); i++) {
String str = givenString.replace(givenString.charAt(i) + "", "");
strList.add("" + givenString.charAt(i) + getAnagrams(str).get(0));
strList.add("" + givenString.charAt(i) + getAnagrams(str).get(1));
}
return strList;
}
再次重構givenString.length() == 3的代碼,去掉重複代碼,抽方法,inline代碼:
if(givenString.length() == 3) {
for (int i = 0; i < givenString.length(); i++) {
for (int j = 0; j < getAnagrams(getRemaindString(givenString, i)).size(); j++) {
strList.add("" + givenString.charAt(i) + getAnagrams(getRemaindString(givenString, i)).get(j));
}
}
return strList;
}
最終如下:
package cs.anagrams;
import java.util.ArrayList;
import java.util.List;
public class AnagramsProblem {
public List<String> getAnagrams(String givenString) {
List<String> strList = new ArrayList<>();//java 1.8 新特性
if(givenString.length() == 1) {
strList.add(givenString);
return strList;
}
if(givenString.length() == 2) {
strList.add("" + givenString.charAt(0) + givenString.charAt(1));
strList.add("" + givenString.charAt(1) + givenString.charAt(0));
return strList;
}
if(givenString.length() == 3) {
for (int i = 0; i < givenString.length(); i++) {
for (int j = 0; j < getAnagrams(getRemaindString(givenString, i)).size(); j++) {
strList.add("" + givenString.charAt(i) + getAnagrams(getRemaindString(givenString, i)).get(j));
}
}
return strList;
}
return null;
}
private String getRemaindString(String givenString, int i) {
return givenString.replace(givenString.charAt(i) + "", "");
}
}
四、當有四個字母的時候
測試方法:
@Test
public void testFourLetters() {
//given
String strGiven = "biro";
AnagramsProblem anagramsProblem = new AnagramsProblem();
List<String> exceptStr = Arrays.asList("biro", "bior", "brio", "broi", "boir", "bori",
"ibro", "ibor", "irbo", "irob", "iobr", "iorb",
"rbio", "rboi", "ribo", "riob", "roib", "robi",
"obir", "obri", "oibr", "oirb", "orbi", "orib");
Collections.sort(exceptStr);
//when
List<String> strReturn = anagramsProblem.getAnagrams(strGiven);
Collections.sort(strReturn);
//then
Assert.assertEquals(exceptStr, strReturn);
}
業務語句:
if(givenString.length() == 4) {
for (int i = 0; i < givenString.length(); i++) {
for (int j = 0; j < getAnagrams(getRemaindString(givenString, i)).size(); j++) {
strList.add("" + givenString.charAt(i) + getAnagrams(getRemaindString(givenString, i)).get(j));
}
}
return strList;
}
五、當有N個字母的時候
業務類,抽共性:
package cs.anagrams;
import java.util.ArrayList;
import java.util.List;
public class AnagramsProblem {
public List<String> getAnagrams(String givenString) {
List<String> strList = new ArrayList<>();//java 1.8 新特性
if(givenString.length() == 1) {
strList.add(givenString);
return strList;
}
if(givenString.length() >= 2) {
for (int i = 0; i < givenString.length(); i++) {
for(int j = 0; j < getAnagrams(getRemaindString(givenString, i)).size(); j++)
strList.add("" + givenString.charAt(i) + getAnagrams(getRemaindString(givenString, i)).get(j));
}
return strList;
}
return null;
}
private String getRemaindString(String givenString, int i) {
return givenString.replace(givenString.charAt(i) + "", "");
}
}
六、去掉重複字符
使用set代替List即可