CS106B Serafini

这篇博客记录一下完成Serafini这个lab的过程

1.看书

完成这个lab需要看<>的前四章节.
前四章主要叙述了一些简单的C++的语法,此外介绍了集中重要的数据结构,这几种数据结构是由Stanford 大学提供的(库,文档在此)[https://cs.stanford.edu/people/eroberts/StanfordCPPLib/doc/index.html]

读完前四章我自己有如下总结,由于平时所用的语言是Java,这个总结也比较偏向Java的使用者:

  • 1.关于引用:
 public static void main(String args[]) throws Exception {
            Type type = new Type(1);
            System.out.println("this type is "+type.id);
            change(type);
            System.out.println("this type is "+type.id);
    
            int a = 1;
            System.out.println("this a is " + a);
            change(a);
            System.out.println("this a is " + a);
    }

   public static void change(Type type){
        type.id = 2;
    }

public static int  change(int i){
        i = 2;
        return i ;
    }

输出是

this type is 1
this type is 2
this a is 1
this a is 1

而在c++中 使用&可以让基本数据类型在通过函数之后都发生改变.

  • 2.关于构造函数

Java :

Type type = new Type(1);

c++

Type type(1);

2.完成lab

第一个实验: Wordladder
要求: 给定起始单词结尾单词,每次改变这个单词的一个字母,并且改变之后这个单词需要在字典中存在. 请求出从起始单词结尾单词的最短路径.

  • 怎么实现: 使用BFS算法
  • 为什么使用BFS算法可以让路径最短:
  • 如何优化程序让代码跑起来更快?

直接上代码:


#include 
#include 
#include 
#include 
#include 
#include 
#include "console.h"
#include "queue.h"
#include "set.h"
#include "stack.h"
#include "vector.h"
#include "lexicon.h"

using namespace std;
string word1,word2;
Set usedString;
string lexiconLocation ;
Lexicon dictionary;

void Welcome(){
    //absolute path
    string locationPrefix = "/home/kolibreath/桌面/WordLadder/res/",suffix ="";
    cin>>suffix;
    lexiconLocation = locationPrefix+suffix;
    cout<<"Word #1 (or Enter to quit):"<>word1;
    cout<<"Word #2 (or Enter to quit):"<>word2;
}

Lexicon loadDictionary(string location){
    Lexicon lexicon(lexiconLocation);
    return lexicon;
}

//return ture if the word is used else false
bool IsUsed(string word){
    if(usedString.contains(word)){
        return true;
    }else{
        return false;
    }
}

void BuildWordLadder(){
    usedString.add(word1);
    Queue> queueStack;
    Stack stack;
    stack.push(word1);
    queueStack.enqueue(stack);

    while(!queueStack.isEmpty()){
        Stack copy = queueStack.dequeue();
        string top = copy.peek();
        if(top == word2){
           cout<<"A ladder from data back to code:"< partialLadder = copy;
                        partialLadder.push(wordCopy);
                        queueStack.enqueue(partialLadder);
                        usedString.add(wordCopy);
                }
            }
        }
        }
    }
}

int main() { 
    setConsoleSize(750, 450);
    setConsoleFont("Courier New-16");
    setConsoleEcho(true);

    cout<<"Welcome to CS 106B Word Ladder.\n"
       <<"Please give me two English words, and I will change the\n"
       <<"first into the second by changing one letter at a time.\n";
    cout<<"Dictionary file name?";
    Welcome();
    dictionary = loadDictionary(lexiconLocation);
    BuildWordLadder();
    return 0;

}

好的,现在来解答这些问题:

  • 1.使用BFS算法的目的:
    首先简要的解释一下什么是BFS算法:
    Youtube 视频链接
    看完这个视频我们有如下经验:
    1.走过的点不能走,需要额外的有一个数据结构保存这些点
    2.主要的数据结构是队列和堆栈
    3.BFS算法的路径不止有一条

  • 2.怎么能确保使用BFS的路径是最短的?
    事实上使用得到的路径不止一条. 但是英文单词是很特殊的.举个例子:
    起始单词 code 终点单词 data

已知的最短路径是:

 code → cade → cate → date → data 
CS106B Serafini_第1张图片
图片.png

假设图单词都存在,因为一个字母之差可能失之千里.就算最后可以得到一个终点的单词 但是这个wordladder一定不是最短的. 所以最短的ladder是唯一的

另外需要提及的是储存已经使用过了的单词是避免ladder中产生loop的关键

3.关于优化代码速度:

  • 读取:只读取一次字典中的值放到Lexicon中
  • 寻找neighbor word 不应当找到所有的neighbor word 再进行判断,直接从一个字母一个字母的改变入手.

第二个lab N-gram
要求:读入一篇文章,需要"模仿"作者的口吻说出一段话.
具体的原理可以翻看CS106B的要求.

直接上代码:

// This is the CPP file you will edit and turn in.
// Also remove these comments here and add your own.
// TODO: remove this comment header

#include 
#include 
#include 
#include 
#include 
#include "console.h"
#include "tokenscanner.h"
#include "hashmap.h"
#include "random.h"
#include "vector.h"
#include "queue.h"


using namespace std;
string word1,word2;
string location = "/home/kolibreath/CLionProjects/Ngrams/res/";
HashMap > hashMap;
Vector keySet;


void GenerateNgramMap(int n,string path){
    ifstream stream;
    location += path;
    stream.open(location);
    TokenScanner scanner(stream);
    scanner.ignoreWhitespace();
    //store the input steam of words

    Vector temp;
    while(scanner.hasMoreTokens()){
       temp.add(scanner.nextToken());
    }

    for(int i=0;i vector;
            vector.add(value);
            hashMap.put(key,vector);
        }else{
            hashMap.get(key).add(value);
        }
    }
}

bool Contains(string key){
    for(int i=0;i window){
    string nextKey = "";
    for(int i=1;i values = hashMap.get(nextKey);
    string nextValue = values[randomInteger(0,values.size()-1)];
    return nextValue;
}

//n means the N-Gram number means the total words need to be generate
void RandomWriter(int n,int number){
    string firstRandomKey = keySet[randomInteger(0,keySet.size()-1)];
    Vectorvalues = hashMap.get(firstRandomKey);
    string firstValue = values[randomInteger(0,values.size()-1)];
    cout<<"..."< window;
    while(scanner.hasMoreTokens()){
        window.add(scanner.nextToken());
    }
    while(number>0){

        string nextValue = GetValidString(window);
        window.remove(0);
        window.add(nextValue);
        number--;
        cout<<" "<>path;
        GenerateNgramMap(3,path);
        RandomWriter(3,20);
    return 0;
}

其实这个第二个lab挺容易的,感觉比第一个lab还要简单一些,只需要定义一个完整的Map>就可以完成

你可能感兴趣的:(CS106B Serafini)