结对编程 - 马尔科夫链
需求分析
- 程序能够从文件中读取文章,且具备学习能力
- 建立前后缀之间的关系
- 控制文章输出的篇幅(字数)
- 随机生成文章
做题思路(设计思路&解决问题)
一、程序且具备学习能力
结合参考文章的思路:利用连续两个词构成的前缀来选择作为后缀的一个词
设置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;
}
}
题目总结
- 这次的题目很难,这真的很打脑壳,有很多知识都是课下自己补充的,在一些思路和方法上也借鉴了些其他人的,导致这次的结对编程很尴尬。
- 这个程序只是做到了根据一些文章来写一篇文章,生成的文章还些许的语法错误,也没能很好处理标点的问题。
- 一开始看到要求中“避免环”,嘎住了,这个东西也没能解决。
- 程序执行效率分析未能完成,因为做出以上的东西对现在的我来说较为难了
- 总之,每次的结对编程都是一次成长的过程,当然还有折磨...这让我清楚的认识到“当自己的才华撑不起自己的野心的时候,静下来学习吧”
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!
· 从 Windows Forms 到微服务的经验教训