2.TDD實現字符串排列組合

  題目地址: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即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章