PTA前3次大作业总结
- PTA前三次大作业的总结
- 引言:
- 设计与分析:
- 第一次PTA:
- 点击这里查看第一次PTA代码
- 第二次PTA
- 点击这里查看第二次PTA代码
- 第三次PTA:
- 点击这里查看第三次PTA代码
- 第一次PTA:
- 踩坑心得:
- 改进建议:
- 总结:
PTA前三次大作业的总结
引言:
PTA从第一次到现在,每一次的作业难度都有所增加,显而易见,类的设计对于pta往后的阶梯过程十分的重要。
知识点而言,前三次PTA主要考察了我们对于类的设计以及关联组合等等类的关系的知识点,并且后续还会加上继承多态等类之间的关系,除此之外呢,题目中还包括了各种对字符串的处理的知识点,其中就包括了正则表达式的应用以及Arrylist<>的应用。
题量看上去从第一次到第三次的题目的减少,其实由于难度的增加,导致了我们需要花更多的时间去完成他。
接下来让我们一起来看一下这三次PTA上的最后一题吧。
设计与分析:
第一次PTA:
题目内容如下
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三部分:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、题目内容
一行为一道题,可以输入多行数据。
格式:"#N:"+题号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
样例:#N:1 #Q:1+1= #A:2
.#N:2 #Q:2+2= #A:4
3、答题信息
答题信息按行输入,每一行为一组答案,每组答案包含第2部分所有题目的解题答案,答案的顺序号与题目题号相对应。
格式:"#A:"+答案内容
格式约束:答案数量与第2部分题目的数量相同,答案之间以英文空格分隔。
样例:#A:2 #A:78
2是题号为1的题目的答案
78是题号为2的题目的答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、答题信息
一行为一道题的答题信息,根据题目的数量输出多行数据。
格式:题目内容+" ~"+答案
样例:1+1=~2
2+2= ~4
3、判题信息
判题信息为一行数据,一条答题记录每个答案的判断结果,答案的先后顺序与题目题号相对应。
格式:判题结果+" "+判题结果
格式约束:
1、判题结果输出只能是true或者false,
2、判题信息的顺序与输入答题信息中的顺序相同
样例:true false true
这道题其实是比较简单的,因为题目的末尾给了我们具体的类的设计以及类中的方法和属性。
这道题的类图是这样的

我们根据类图写出的源码是这样的:
点击这里查看第一次PTA代码
点击查看代码
import java.util.*;
class Topic {
private int topicID;
private int score;
private String content;
private String standAnswer;
private boolean right = false;
public Topic() {}
public Topic(int topicID, String content, String standAnswer) {
this.topicID = topicID;
this.content = content;
this.standAnswer = standAnswer;
}
public int getTopicID() {
return topicID;
}
public void setTopicID(int topicID) {
this.topicID = topicID;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStandAnswer() {
return standAnswer;
}
public void setStandAnswer(String standAnswer) {
this.standAnswer = standAnswer;
}
public boolean judgment(String answer) {
return Objects.equals(answer, standAnswer);
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public boolean isRight() {
return right;
}
public void setRight(boolean right) {
this.right = right;
}
}
class Answer {
private int ar;
private final String[] answer = new String[100];
private boolean[] outcome;
public Answer() {}
public String getAnswer(int num) {
return answer[num];
}
public void setAnswer(int num, String answer) {
this.answer[num] = answer;
}
public boolean[] getOutcome() {
return outcome;
}
public void setOutcome(boolean[] outcome) {
this.outcome = outcome;
}
public int getAr() {
return ar;
}
public void setAr(int ar) {
this.ar = ar;
}
}
class AnswerParer {
private ArrayList<Answer> answers;
public AnswerParer() {
answers = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
answers.add(i, new Answer());
}
}
public void setAnswers() {
for (int i = 0; i < 100; i++) {
answers.add(i, new Answer());
}
}
public ArrayList<Answer> getAnswers() {
return answers;
}
}
class Paper {
private int topic_num;
private int score = 0;
private int[] real_ar = new int[100];
private ArrayList<Topic> topics;
public Paper() {
topics = new ArrayList<Topic>(100);
for (int i = 0; i < 100; i++) {
topics.add(i, new Topic());
}
}
public void setTopics() {
topics = new ArrayList<>(100);
}
public ArrayList<Topic> getTopics() {
return topics;
}
public boolean judgment(int num, String answer) {
return this.topics.get(num).judgment(answer);
}
public void save(int num, String question) {
this.topics.get(num).setContent(question);
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score += score;
}
public int getTopic_num() {
return topic_num;
}
public void setTopic_num(int topic_num) {
this.topic_num = topic_num;
}
public int getReal_ar(int num) {
return real_ar[num];
}
public void setReal_ar(int ar, int num) {
real_ar[ar] = num;
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int pos_paper = 1;
int pos_answer = 0;
int topic_num = 0;
String[] str = new String[100];
String str1, str2, str3;
str1 = in.nextLine();
ArrayList<Paper> papers = new ArrayList<>(100);
AnswerParer answerParer = new AnswerParer();
for (int i = 0; i < 100; i++) {
papers.add(i, new Paper());
}
while (!Objects.equals(str1, "end")) {
if (str1.matches("#N(.*)")) {
topic_num++;
str1 = str1.replaceAll("(\\s+|)#N:(\\s+|)", "#");
str1 = str1.replaceAll("(\\s+|)#Q:(\\s+|)", "#");
str1 = str1.replaceAll("(\\s+|)#A:(\\s+|)", "#");
str = str1.split("#");
for (int i = 0; i < 100; i++) {
papers.get(i).getTopics().get(Integer.parseInt(str[1]) - 1).setContent(str[2]);
papers.get(i).getTopics().get(Integer.parseInt(str[1]) - 1).setStandAnswer(str[3]);
}
}
if (str1.matches("#T(.*)")) {
str1 = str1.replaceAll("(\\s+|)#T:(\\s+|)", "#");
str1 = str1.replaceAll("\\s+", "#");
str = str1.split("[#\\s+-]+");
pos_paper = Integer.parseInt(str[1]);
for (int i = 3, j = 0; i <= str.length - 1; i += 2, j++) {
papers.get(pos_paper - 1).setScore(Integer.parseInt(str[i]));
papers.get(pos_paper - 1).getTopics().get(Integer.parseInt(str[i - 1])).setScore(Integer.parseInt(str[i]));
papers.get(pos_paper - 1).setReal_ar(j, Integer.parseInt(str[i - 1]));
}
papers.get(pos_answer).setTopic_num((str.length - 2) / 2);
if (papers.get(pos_paper - 1).getScore() != 100) {
System.out.println("alert: full score of test paper"+ pos_paper +" is not 100 points");
}
}
if (str1.matches("#S(.*)")) {
str1 = str1.replaceAll("(\\s+|)#S:(\\s+|)", "#");
str1 = str1.replaceAll("\\s+", "#");
str1 = str1.replaceAll("A:", "#");
str = str1.split("[#\\s]+");
answerParer.getAnswers().get(pos_answer).setAr(Integer.parseInt(str[1]));
for (int i = 2, j = 0; i < str.length; i++, j++) {
answerParer.getAnswers().get(pos_answer).setAnswer(j, str[i]);
}
pos_answer++;
}
str1 = in.nextLine();
}
for (int i = 0; i < pos_answer; i++) {
int answer_pos = answerParer.getAnswers().get(i).getAr();
if (answer_pos <= pos_paper) {
for (int j = 0; j < papers.get(answer_pos - 1).getTopic_num(); j++) {
if (answerParer.getAnswers().get(i).getAnswer(j) == null) {
System.out.println("answer is null");
} else {
System.out.print(papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j) - 1).getContent() + "~" + answerParer.getAnswers().get(i).getAnswer(j) + "~");
if (Objects.equals(papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j) - 1).getStandAnswer(), answerParer.getAnswers().get(i).getAnswer(j))) {
System.out.println("true");
papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).setRight(true);
} else {
System.out.println("false");
}
}
}
for (int j = 0; j < papers.get(answer_pos - 1).getTopic_num(); j++) {
if (papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight() && j == 0) {
System.out.print(papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).getScore());
}
if (!papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight() && j == 0) {
System.out.print("0");
}
if (papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight() && j != 0) {
System.out.print(" " + papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).getScore());
}
if (!papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight() && j != 0) {
System.out.print(" 0");
}
}
int score = 0;
for (int j = 0; j < papers.get(answer_pos - 1).getTopic_num(); j++) {
if (papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight()) {
score += papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).getScore();
}
}
System.out.println("~" + score);
} else {
System.out.println("The test paper number does not exist");
}
}
}
}
第二次PTA
题目内容如下
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-1基础上增补或者修改的内容。
要求输入题目信息、试卷信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三种,三种信息可能会打乱顺序混合输入:
1、题目信息
一行为一道题,可输入多行数据(多道题)。
格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:
1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:#N:1 #Q:1+1= #A:2
.#N:2 #Q:2+2= #A:4
2、试卷信息
一行为一张试卷,可输入多行数据(多张卷)。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值
题目编号应与题目信息中的编号对应。
一行信息中可有多项题目编号与分值。
样例:#T:1 3-5 4-8 5-2
3、答卷信息
答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序与试卷信息中的题目顺序相对应。
格式:"#S:"+试卷号+" "+"#A:"+答案内容
格式约束:答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
样例:#S:1 #A:5 #A:22
1是试卷号
5是1号试卷的顺序第1题的题目答案
22是1号试卷的顺序第2题的题目答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、试卷总分警示
该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100分,该部分忽略,不输出。
格式:"alert: full score of test paper"+试卷号+" is not 100 points"
样例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。
格式:题目内容+""+答案++""+判题结果(true/false)
约束:如果输入的答案信息少于试卷的题目数量,答案的题目要输"answer is null"
样例:3+2=5true
4+6=22false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:5 8 0~13
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、提示错误的试卷号
如果答案信息中试卷的编号找不到,则输出”the test paper number does not exist”,参见样例9。
设计建议:
参考答题判题程序-1,建议增加答题类,类的内容以及类之间的关联自行设计。
题目内容如上
第二题很明显就比第一题多了很多东西,包括输入的错误等,这时候就要求我们提取出正确的题目信息并且判断是否符合要求根据题目的条件,我们可以画出如下类图:

根据这个类图我们可以得到如下代码:
点击这里查看第二次PTA代码
点击查看代码
import java.util.*;
class Topic {
private int topicID;
private int score;
private String content;
private String standAnswer;
private boolean right = false;
public Topic() {}
public Topic(int topicID, String content, String standAnswer) {
this.topicID = topicID;
this.content = content;
this.standAnswer = standAnswer;
}
public int getTopicID() {
return topicID;
}
public void setTopicID(int topicID) {
this.topicID = topicID;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStandAnswer() {
return standAnswer;
}
public void setStandAnswer(String standAnswer) {
this.standAnswer = standAnswer;
}
public boolean judgment(String answer) {
return Objects.equals(answer, standAnswer);
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public boolean isRight() {
return right;
}
public void setRight(boolean right) {
this.right = right;
}
}
class Answer {
private int ar;
private final String[] answer = new String[100];
private boolean[] outcome;
public Answer() {}
public String getAnswer(int num) {
return answer[num];
}
public void setAnswer(int num, String answer) {
this.answer[num] = answer;
}
public boolean[] getOutcome() {
return outcome;
}
public void setOutcome(boolean[] outcome) {
this.outcome = outcome;
}
public int getAr() {
return ar;
}
public void setAr(int ar) {
this.ar = ar;
}
}
class AnswerParer {
private ArrayList<Answer> answers;
public AnswerParer() {
answers = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
answers.add(i, new Answer());
}
}
public void setAnswers() {
for (int i = 0; i < 100; i++) {
answers.add(i, new Answer());
}
}
public ArrayList<Answer> getAnswers() {
return answers;
}
}
class Paper {
private int topic_num;
private int score = 0;
private int[] real_ar = new int[100];
private ArrayList<Topic> topics;
public Paper() {
topics = new ArrayList<Topic>(100);
for (int i = 0; i < 100; i++) {
topics.add(i, new Topic());
}
}
public void setTopics() {
topics = new ArrayList<>(100);
}
public ArrayList<Topic> getTopics() {
return topics;
}
public boolean judgment(int num, String answer) {
return this.topics.get(num).judgment(answer);
}
public void save(int num, String question) {
this.topics.get(num).setContent(question);
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score += score;
}
public int getTopic_num() {
return topic_num;
}
public void setTopic_num(int topic_num) {
this.topic_num = topic_num;
}
public int getReal_ar(int num) {
return real_ar[num];
}
public void setReal_ar(int ar, int num) {
real_ar[ar] = num;
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int pos_paper = 1;
int pos_answer = 0;
int topic_num = 0;
String[] str = new String[100];
String str1, str2, str3;
str1 = in.nextLine();
ArrayList<Paper> papers = new ArrayList<>(100);
AnswerParer answerParer = new AnswerParer();
for (int i = 0; i < 100; i++) {
papers.add(i, new Paper());
}
while (!Objects.equals(str1, "end")) {
if (str1.matches("#N(.*)")) {
topic_num++;
str1 = str1.replaceAll("(\\s+|)#N:(\\s+|)", "#");
str1 = str1.replaceAll("(\\s+|)#Q:(\\s+|)", "#");
str1 = str1.replaceAll("(\\s+|)#A:(\\s+|)", "#");
str = str1.split("#");
for (int i = 0; i < 100; i++) {
papers.get(i).getTopics().get(Integer.parseInt(str[1]) - 1).setContent(str[2]);
papers.get(i).getTopics().get(Integer.parseInt(str[1]) - 1).setStandAnswer(str[3]);
}
}
if (str1.matches("#T(.*)")) {
str1 = str1.replaceAll("(\\s+|)#T:(\\s+|)", "#");
str1 = str1.replaceAll("\\s+", "#");
str = str1.split("[#\\s+-]+");
pos_paper = Integer.parseInt(str[1]);
for (int i = 3, j = 0; i <= str.length - 1; i += 2, j++) {
papers.get(pos_paper - 1).setScore(Integer.parseInt(str[i]));
papers.get(pos_paper - 1).getTopics().get(Integer.parseInt(str[i - 1])).setScore(Integer.parseInt(str[i]));
papers.get(pos_paper - 1).setReal_ar(j, Integer.parseInt(str[i - 1]));
}
papers.get(pos_answer).setTopic_num((str.length - 2) / 2);
if (papers.get(pos_paper - 1).getScore() != 100) {
System.out.println("alert: full score of test paper"+ pos_paper +" is not 100 points");
}
}
if (str1.matches("#S(.*)")) {
str1 = str1.replaceAll("(\\s+|)#S:(\\s+|)", "#");
str1 = str1.replaceAll("\\s+", "#");
str1 = str1.replaceAll("A:", "#");
str = str1.split("[#\\s]+");
answerParer.getAnswers().get(pos_answer).setAr(Integer.parseInt(str[1]));
for (int i = 2, j = 0; i < str.length; i++, j++) {
answerParer.getAnswers().get(pos_answer).setAnswer(j, str[i]);
}
pos_answer++;
}
str1 = in.nextLine();
}
for (int i = 0; i < pos_answer; i++) {
int answer_pos = answerParer.getAnswers().get(i).getAr();
if (answer_pos <= pos_paper) {
for (int j = 0; j < papers.get(answer_pos - 1).getTopic_num(); j++) {
if (answerParer.getAnswers().get(i).getAnswer(j) == null) {
System.out.println("answer is null");
} else {
System.out.print(papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j) - 1).getContent() + "~" + answerParer.getAnswers().get(i).getAnswer(j) + "~");
if (Objects.equals(papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j) - 1).getStandAnswer(), answerParer.getAnswers().get(i).getAnswer(j))) {
System.out.println("true");
papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).setRight(true);
} else {
System.out.println("false");
}
}
}
for (int j = 0; j < papers.get(answer_pos - 1).getTopic_num(); j++) {
if (papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight() && j == 0) {
System.out.print(papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).getScore());
}
if (!papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight() && j == 0) {
System.out.print("0");
}
if (papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight() && j != 0) {
System.out.print(" " + papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).getScore());
}
if (!papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight() && j != 0) {
System.out.print(" 0");
}
}
int score = 0;
for (int j = 0; j < papers.get(answer_pos - 1).getTopic_num(); j++) {
if (papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).isRight()) {
score += papers.get(answer_pos - 1).getTopics().get(papers.get(answer_pos - 1).getReal_ar(j)).getScore();
}
}
System.out.println("~" + score);
} else {
System.out.println("The test paper number does not exist");
}
}
}
}
第三次PTA:
题目内容如下
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-2基础上增补或者修改的内容,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分五种,信息可能会打乱顺序混合输入。
1、题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。
格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:
1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:
.#N:1 #Q:1+1= #A:2
.#N:2 #Q:2+2= #A:4
2、试卷信息
试卷信息为独行输入,一行为一张试卷,多张卷可分多行输入数据。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值+" "+题目编号+"-"+题目分值+...
格式约束:
题目编号应与题目信息中的编号对应。
一行信息中可有多项题目编号与分值。
样例:#T:1 3-5 4-8 5-2
3、学生信息
学生信息只输入一行,一行中包括所有学生的信息,每个学生的信息包括学号和姓名,格式如下。
格式:"#X:"+学号+" "+姓名+"-"+学号+" "+姓名....+"-"+学号+" "+姓名
格式约束:
答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
样例:
.#S:1 #A:5 #A:22
1是试卷号
5是1号试卷的顺序第1题的题目答案
4、答卷信息
答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序号与试 卷信息中的题目顺序相对应。答卷中:
格式:"#S:"+试卷号+" "+学号+" "+"#A:"+试卷题目的顺序号+"-"+答案内容+...
格式约束:
答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
答案内容可以为空,即””。
答案内容中如果首尾有多余的空格,应去除后再进行判断。
样例:
.#T:1 1-5 3-2 2-5 6-9 4-10 7-3
.#S:1 20201103 #A:2-5 #A:6-4
1是试卷号
20201103是学号
2-5中的2是试卷中顺序号,5是试卷第2题的答案,即T中3-2的答案
6-4中的6是试卷中顺序号,4是试卷第6题的答案,即T中7-3的答案
注意:不要混淆顺序号与题号
5、删除题目信息
删除题目信息为独行输入,每一行为一条删除信息,多条删除信息可分多行输入。该信息用于删除一道题目信息,题目被删除之后,引用该题目的试卷依然有效,但被删除的题目将以0分计,同时在输出答案时,题目内容与答案改为一条失效提示,例如:”the question 2 invalid~0”
格式:"#D:N-"+题目号
格式约束:
题目号与第一项”题目信息”中的题号相对应,不是试卷中的题目顺序号。
本题暂不考虑删除的题号不存在的情况。
样例:
.#N:1 #Q:1+1= #A:2
.#N:2 #Q:2+2= #A:4
.#T:1 1-5 2-8
.#X:20201103 Tom-20201104 Jack
.#S:1 20201103 #A:1-5 #A:2-4
.#D:N-2
end
输出
alert: full score of test paper1 is not 100 points
1+1=5false
the question 2 invalid~0
20201103 Tom: 0 0~0
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、试卷总分警示
该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100 分,该部分忽略,不输出。
格式:"alert: full score of test paper"+试卷号+" is not 100 points"
样例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。
格式:题目内容+""+答案++""+判题结果(true/false)
约束:如果输入的答案信息少于试卷的题目数量,每一个缺失答案的题目都要输出"answer is null" 。
样例:
3+2=5true
4+6=22false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:学号+" "+姓名+": "+题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目、被删除的题目、答案错误的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:20201103 Tom: 0 0~0
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、被删除的题目提示信息
当某题目被试卷引用,同时被删除时,答案中输出提示信息。样例见第5种输入信息“删除题目信息”。
5、题目引用错误提示信息
试卷错误地引用了一道不存在题号的试题,在输出学生答案时,提示”non-existent question~”加答案。例如:
输入:
.#N:1 #Q:1+1= #A:2
.#T:1 3-8
.#X:20201103 Tom-20201104 Jack-20201105 Www
.#S:1 20201103 #A:1-4
end
输出:
alert: full score of test paper1 is not 100 points
non-existent question~0
20201103 Tom: 0~0
如果答案输出时,一道题目同时出现答案不存在、引用错误题号、题目被删除,只提示一种信息,答案不存在的优先级最高,例如:
输入:
.#N:1 #Q:1+1= #A:2
.#T:1 3-8
.#X:20201103 Tom-20201104 Jack-20201105 Www
.#S:1 20201103
end
输出:
alert: full score of test paper1 is not 100 points
answer is null
20201103 Tom: 0~0
6、格式错误提示信息
输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。
例如:wrong format:2 #Q:2+2= #4
7、试卷号引用错误提示输出
如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”,答卷中的答案不用输出,参见样例8。
8、学号引用错误提示信息
如果答卷中的学号信息不在学生列表中,答案照常输出,判分时提示错误。参见样例9。
本题暂不考虑出现多张答卷的信息的情况。
题目内容如上
显而易见,这第三次题目集和前两次完全不是一个档次的(起码对于我来说),这一次对于类的设计的要求明显变高,我们需要设计一个能存储并解析所有题目的类来帮助我们整理好每一张答卷,并且题目,答卷,学生等等,类也增加了许多,对此,有如下类图:

根据类图得到的代码如下:
点击这里查看第三次PTA代码
点击查看代码
import java.util.ArrayList;
import java.util.Objects;
import java.util.Scanner;
class Topic {
private int ID;
private int score;
private String content;
private String standAnswer;
private boolean effective = true;
public Topic() {}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public void setStandAnswer(String standAnswer) {
this.standAnswer = standAnswer;
}
public boolean isEffective() {
return effective;
}
public void setEffective(boolean effective) {
this.effective = effective;
}
public boolean judgment(String answer) {
return Objects.equals(answer, this.standAnswer);
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
}
class Answer {
private int ar;
private String ID;
private int[] answerArray = new int[100];
private final String[] answer = new String[100];
public Answer() {}
public String getAnswer(int num) {
return answer[num];
}
public void setAnswer(int num, String answer) {
this.answer[num] = answer;
}
public int getAr() {
return ar;
}
public void setAr(int ar) {
this.ar = ar;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public int getArray(int pos) {
return answerArray[pos];
}
public void setArray( int pos, int num) {
this.answerArray[pos] = num;
}
}
class AnswerParer {
private ArrayList<Answer> answers;
public AnswerParer() {
answers = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
answers.add(i, new Answer());
}
}
public ArrayList<Answer> getAnswers() {
return answers;
}
}
class Paper {
private int topicNum;
private int score = 0;
private int[] realAr = new int[100];
private int[] topicArray = new int[100];
private ArrayList<Topic> topics;
public Paper() {
topics = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
topics.add(i, new Topic());
}
}
public ArrayList<Topic> getTopics() {
return topics;
}
public boolean judgment(int num, String answer) {
if (getTopics().get(num).judgment(answer) && getTopics().get(num).isEffective()) {
this.score += getTopics().get(num).getScore();
return true;
} else {
return false;
}
}
public void saveScore(int num, int score) {
this.topics.get(num).setScore(score);
}
public int getScore() {
return score;
}
public int getTopicNum() {
return topicNum;
}
public void setTopicNum(int topicNum) {
this.topicNum = topicNum;
}
public int getRealAr(int num) {
return realAr[num];
}
public void setRealAr(int ar, int num) {
realAr[ar] = num;
}
public int getTopicArray(int pos) {
return topicArray[pos];
}
public void setTopicArray(int pos, int num) {
topicArray[pos] = num;
}
}
class Student {
private String name;
private String ID;
public Student() {}
public Student(String name, String ID) {
this.name = name;
this.ID = ID;
}
public String getName() {
return name;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
}
class Input {
private int posPaper = 1;
public int getPosAnswer() {
return posAnswer;
}
public int getStudentNum() {
return studentNum;
}
public int getPaperArray(int pos) {
return paperArray[pos];
}
public ArrayList<Paper> getPapers() {
return papers;
}
private int posAnswer = 0;
private int topicNum = 0;
private int studentNum = 0;
public AnswerParer getAnswerParer() {
return answerParer;
}
private int[] paperArray = new int[100];
private ArrayList<Paper> papers = new ArrayList<>(100);
public ArrayList<Student> getStudents() {
return students;
}
private ArrayList<Student> students = new ArrayList<>(100);
private AnswerParer answerParer = new AnswerParer();
public Input(ArrayList<Paper> papers, ArrayList<Student> students, AnswerParer answerParer) {
for (int i = 0; i < 100; i++) {
papers.add(i, new Paper());
students.add(i, new Student());
}
this.papers = papers;
this.students = students;
this.answerParer = answerParer;
}
public void getMassage() {
Scanner in = new Scanner(System.in);
int ar = 0;
String[] str = new String[100];
String str1;
str1 = in.nextLine();
for (int i = 0; i < 100; i++) {
papers.add(i, new Paper());
}
while (!Objects.equals(str1, "end")) {
if (str1.matches("#N:\\d(.*) #Q:(.*|) #A:(.*|)")) {
String tem = str1;
if (str1.matches("(.*)#Q:(.*)")) {
str1 = str1.replaceAll("#N:", " #");
str1 = str1.replaceAll("#Q:", "#");
str1 = str1.replaceAll("#A:$", "#A:" + "@");
str1 = str1.replaceAll("#A:(\\s+|)", "#");
if (str1.matches("(.*)##(.*)")) {
System.out.println("wrong format:" + tem);
} else {
topicNum++;
str = str1.split("( #)");
for (int j = 0; j < str.length; j++) {
if (Objects.equals(str[j], "@")) {
str[j] = "";
}
}
str[3] = str[3].replaceAll("\\s+$","");
for (int i = 0; i < 100; i++) {
papers.get(i).getTopics().get(Integer.parseInt(str[1]) - 1).setContent(str[2]);
papers.get(i).getTopics().get(Integer.parseInt(str[1]) - 1).setStandAnswer(str[3]);
papers.get(i).setTopicArray(topicNum - 1, Integer.parseInt(str[1]));
}
}
} else {
System.out.println("wrong format:" + str1);
}
} else if (str1.matches("#T:\\d+( \\d+-\\d+)+")) {
if (str1.matches("(.*)(?<=(\\D|\\s))-(.*)") || str1.matches("(.*)-(?=\\D+|\\s+)(.*)") || str1.matches("(.*)-") || !str1.matches("(.*)-(.*)")) {
System.out.println("wrong format:" + str1);
} else {
str1 = str1.replaceAll("(\\s+|)#T:(\\s+|)", "#");
str1 = str1.replaceAll("\\s+", "#");
str = str1.split("[#\\s+-]+");
posPaper = Integer.parseInt(str[1]);
paperArray[ar] = Integer.parseInt(str[1]);
ar++;
int score = 0;
for (int i = 3, j = 0;i <= str.length - 1; i += 2, j++) {
score += Integer.parseInt(str[i]);
papers.get(posPaper - 1).saveScore(Integer.parseInt(str[i - 1]) - 1, Integer.parseInt(str[i]));
papers.get(posPaper - 1).setRealAr(j, Integer.parseInt(str[i - 1]));
}
papers.get(posPaper - 1).setTopicNum((str.length - 2) / 2);
if (score != 100) {
System.out.println("alert: full score of test paper" + posPaper + " is not 100 points");
}
}
} else if (str1.matches("#S:\\d+ \\d+(.*)")) {
String tem = str1;
if (str1.matches("(.*)(?<=(\\D))-(.*)")) {
System.out.println("wrong format:" + str1);
} else {
str1 = str1.replaceAll("(?<=[^\\s+])#", " #");
str1 = str1.replaceAll("#S:", " #");
str1 = str1.replaceAll("#A:", "#");
str1 = str1.replaceAll("(\\d)\\s+(\\d{8})", "$1 #$2");
str1 = str1.replaceAll("-(?=#)", "-@ ");
str1 = str1.replaceAll("-(?=$)", "-@");
str = str1.split("( #)|-");
for (int i = 0; i < str.length; i++) {
if (Objects.equals(str[i], "@")) {
str[i] = "";
}
}
if (str.length > 2) {
answerParer.getAnswers().get(posAnswer).setAr(Integer.parseInt(str[1]));
answerParer.getAnswers().get(posAnswer).setID(str[2]);
for (int i = 3, j = 0; i < str.length; i += 2, j++) {
str[i + 1] = str[i + 1].replaceAll("\\s+$","");
answerParer.getAnswers().get(posAnswer).setAnswer(Integer.parseInt(str[i]) - 1, str[i + 1]);
answerParer.getAnswers().get(posAnswer).setArray(j, Integer.parseInt(str[i]));
}
}
else {
System.out.println("wrong format:" + tem);
}
posAnswer++;
}
} else if (str1.matches("#X:\\d+ [a-zA-Z]+(-\\d+ [a-zA-Z]+)*")) {
if (str1.matches("(.*)(?<![a-zA-Z])-(.*)") || str1.matches("(.*)-(?=\\D+|\\s+)(.*)") || str1.matches("(.*)-")) {
System.out.println("wrong format:" + str1);
} else {
str1 = str1.replaceAll("(\\s+|)#X:(\\s+|)", "");
str = str1.split("[-\\s#]");
for (int i = 1; i < str.length; i += 2) {
students.add(studentNum, new Student(str[i], str[i - 1]));
studentNum++;
}
}
} else if (str1.matches("#D:N-\\d+")){
str1 = str1.replaceAll("(\\s+|)#D:(\\s+|)", "");
str1 = str1.replaceAll("\\s+", "");
str = str1.split("[-\\s#]");
for (int i = 0; i < 100; i++) {
papers.get(i).getTopics().get(Integer.parseInt(str[1]) - 1).setEffective(false);
}
}
else {
System.out.println("wrong format:" + str1);
}
str1 = in.nextLine();
}
}
}
class Judgment {
private ArrayList<Paper> papers = new ArrayList<>(100);
private ArrayList<Student> students = new ArrayList<>(100);
private ArrayList<String> strings = new ArrayList<>();
private AnswerParer answerParer = new AnswerParer();
private Input input = new Input(papers, students, answerParer);
public Judgment(ArrayList<Paper> papers, ArrayList<Student> students, AnswerParer answerParer) {
for(int i = 0; i < 100; i++) {
papers.add(i, new Paper());
students.add(i, new Student());
}
this.papers = papers;
this.students = students;
this.answerParer = answerParer;
}
public void getMassage() {
input.getMassage();
}
public void getOutcome() {
boolean bo1 = false;
boolean bo2 = false;
boolean bo3 = false;
boolean bo4 = false;
for (int i = 0; i < input.getPosAnswer(); i++) {
int answerPos = input.getAnswerParer().getAnswers().get(i).getAr();
for (int j = 0; j < 100; j++) {
if (answerPos == input.getPaperArray(j)) {
bo4 = true;
break;
}
}
if (bo4) {
for (int j = 0; j < input.getPapers().get(answerPos - 1).getTopicNum(); j++) {
for (int n = 0; n < 100; n++) {
if ((input.getAnswerParer().getAnswers().get(i).getArray(n) == j + 1)) {
bo2 = true;
break;
}
}
if (bo2) {
for (int n = 0; n < 100; n++) {
if (input.getPapers().get(answerPos - 1).getRealAr(j) == input.getPapers().get(answerPos - 1).getTopicArray(n)) {
bo3 = true;
break;
}
}
if (bo3) {
if (input.getPapers().get(answerPos - 1).getTopics().get(input.getPapers().get(answerPos - 1).getRealAr(j) - 1).isEffective()) {
System.out.print(input.getPapers().get(answerPos - 1).getTopics().get(input.getPapers().get(answerPos - 1).getRealAr(j) - 1).getContent() + "~");
System.out.print(input.getAnswerParer().getAnswers().get(i).getAnswer(j) + "~");
if (input.getPapers().get(answerPos - 1).judgment(input.getPapers().get(answerPos - 1).getRealAr(j) - 1, input.getAnswerParer().getAnswers().get(i).getAnswer(j))) {
System.out.println("true");
strings.add(" " + input.getPapers().get(answerPos - 1).getTopics().get(input.getPapers().get(answerPos - 1).getRealAr(j) - 1).getScore());
} else {
System.out.println("false");
strings.add(" 0");
}
} else {
System.out.println("the question " + input.getPapers().get(answerPos - 1).getRealAr(j) + " invalid~0");
strings.add(" 0");
}
bo3 = false;
} else {
System.out.println("non-existent question~0");
strings.add(" 0");
}
bo2 = false;
} else {
System.out.println("answer is null");
strings.add(" 0");
}
}
for (int j = 0; j < input.getStudentNum(); j++) {
if (Objects.equals(input.getAnswerParer().getAnswers().get(i).getID(), input.getStudents().get(j).getID())) {
bo1 = true;
System.out.print(input.getStudents().get(j).getID() + " " + input.getStudents().get(j).getName() + ":");
break;
}
}
if (bo1) {
for (String string : strings) {
System.out.print(string);
}
System.out.println("~" + input.getPapers().get(answerPos - 1).getScore());
bo1 = false;
} else {
System.out.println(input.getAnswerParer().getAnswers().get(i).getID() + " not found");
}
bo4 = false;
} else {
System.out.println("The test paper number does not exist");
}
}
}
}
public class Main {
public static void main(String[] args) {
ArrayList<Paper> papers = new ArrayList<>(100);
ArrayList<Student> students = new ArrayList<>(100);
AnswerParer answerParer = new AnswerParer();
Judgment judgment = new Judgment(papers, students, answerParer);
judgment.getMassage();
judgment.getOutcome();
}
}
踩坑心得:
这个板块属实是一个非常扎心的板块,毕竟全都是这段时间以来写PTA的“血和泪”。
首先,是个人的技术问题,第一次写PTA的大作业时,就发现我对于正则表达式的构建还十分的不熟练,对于题目中要求我分离的字符串很难将其分割成正确的形式,为此特意去线上学堂重新刷了一遍正则表达式的相关课程,但是发现课程上的正则表达式的讲解并不够全面,于是又通过了CSDN,询问其他人等方法来解决正则表达式的问题,但是尽管如此,到了第三次PTA题目集发现依旧还是很难正确地使用正则表达式来分离起题目输入的字符串,总结一下,原因大概率是正则表达式的使用次数太少了,实在是不够熟练,应该多加练习。
其次,就是和大部分人一样的对于类的设计不够精准,有时还无法做到SCP,导致下一个题目集不得不重新设计各个类,从而大大增加了解题时间,使得每次题目集所花的时间一次比一次长。
最后就是很多细节方面把控不好,测试点经常只过少数几个,考虑的方面不周全,没有做到追求完美。我相信很多人和我一样也会有这种问题,说白了对于我们这些新手程序员无非只能花更多的时间来磨这些题,只有花更多的时间来追求各种细节,才能提高能力。
改进建议:
可以尽可能多地设计控制类,做到将各种数据的处理的方法分离,不要将answerpaper,questions...中的各种数据集合在一个类中进行处理,分离了有利于后续PTA的代码的迭代
总结:
学习到的东西确实挺多的,个人觉得最标志性的就是正则表达式的应用,其次就是类的设计(虽然目前设计出来的依旧不尽人意,但是还是对于刚开始有了较大的进步)。
建议每次做完一个题目集都能发出当次PTA最后一题的类图,并不是说降低难度,这对于没有做出来的人和做出来的人都有好处。首先,对于已经拿到满分的同学:可以通过发出来的标准的类图可以对自己的设计有所改进,从中学习,并与自己的设计精心对比,温故而知新,起到了巩固的效果。其次,对于没有拿到满分的同学:学习正确的类图的设计不仅铺垫了下一次题目集的基础,也能更好地提高自己的水平,毕竟这些题目集依次迭代,知道了上一次的类的设计对于下一次的影响也不是很大。