目 錄java
1 實驗目標概述... 1git
2 實驗環境配置... 1github
3 實驗過程... 1算法
3.1 Magic Squares. 2編程
3.1.1 isLegalMagicSquare().. 2數組
3.1.2 generateMagicSquare() 3網絡
3.2 Turtle Graphics. 5app
3.2.1 Problem 1: Clone and import 5框架
3.2.2 Problem 3: Turtle graphics and drawSquare. 5eclipse
3.2.3 Problem 5: Drawing polygons. 5
3.2.4 Problem 6: Calculating Bearings. 5
3.2.5 Problem 7: Convex Hulls. 5
3.2.6 Problem 8: Personal art 6
3.2.7 Submitting. 6
3.3 Social Network. 6
3.3.1 設計/實現FriendshipGraph類... 6
3.3.2 設計/實現Person類... 7
3.3.3 設計/實現客戶端代碼main(). 8
3.3.4 設計/實現測試用例... 8
3.4 Tweet Tweet 10
3.4.1 Problem 1: Extracting data from tweets. 10
3.4.2 Problem 2: Filtering lists of tweets. 10
3.4.3 Problem 3: Inferring a social network. 10
3.4.4 Problem 4: Get smarter 10
4 實驗進度記錄... 10
5 實驗過程當中遇到的困難與解決途徑... 11
6 實驗過程當中收穫的經驗、教訓、感想... 11
6.1 實驗過程當中收穫的經驗和教訓... 11
6.2 針對如下方面的感覺... 11
本次實驗經過求解四個問題,訓練基本 Java 編程技能,可以利用 Java OO 開。
發基本的功能模塊,可以閱讀理解已有代碼框架並根據功能需求補全代碼,可以。
爲所開發的代碼編寫基本的測試程序並完成測試,初步保證所開發代碼的正確性。
另外一方面,利用 Git 做爲代碼配置管理的工具,學會 Git 的基本使用方法。
基本的 Java OO 編程;
基於 Eclipse IDE 進行 Java 編程;
基於 JUnit 的測試;
基於 Git 的代碼配置管理。
簡要陳述你配置本次實驗所需開發、測試、運行環境的過程,必要時能夠給出屏幕截圖。
特別是要記錄配置過程當中遇到的問題和困難,以及如何解決的。
在這裏給出你的GitHub Lab1倉庫的URL地址(Lab1-學號):
https://github.com/ComputerScienceHIT/Lab1-1170400307
請仔細對照實驗手冊,針對四個問題中的每一項任務,在下面各節中記錄你的實驗過程、闡述你的設計思路和問題求解思路,可輔之以示意圖或關鍵源代碼加以說明(但無需把你的源代碼所有粘貼過來!)。
爲了條理清晰,可根據須要在各節增長三級標題。
問題理解:本問題要求實現判斷一個nxn矩陣是不是一個幻方,而且理解一個針對n爲奇數的幻方的生成算法。主要考察點:Java基本語法,文件讀寫,判斷輸入的合法性。
1. 讀入文本。
InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("src/P1/txt/" + fileName)),"UTF-8");
BufferedReader stream = new BufferedReader(reader);
2檢查有沒有非法字符,對於本題來講,合法的字符只有’0’到’9’和’\t’。
if(test[i].contains(".") || test[i].contains("-"))
{
System.out.print("contais - or .");
return false;
}
3檢查是否是方陣。檢查每一行的字符數是否等於行數。
if(checkStrings.length!=row)
{
System.out.print("lines is not equal rows");
return false;
}
4以上條件都知足時再判斷是否是幻方。
for (int i = 0; i < row; i++) {
sum[i]=0;
checkStrings=test[i].split("\t");
if(checkStrings.length!=row)
{
System.out.print("lines is not equal rows");
return false;
}
for (int j = 0; j < checkStrings.length; j++) {
result[i][j]=Integer.valueOf(checkStrings[j]);
}
for (int j = 0; j < row; j++) {
sum[i]=sum[i]+result[i][j];
}
}
for (int i = 0; i < row; i++) {
sum[i+row]=0;
for (int j = 0; j < row; j++) {
sum[i+row]=sum[i+row]+result[j][i];
}
}
sum[2*row]=0;
sum[2*row+1]=0;
for(int i=0;i<row;i++)
{
sum[2*row]=sum[2*row]+result[i][i];
sum[2*row+1]=sum[2*row+1]+result[i][row-1-i];
}
for (int i = 1; i <= 2*row+1; i++) {
if(sum[i-1]!=sum[i])
{
System.out.print("sums are not equal");
return false;
}
思路:使用羅伯法構造一個n爲奇數的nxn幻方。羅伯法的算法爲把1(或最小的數)放在第一行正中;按如下規律排列剩下的(n×n-1)個數:
(1)每個數放在前一個數的右上一格;
(2)若是這個數所要放的格已經超出了頂行那麼就把它放在底行,仍然要放在右一列;
(3)若是這個數所要放的格已經超出了最右列那麼就把它放在最左列,仍然要放在上一行;
(4)若是這個數所要放的格已經超出了頂行且超出了最右列,那麼就把它放在底行且最左列;
(5)若是這個數所要放的格已經有數填入,那麼就把它放在前一個數的下一行同一列的格內。
該任務須要我去自主學習java的一個第三方畫圖方案Turtle,而且經過給出的現有的Turtle方法實現題目要求的畫圖任務,而且藉助數學工具進行解題。
利用get clone命令行
這個函數的功能是畫一個正方形。須要調用兩個方法foward(int units)向當前方向畫直線,長度是輸入的數字,單位是內部規定單位。turn(double degrees)按照順時針方向旋轉畫圖方向。
這個任務包含幾個小任務。
(1)calculateRegularPolygonAngle 計算正多邊形的內角,(邊數-2)/sides。
(2)int calculatePolygonSidesFromAngle(double angle)
這個方法和上一個相似,根據角度計算正多邊形邊數。
(3)drawRegularPolygon :調用calculateRegularPolygonAngle(sides)計算正多邊形的內角爲rotation,調用turtle.forward和turtle.turn進行前進和轉向。
calculateBearingToPoint :計算(當前點,當前朝向)構成的向量與(當前點,目標點)構成的向量之間的夾角,首先計算(當前點,目標點)構成的向量與y軸之間的tan,使用Math.atan2計算與y軸夾角,與當前朝向夾角(與y軸之間)做差計算兩向量之間的夾角,須要注意負角變正角。
calculateBearings:對列表中的每兩個相鄰節點調用calculateBearingToPoint計算夾角。
這個是運用凸包算法。即對於一組輸入的平面點集,求一個最小的集合組成的凸包,使這個凸包的全部點組成的凸多邊形能夠圍着全部的點。
我採起的是gift-wrapping算法,這個算法形象的理解是,先選取一個一定在凸包裏的點做爲起點,這個點能夠選取縱座標最小的點(當存在多個縱座標最小的點時,選取其中橫座標最小的點)。而後想象用一根繩子從起點出發,把平面上的全部點牢牢的圍在一塊兒,這條繩子上的拐點就是凸包上的點。
個人設計值得注意的幾點是
1將輸入的存放點集的set改爲數組,方便操做
2經過向量叉積判斷向量方位,例如A*B當A須要逆時針才能轉向B時,A*B的值是正的。
利用以下指令,藉助函數改變繪畫形狀和顏色:
public static void drawPersonalArt(Turtle turtle) {
for (int i = 0 ; i < 1500; i++) {
turtle.forward(i/2);
switch ((i/15) % 10) {
case 0:turtle.color(PenColor.BLACK);break;
case 1:turtle.color(PenColor.GRAY);break;
case 2:turtle.color(PenColor.RED);break;
case 3:turtle.color(PenColor.PINK);break;
case 4:turtle.color(PenColor.ORANGE);break;
case 5:turtle.color(PenColor.YELLOW);break;
case 6:turtle.color(PenColor.GREEN);break;
case 7:turtle.color(PenColor.CYAN);break;
case 8:turtle.color(PenColor.BLUE);break;
case 9:turtle.color(PenColor.MAGENTA);break;
}
turtle.turn(91);
}
}
利用git push命令行
該任務是須要我去創建一個圖,經過輸入搭建有向社交網,而且給出正確的輸出,對非法輸入進行正確的判斷。
我採用的是鄰接表的展現結構,效率較高。在List類型內裝入Person類型,並且每個Person內有List存儲每個人的序號
對於求出兩個person之間的距離,先調用方法 calculateDistance
private void calculateDistance(Person name1){
int size = name1.getIdSize();
List<Integer> id = name1.getId();
for(int i = 0; i < size; i ++){
Person person = nameList.get(id.get(i));
if(!person.getKnown()){
person.setDistance(name1.getDistance()+1);
person.setKnown(true);
calculateDistance(person);
}else{
if(name1.getDistance()+1<person.getDistance()){
person.setDistance(name1.getDistance()+1);
}
}
}
}
這個方法以一個person爲起點進行深度優先搜索,標記搜索過的點,並記錄距起始搜索點的距離,而後經過getDistance方法得到兩個person之間的信息,若是另外一個person的distance是0,說明是同一個點,若是未搜索到,說明無關係,返回-1。
Person設計儘可能知足如下幾點
1成員變量設置成private,成員變量的訪問是經過成員方法進行的
2知足FreindshipGraph的要求
如下是源代碼
public class Person{
private String name;
private boolean known;
private int distance;
private List<Integer> id = new ArrayList<>();
public boolean getKnown(){
return known;
}
public int getDistance(){
return distance;
}
public void setDistance(int Distance){
this.distance = Distance;
}
public String getName() {
return name;
}
public void setKnown(boolean flag){
known = flag;
}
public List<Integer> getId(){
return id;
}
public int getIdSize(){
return id.size();
}
public boolean existId(int id){
if(this.id.contains(id)){
return true;
}
return false;
}
public void setId(int p) {
Integer P = new Integer(p);
this.id.add(P);
}
public Person(String name){
this.name = name;
}
}
客戶端代碼實驗文檔已經提供
FriendshipGraph graph = new FriendshipGraph();
Person rachel = new Person("rachel");
Person ross = new Person("ross");
Person ben = new Person("ben");
Person kramer = new Person("kramer");
graph.addVertex(rachel);
graph.addVertex(ross);
graph.addVertex(ben);
graph.addVertex(kramer);
graph.addEdge(rachel, ross);
graph.addEdge(ross, rachel);
graph.addEdge(ross, ben);
graph.addEdge(ben, ross);
System.out.println(graph.getDistance(rachel,ross));
System.out.println(graph.getDistance(rachel,ben));
System.out.println(graph.getDistance(rachel,rachel));
System.out.println(graph.getDistance(rachel,kramer));
主要對計算距離的算法進行了測試。
public void GetDistanceTest() {
FriendshipGraph graph = new FriendshipGraph();
Person rachel = new Person("Rachel");
Person ross = new Person("Ross");
Person ben = new Person("Ben");
Person kramer = new Person("Kramer");
Person abc = new Person("abc");
Person def = new Person("def");
Person hij = new Person("hij");
Person lmn = new Person("lmn");
graph.addVertex(rachel);
graph.addVertex(ross);
graph.addVertex(ben);
graph.addVertex(kramer);
graph.addVertex(abc);
graph.addVertex(def);
graph.addVertex(hij);
graph.addVertex(lmn);
graph.addEdge(rachel, ross);
graph.addEdge(ross, rachel);
graph.addEdge(ross, ben);
graph.addEdge(ben, ross);
graph.addEdge(rachel, def);
graph.addEdge(def, rachel);
graph.addEdge(abc, ross);
graph.addEdge(ross, abc);
graph.addEdge(hij, ross);
graph.addEdge(ross, hij);
graph.addEdge(lmn, ben);
graph.addEdge(ben, lmn);
assertEquals(1, graph.getDistance(rachel, ross));
assertEquals(2, graph.getDistance(rachel, ben));
assertEquals(0, graph.getDistance(rachel, rachel));
assertEquals(-1, graph.getDistance(rachel, kramer));
assertEquals(2, graph.getDistance(rachel, abc));
assertEquals(1, graph.getDistance(rachel, def));
assertEquals(2, graph.getDistance(rachel, hij));
assertEquals(3, graph.getDistance(rachel, lmn));
}
getTimespan:
若是tweets爲空則將當前時間做爲始末時間點構造Timespan,不然調用getEarliestTime和getLatestTime分別得到全部tweets中的最先發表時間和最晚發表時間構造Timespan。時間比較調用Time.isBefore和Time.isAfter函數。
getMentionedUsers
檢測tweet的text部分,先找到字符@,而後檢測@前一個字符,當不是有效字符時,記錄@後面的有效字符,便是咱們要找的字符串。
writtenBy:for循環檢查全部tweet,獲取username,而後和咱們的字符串比較,相等即匹配成功。
inTimespan:利用Time.isBefore和Time.isAfter進行比較。
containing:先利用toLowerCase函數把推文內容和待查找字符串都轉化爲小寫字母形式,而後直接調用contains函數進行檢查。
guessFollowGraph:第一種證據思路是若是一名author在tweet中@過其餘人,那麼該author就會follow這些被@的人。掃描每條tweet,調用Extract.getMentionedUsers提取出該條tweet中全部被@到的人,將這些人加入到Map[author]->Set<Stirng>中。
public static List<String> influencers(Map<String, Set<String>> followsGraph)
influencers:按照社交網絡的影響力(follow數目)對全部user進行排名。首先根據followsGraph統計每一個人的follow數目,再對每一個人的follow數目進行排名。
我採用的是最簡單的尋找推文中的話題,利用話題的集合程度來表達兩我的之間關係的親密。
算法上和之間的尋找@的人物十分相似,咱們的主要目的是但願找到兩個具備相同話題的人,若是在此基礎之上,兩我的又有互相@的行爲,咱們就能夠斷定爲他們的關係不該該侷限於「互相影響上面」,而有多是其餘關係,例如朋友。
請使用表格方式記錄你的進度狀況,以超過半小時的連續編程時間爲一行。
日期 |
時間段 |
任務 |
實際完成狀況 |
2019-3-1 |
15:45-17:30 |
配置好實驗環境和編譯器 |
按計劃完成 |
2019-3-5 |
15:45-17:30 |
完成項目1 |
延期1小時完成 |
2019-3-7 |
15:45-17:30 |
完成項目2 |
遇到困難,未完成 |
2019-3-10 |
15:45-17:30 |
完成項目3 |
提早一小時完成 |
2019-3-15 |
15:45-17:30 |
完成項目4 |
遇到困難,求助谷歌 |
2019-3-17 |
15:45-17:30 |
完成實驗報告 |
按計劃完成 |
遇到的難點 |
解決途徑 |
對git使用不清楚
|
仔細閱讀《git中文使用手冊》 |
對於JAVA基本語法不熟悉
|
仔細學習《JAVA編程思想》 |
題目有點難度,錯誤比較多
|
逐次調試,改正bug |
1.關於JAVA的一些基礎知識不會,網上也沒有適合的資料,學習的過程浪費了一些時間。
2.題目是英文的,閱讀起來有些難度,須要藉助於網絡工具,不少時候對題意的理解也有問題,很難下手。
3.本身的代碼寫的不好,沒有章法,沒有明確的思路,結構也很混亂,只能保證答案正確。
(1) Java編程語言是否對你的口味?
JAVA是世界上最好的編程語言。
(2) 關於Eclipse IDE
Eclipse是世界上最好的IDE。
(3) 關於Git和GitHub
Git和GitHub是世界上最好的代碼交流項目。
(4) 關於CMU和MIT的做業
做業很難,作做業的過程很艱辛,經過作CMU和MIT的做業,我深入地認識到了本身和它們學生之間的差距,怪不得我考不上CMU和MIT。
(5) 關於本實驗的工做量、難度、deadline
作完以後感受難度仍是有點大的,主要緣由在於本身第一次用JAVA,關於語法和算法的基礎知識屬於現學現用,,只能照葫蘆畫瓢,很艱難。
(6) 關於初接觸「軟件構造」課程
上課的內容和實驗的內容有必定差距,不少實驗內容要自學,目前基礎太差,之後須要更加努力。