结对编程 - 马尔科夫链

需求分析

  • 程序能够从文件中读取文章,且具备学习能力
  • 建立前后缀之间的关系
  • 控制文章输出的篇幅(字数)
  • 随机生成文章

做题思路(设计思路&解决问题)

一、程序且具备学习能力

结合参考文章的思路:利用连续两个词构成的前缀来选择作为后缀的一个词
设置w1和w2为文本的前两个词
输出w1和w2
循环:
随机地选出w3,它是文本中w1w2的后缀中的一个
打印w3
把w1和w2分别换成w2和w3
重复循环

    "this is" -> ["a"]
    "is a" -> ["good", "dog"]
    "a dog" -> ["and", "where"]
    "dog and" -> ["it", "this"]
  • 由此,第一个问题和难点来了,如何做前缀和后缀,用什么方式去做?

  • 解决过程(一):

  • 首先,在课程开始的时候我在追看这位老兄写的博客,曾经关于封装,继承,多态的理解他给了我很大帮助.
    在Java提高篇(二三)后讲到了Map的实现,产生key-value键对值,将键映射到值的对象。
    这样就满足了根据w1w2选择出w3。
  • 然后,决定用List<> 来作为前缀的容器。
  • 解决过程(二):
    //前缀用一个类来表示:
    public class Front
    //首先得有保存前缀的基本属性:
                            public List<String> pref;    //前缀保存的两个词,w1,w2按顺序存入
    //对于一篇文章,程序每读一个单词,程序就会重复以下步骤:
                            add(word);
    private void add(String word) {  
        List<String> suf = stateTable.get(prefix);  
        if(suf == null){  
            suf = new ArrayList<String>();  
            stateTable.put(new Prefix(prefix),suf);  //Map<Front,List<String>> stateTable = new HashMap<Front,List<String>>();
        }  
        
        Front.pref.remove(0);  
        Front.pref.add(word);  
    }  

二、随机生成文章和控制输出篇幅

  • 已经建立了前后缀之间的映射关系,只需要建立循环Num次
   FileWriter fw = new FileWriter(*.txt);  
    

    for(int i=0; i<Num; i++){  
            List<String> suf = stateTable.get(prefix);  
            int r = Math.abs(random.nextInt() % suf.size());  
            String word = suf.get(r);  
            System.out.print(word+" "); 
            if(word.equals(".")){
                fw.write("\n");
            }
            else
                fw.write(word+" "); 
            prefix.pref.remove(0);  
            prefix.pref.add(word);  
        }  
            
            fw.close;

三、程序读取文章

  • 这个确实不是什么大问题,解决过程如下:
    FileInputStream fis = new FileInputStream(new File("C:/*/*.txt"));
    Scanner scanner = new Scanner(InputStream in); 
    while(scanner.hasNext()){  
            add(scanner.next());  
        }  

关键代码解释(通过注释解释)

    public class Chain {  
            static final int NPREF = 2; //size of prefix                          //因为是利用两个词来构成前缀,所以定义了Front的构造函数Pront(int a,String b),所以这里a=2;b一开始为"\n" 
            static final String NOWORD = "\n";                                      
            Map<Front,List<String>> stateTable = new HashMap<Front,List<String>>();        
            Front prefix = new Front(NPREF,NOWORD);  
            Random random = new Random();                            //用于产生随机数           
    public void build(InputStream in) throws Exception {    
        Scanner scanner = new Scanner(in);                  //读取文件
          
        while(scanner.hasNext()){  
            add(scanner.next());  
        }  
        add(NOWORD);  
    }   
    //add方法是为了建立前缀的库,以及生成前后缀之间的映射
    private void add(String word) {                    
        List<String> suf = stateTable.get(prefix);  
        if(suf == null){  
            suf = new ArrayList<String>();  
            stateTable.put(new Prefix(prefix),suf);  
        }  
        suf.add(word);                             
        prefix.pref.remove(0);                    //实现前缀 w1w2 转变为 w2w3;先调用List的remove方法删除w2,然后加入w3与w2组成新的后缀
        prefix.pref.add(word);  
    }  
  
    //根据篇幅数进行循环
    public void generate() {
        FileWriter fw = new FileWriter(args[1]);  
        prefix = new Prefix(NPREF,NOWORD);  
        for(int i=0; i<args[0]; i++){  
            List<String> suf = stateTable.get(prefix);  
            int r = Math.abs(random.nextInt() % suf.size());     //根据w1w2来产生w3
            String word = suf.get(r);  
            if(word.equals(NOWORD)){  
                break;  
            } 
            System.out.print(word+" ");  
            
                fw.write(word+" "); 
            prefix.pref.remove(0);  
            prefix.pref.add(word);  
        }
        fw.close;  
    }        
    }  

题目总结

  • 这次的题目很难,这真的很打脑壳,有很多知识都是课下自己补充的,在一些思路和方法上也借鉴了些其他人的,导致这次的结对编程很尴尬。
  • 这个程序只是做到了根据一些文章来写一篇文章,生成的文章还些许的语法错误,也没能很好处理标点的问题。
  • 一开始看到要求中“避免环”,嘎住了,这个东西也没能解决。
  • 程序执行效率分析未能完成,因为做出以上的东西对现在的我来说较为难了
  • 总之,每次的结对编程都是一次成长的过程,当然还有折磨...这让我清楚的认识到“当自己的才华撑不起自己的野心的时候,静下来学习吧”

代码托管

PSP

posted @ 2017-06-11 13:46  Wb同学在此  阅读(220)  评论(8编辑  收藏  举报