pta前三次作业总结
1.前言
(1)
在经过三次PTA的洗礼过后,我感觉我已经升华了,脑细胞大半已经去往那美好的地方了。也许是我天资愚钝,我感觉第一次PTA可以应对,第二次PTA有点吃力,第三次PTA直接开始不知所措了。但我还是从这个过程中学到了不少东西在经过三次PTA的洗礼过后,我感觉我已经升华了,脑细胞大半已经去往那美好的地方了。也许是我天资愚钝,我感觉第一次PTA可以应对,第二次PTA有点吃力,第三次PTA直接开始不知所措了,因为三次PTA的最后一题是属于在上次代码上进行增减,难度依次增加。
我也从做题的过程中学到了不少东西。
(2)
这几次PTA主要考察了
1.正则表达式。
2.ArrayList,LinkedList和HashMap的使用。
3.对单一职责原则的理解(每个类负责一件事),还要确保封装性。3.对单一职责原则的理解(每个类负责一件事),还要确保封装性。
4.调试代码(许多时候代码太多,一下看不出错误,就在不断调试)
2.设计与分析
(题目中的*为无意义不属于题目)
(1)第一次的最后一题
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三部分:
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
输入样例1:
单个题目。例如:
1
*#N:1 #Q:1+1= #A:2
*#A:2
end
输出样例1:
在这里给出相应的输出。例如:
1+1=~2
true
输入样例2:
单个题目。例如:
1
*#N:1 #Q:1+1= #A:2
*#A:4
end
输出样例2:
在这里给出相应的输出。例如:
1+1=~4
false
输入样例3:
多个题目。例如:
2
*#N:1 #Q:1+1= #A:2
*#N:2 #Q:2+2= #A:4
*#A:2 #A:4
end
输出样例3:
在这里给出相应的输出。例如:
1+1=~2
2+2=~4
true true
输入样例4:
多个题目。例如:
2
*#N:1 #Q:1+1= #A:2
*#N:2 #Q:2+2= #A:4
*#A:2 #A:2
end
输出样例4:
在这里给出相应的输出。例如:
1+1=~2
2+2=~2
true false
输入样例5:
多个题目,题号顺序与输入顺序不同。例如:
2
*#N:2 #Q:1+1= #A:2
*#N:1 #Q:5+5= #A:10
*#A:10 #A:2
end
输出样例5:
在这里给出相应的输出。例如:
5+5=~10
1+1=~2
true true
输入样例6:
含多余的空格符。例如:
1
*#N:1 #Q: The starting point of the Long March is #A:ruijin
*#A:ruijin
end
输出样例6:
在这里给出相应的输出。例如:
The starting point of the Long March is~ruijin
true
输入样例7:
含多余的空格符。例如:
1
*#N: 1 #Q: 5 +5= #A:10
*#A:10
end
输出样例7:
在这里给出相应的输出。例如:
5 +5=~10
true
分析
第一次题目较简单,只需要额外设计三个类:Query(题目),TestPaper(试卷),AnswerSheet(答卷)。
第一次的重点应该是学会使用正则表达式,List,以及遵循单一职责原则。
以下是我的代码
点击查看代码
import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
class Query {
private int number;
private String question;
private String standardAnswer;
public Query(int number, String question, String standardAnswer) {
this.number=number;
this.question=question;
this.standardAnswer=standardAnswer;
}
public int getNumber() {
return number;
}
public String getQuestion() {
return question;
}
public String getStandardAnswer() {
return standardAnswer;
}
public boolean checkAnswer(String userAnswer) {
return this.standardAnswer.equals(userAnswer);
}
}
class TestPaper {
private List<Query> queries=new ArrayList<>();
public void addQuery(Query query){
queries.add(query);
}
public Query getQueryByNumber(int number) {
for(Query query:queries){
if(query.getNumber()==number) {
return query;
}
}
return null;
}
}
class AnswerSheet{
private TestPaper testPaper;
private List<String> userAnswers=new ArrayList<>();
private List<Boolean> judgments=new ArrayList<>();
public AnswerSheet(TestPaper testPaper) {
this.testPaper=testPaper;
}
public void addAnswer(String answer) {
userAnswers.add(answer);
}
public void gradeAnswers() {
for (int i=0;i<userAnswers.size();i++){
Query query=testPaper.getQueryByNumber(i+1);
if(query!=null){
boolean judgment=query.checkAnswer(userAnswers.get(i));
judgments.add(judgment);
}
}
}
public void printResults() {
for(int i=0;i<userAnswers.size();i++){
Query query=testPaper.getQueryByNumber(i+1);
if(query!=null){
System.out.println(query.getQuestion()+"~"+userAnswers.get(i));
}
}
StringBuilder sb=new StringBuilder();
for(Boolean judgment:judgments) {
if(sb.length()>0){
sb.append(" ");
}
sb.append(judgment);
}
System.out.println(sb.toString());
}
}
public class Main{
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int queryCount=Integer.parseInt(scanner.nextLine());
TestPaper testPaper=new TestPaper();
for(int i=0;i<queryCount;i++) {
String line=scanner.nextLine();
String[] parts=line.split("#N:| #Q:| #A:");
int number=Integer.parseInt(parts[1].trim());
String question=parts[2].trim();
String standardAnswer=parts[3].trim();
Query query=new Query(number,question,standardAnswer);
testPaper.addQuery(query);
}String Line=scanner.nextLine();
AnswerSheet answerSheet=new AnswerSheet(testPaper);
for(int i=0;i<queryCount;i++){
String answer;
if (Line.equals("end")){
break;
}
answer=Line.split("#A:")[i+1].trim();
answerSheet.addAnswer(answer);
}
answerSheet.gradeAnswers();
answerSheet.printResults();
}
}
类图

下面对代码进行解释:
1.Query类表示一个题目,包括题号、问题和标准答案,并提供了获取题号、问题、标准答案以及检查答案是否正确的方法。
2.TestPaper类表示一套试卷,包括了多个题目,可以添加题目和根据题号获取题目的功能。
3.AnswerSheet类表示学生的答题卡,包括了试卷信息、学生的答案列表、判定列表,以及添加答案、评分和打印结果的功能。
4.Main类是程序的入口,通过控制台输入来录入题目信息和学生答案,arsenal通过调用相应的方法实现整个考试系统的运行。
在Main类的main方法中:
首先通过Scanner从控制台读取题目数量,并创建一个TestPaper对象。
然后循环读取每道题目的信息,创建Query对象并添加到TestPaper中。
接着循环读取学生的答案,创建AnswerSheet对象并添加学生答案。
最后对学生答案进行评分,并打印每道题目的问题和学生答案,以及整体的判定结果。
第二次最后一题
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-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=~22~false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:5 8 0~13
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、提示错误的试卷号
如果答案信息中试卷的编号找不到,则输出”the test paper number does not exist”,参见样例9。
设计建议:
参考答题判题程序-1,建议增加答题类,类的内容以及类之间的关联自行设计。
输入样例1:
一张试卷一张答卷。试卷满分不等于100。例如:
*#N:1 #Q:1+1= #A:2
*#N:2 #Q:2+2= #A:4
*#T:1 1-5 2-8
*#S:1 #A:5 #A:22
end
输出样例1:
在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
2+2=22false
0 0~0
输入样例2:
一张试卷一张答卷。试卷满分不等于100。例如:
*#N:1 #Q:1+1= #A:2
*#N:2 #Q:2+2= #A:4
*#T:1 1-70 2-30
*#S:1 #A:5 #A:22
end
输出样例2:
在这里给出相应的输出。例如:
1+1=5false
2+2=22false
0 0~0
输入样例3:
一张试卷、一张答卷。各类信息混合输入。例如:
*#N:1 #Q:1+1= #A:2
*#N:2 #Q:2+2= #A:4
*#T:1 1-70 2-30
*#N:3 #Q:3+2= #A:5
*#S:1 #A:5 #A:4
end
输出样例:
在这里给出相应的输出。例如:
1+1=5false
2+2=4true
0 30~30
输入样例4:
试卷题目的顺序与题号不一致。例如:
*#N:1 #Q:1+1= #A:2
*#N:2 #Q:2+2= #A:4
*#T:1 2-70 1-30
*#N:3 #Q:3+2= #A:5
*#S:1 #A:5 #A:22
end
输出样例:
在这里给出相应的输出。例如:
2+2=5false
1+1=22false
0 0~0
输入样例5:
乱序输入。例如:
*#N:3 #Q:3+2= #A:5
*#N:2 #Q:2+2= #A:4
*#T:1 3-70 2-30
*#S:1 #A:5 #A:22
*#N:1 #Q:1+1= #A:2
end
输出样例:
在这里给出相应的输出。例如:
3+2=5true
2+2=22false
70 0~70
输入样例6:
乱序输入+两份答卷。例如:
*#N:3 #Q:3+2= #A:5
*#N:2 #Q:2+2= #A:4
*#T:1 3-70 2-30
*#S:1 #A:5 #A:22
*#N:1 #Q:1+1= #A:2
*#S:1 #A:5 #A:4
end
输出样例:
在这里给出相应的输出。例如:
3+2=5true
2+2=22false
70 0~70
3+2=5true
2+2=4true
70 30~100
输入样例7:
乱序输入+分值不足100+两份答卷。例如:
*#N:3 #Q:3+2= #A:5
*#N:2 #Q:2+2= #A:4
*#T:1 3-7 2-6
*#S:1 #A:5 #A:22
*#N:1 #Q:1+1= #A:2
*#S:1 #A:5 #A:4
end
输出样例:
在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
3+2=5true
2+2=22false
7 0~7
3+2=5true
2+2=4true
7 6~13
输入样例8:
乱序输入+分值不足100+两份答卷+答卷缺失部分答案。例如:
*#N:3 #Q:3+2= #A:5
*#N:2 #Q:2+2= #A:4
*#T:1 3-7 2-6
*#S:1 #A:5 #A:22
*#N:1 #Q:1+1= #A:2
*#T:2 2-5 1-3 3-2
*#S:2 #A:5 #A:4
end
输出样例:
在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
alert: full score of test paper2 is not 100 points
3+2=5true
2+2=22false
7 0~7
2+2=5false
1+1=4false
answer is null
0 0 0~0
输入样例9:
乱序输入+分值不足100+两份答卷+无效的试卷号。例如:
*#N:3 #Q:3+2= #A:5
*#N:2 #Q:2+2= #A:4
*#T:1 3-7 2-6
*#S:3 #A:5 #A:4
end
输出样例:
在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
The test paper number does not exist
分析
第二次题目难度还行,增加了试卷信息和答卷信息,以及试卷总分警示,提示错误的试卷号。
第二次题目重点是学习并使用HashMap。
以下为我的代码
点击查看代码
import java.util.*;
class Query{
String number;
String question;
String answer;
public Query(String number, String question, String answer) {
this.number=number;
this.question=question;
this.answer=answer;
}
}
class TestPaper{
String paperNumber;
Map<String,Integer>queryScores;
public TestPaper(String paperNumber){
this.paperNumber=paperNumber;
this.queryScores=new HashMap<>();
}
public void addQuestionScore(String queryNumber, int score) {
queryScores.put(queryNumber,score);
}
}
class AnswerSheet {
String paperNumber;
List<String> answers;
public AnswerSheet(String paperNumber) {
this.paperNumber=paperNumber;
this.answers=new ArrayList<>();
}
public void addAnswer(String answer) {
answers.add(answer);
}
}
public class Main{
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
List<Query> querys=new ArrayList<>();
List<TestPaper> testPapers=new ArrayList<>();
List<AnswerSheet> answerSheets=new ArrayList<>();
String input;
while (!(input=scanner.nextLine()).equals("end")) {
if (input.startsWith("#N:")){
String[] parts=input.split("\\s+");
String number=parts[0].substring(3);
String question=parts[1].substring(3);
String answer=parts[2].substring(3);
querys.add(new Query(number,question,answer));
}else if(input.startsWith("#T:")){
String[] parts = input.split("\\s+");
String paperNumber=parts[0].substring(3);
TestPaper testPaper=new TestPaper(paperNumber);
for (int i=1;i<parts.length;i++){
String[] pair=parts[i].split("-");
testPaper.addQuestionScore(pair[0],Integer.parseInt(pair[1]));
}
testPapers.add(testPaper);
} else if(input.startsWith("#S:")){
String[]parts=input.split("\\s+");
String paperNumber=parts[0].substring(3);
AnswerSheet answerSheet=new AnswerSheet(paperNumber);
for(int i=1;i<parts.length;i++){
answerSheet.addAnswer(parts[i].substring(3));
}
answerSheets.add(answerSheet);
}
}
for(TestPaper testPaper:testPapers){
int totalScore=0;
for(Map.Entry<String,Integer>entry:testPaper.queryScores.entrySet()){
totalScore+=entry.getValue();
}
if(totalScore!=100){
System.out.println("alert: full score of test paper"+testPaper.paperNumber+" is not 100 points");
}
}
for(AnswerSheet answerSheet:answerSheets) {
boolean hasAnswer=false;
for(String answer:answerSheet.answers) {
if(!answer.isEmpty()){
hasAnswer=true;
break;
}
}
if(!hasAnswer){
continue;
}
for(int i=0;i<querys.size();i++){
String answer=i<answerSheet.answers.size()?answerSheet.answers.get(i):"";
if (!answer.isEmpty()){
Query query=querys.get(i);
String correctAnswer=query.answer;
boolean isCorrect=answer.equals(correctAnswer);
System.out.println(""+query.question+"~"+answer+"~"+isCorrect);
}
}
StringBuilder scoreString=new StringBuilder();
int totalScore=0;
boolean firstAnswer=true;
for (int i=0;i<querys.size();i++){
Query query=querys.get(i);
String answer=i<answerSheet.answers.size()?answerSheet.answers.get(i):"";
if(!answer.isEmpty()){
String correctAnswer=query.answer;
boolean isCorrect=answer.equals(correctAnswer);
int score=testPapers.get(Integer.parseInt(answerSheet.paperNumber)-1).queryScores.getOrDefault(query.number,0);
if(isCorrect){
totalScore+=score;
}else{
score=0;
}
if(firstAnswer){
firstAnswer=false;
}else{
scoreString.append(" ");
}
scoreString.append(score);
}
}
scoreString.append("~").append(totalScore);
System.out.println(scoreString.toString());
}
}
}
类图

下面对代码进行解释:
本次代码有点缺陷,未能做到当处理乱序输入 题目号有缺失,而且忘记了保证封闭性,那些数据未用private修饰。这次作业我只做到了2/3的要求,还有部分要求我开始时没看懂,导致后期去添加时发现十分困难。
Query类表示一个题目,包括题号、问题和标准答案,并提供了获取题号、问题、标准答案以及检查答案是否正确的方法。
TestPaper类表示一套试卷,包括了多个题目,可以添加题目和根据题号获取题目的功能。
AnswerSheet类表示学生的答题卡,包括了试卷信息、学生的答案列表、判定列表,以及添加答案、评分和打印结果的功能。
Main类程序的入口,通过控制台输入来录入题目信息和学生答案,arsenal通过调用相应的方法实现整个考试系统的运行。
在Main类的main方法中:
首先通过Scanner从控制台读取题目数量,并创建一个TestPaper对象。
然后循环读取每道题目的信息,创建Query对象并添加到TestPaper中。
接着循环读取学生的答案,创建AnswerSheet对象并添加学生答案。
最后对学生答案进行评分,并打印每道题目的问题和学生答案,以及整体的判定结果。
第三题的最后一题
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-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。
本题暂不考虑出现多张答卷的信息的情况。
输入样例1:
简单输入,不含删除题目信息。例如:
*#N:1 #Q:1+1= #A:2
*#T:1 1-5
*#X:20201103 Tom
*#S:1 20201103 #A:1-5
end
输出样例1:
在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
20201103 Tom: 0~0
输入样例2:
简单输入,答卷中含多余题目信息(忽略不计)。例如:
*#N:1 #Q:1+1= #A:2
*#T:1 1-5
*#X:20201103 Tom
*#S:1 20201103 #A:1-2 #A:2-3
end
输出样例3
简单测试,含删除题目信息。例如:
alert: full score of test paper1 is not 100 points
1+1=2true
20201103 Tom: 5~5
输入样例3:
简单测试,含删除题目信息。例如:
*#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-20201105 Www
*#S:1 20201103 #A:1-5 #A:2-4
*#D:N-2
end
输出样例3:
在这里给出相应的输出,第二题由于被删除,输出题目失效提示。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
the question 2 invalid~0
20201103 Tom: 0 0~0
输入样例4:
简单测试,含试卷无效题目的引用信息以及删除题目信息(由于题目本身无效,忽略)。例如:
*#N:1 #Q:1+1= #A:2
*#N:2 #Q:2+2= #A:4
*#T:1 1-5 3-8
*#X:20201103 Tom-20201104 Jack-20201105 Www
*#S:1 20201103 #A:1-5 #A:2-4
*#D:N-2
end
输出样例4:
输出不存在的题目提示信息。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
non-existent question~0
20201103 Tom: 0 0~0
输入样例5:
综合测试,含错误格式输入、有效删除以及无效题目引用信息。例如:
*#N:1 +1= #A:2
*#N:2 #Q:2+2= #A:4
*#T:1 1-5 2-8
*#X:20201103 Tom-20201104 Jack-20201105 Www
*#S:1 20201103 #A:1-5 #A:2-4
D:N-2
end
输出样例5:
在这里给出相应的输出。例如:
wrong format:#N:1 +1= #A:2
alert: full score of test paper1 is not 100 points
non-existent question~0
the question 2 invalid~0
20201103 Tom: 0 0~0
输入样例6:
综合测试,含错误格式输入、有效删除、无效题目引用信息以及答案没有输入的情况。例如:
*#N:1 +1= #A:2
*#N:2 #Q:2+2= #A:4
*#T:1 1-5 2-8
*#X:20201103 Tom-20201104 Jack-20201105 Www
*#S:1 20201103 #A:1-5
*#D:N-2
end
输出样例6:
答案没有输入的优先级最高。例如:
wrong format:#N:1 +1= #A:2
alert: full score of test paper1 is not 100 points
non-existent question~0
answer is null
20201103 Tom: 0 0~0
输入样例7:
综合测试,正常输入,含删除信息。例如:
*#N:2 #Q:2+2= #A:4
*#N:1 #Q:1+1= #A:2
*#T:1 1-5 2-8
*#X:20201103 Tom-20201104 Jack-20201105 Www
*#S:1 20201103 #A:2-4 #A:1-5
*#D:N-2
end
输出样例7:
例如:
alert: full score of test paper1 is not 100 points
1+1=5false
the question 2 invalid~0
20201103 Tom: 0 0~0
输入样例8:
综合测试,无效的试卷引用。例如:
*#N:1 #Q:1+1= #A:2
*#T:1 1-5
*#X:20201103 Tom
*#S:2 20201103 #A:1-5 #A:2-4
end
输出样例8:
例如:
alert: full score of test paper1 is not 100 points
The test paper number does not exist
输入样例9:
无效的学号引用。例如:
*#N:1 #Q:1+1= #A:2
*#T:1 1-5
*#X:20201106 Tom
*#S:1 20201103 #A:1-5 #A:2-4
end
输出样例9:
答案照常输出,判分时提示错误。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
20201103 not found
输入样例10:
信息可打乱顺序输入:序号不是按大小排列,各类信息交错输入。但本题不考虑引用的题目在被引用的信息之后出现的情况(如试卷引用的所有题目应该在试卷信息之前输入),所有引用的数据应该在被引用的信息之前给出。例如:
*#N:3 #Q:中国第一颗原子弹的爆炸时间 #A:1964.10.16
*#N:1 #Q:1+1= #A:2
*#X:20201103 Tom-20201104 Jack-20201105 Www
*#T:1 1-5 3-8
*#N:2 #Q:2+2= #A:4
*#S:1 20201103 #A:1-5 #A:2-4
end
输出样例10:
答案按试卷中的题目顺序输出。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
中国第一颗原子弹的爆炸时间4false
20201103 Tom: 0 0~0
以下是我的代码
点击查看代码
import java.util.*;
class Query {
int number;
String question;
String answer;
public Query(int number, String question, String answer) {
this.number = number;
this.question = question;
this.answer = answer;
}
}
class TestPaper {
int paperNumber;
Map<Integer, Integer> queryScores;
public TestPaper(int paperNumber) {
this.paperNumber = paperNumber;
this.queryScores = new HashMap<>();
}
public void addQuestionScore(int queryNumber, int score) {
queryScores.put(queryNumber, score);
}
}
class AnswerSheet {
int paperNumber;
List<String> answers;
public AnswerSheet(int paperNumber) {
this.paperNumber = paperNumber;
this.answers = new ArrayList<>();
}
public void addAnswer(String answer) {
answers.add(answer);
}
}
class InputProcessor {
public static void processQueryInput(String input, List<Query> queries) {
String[] parts = input.split("\\\\s+");
int number = Integer.parseInt(parts[0].substring(3));
String question = parts[1].substring(3);
String answer = parts[2].substring(3);
queries.add(new Query(number, question, answer));
}
public static void processTestPaperInput(String input, List<TestPaper> testPapers) {
String[] parts = input.split("\\\\s+");
int paperNumber = Integer.parseInt(parts[0].substring(3));
TestPaper testPaper = new TestPaper(paperNumber);
for (int i = 1; i < parts.length; i++) {
String[] pair = parts[i].split("-");
testPaper.addQuestionScore(Integer.parseInt(pair[0]), Integer.parseInt(pair[1]));
}
testPapers.add(testPaper);
}
public static void processAnswerSheetInput(String input, List<AnswerSheet> answerSheets) {
String[] parts = input.split("\\\\s+");
int paperNumber = Integer.parseInt(parts[0].substring(3));
AnswerSheet answerSheet = new AnswerSheet(paperNumber);
for (int i = 2; i < parts.length; i++) {
answerSheet.addAnswer(parts[i].substring(5));
}
answerSheets.add(answerSheet);
}
public static void processStudentInput(String input, Map<String, String> students) {
String[] parts = input.substring(3).split(" ");
for (int i = 0; i < parts.length; i += 2) {
String studentId = parts[i];
String studentName = parts[i + 1];
students.put(studentId, studentName);
}
}
public static void processDeletionInput(String input, List<TestPaper> testPapers) {
String[] parts = input.split("\\\\s+");
String[] deletionInfo = parts[1].split("-");
int paperNumber = Integer.parseInt(deletionInfo[0]);
int deletedQuestionNumber = Integer.parseInt(deletionInfo[1]);
for (TestPaper testPaper : testPapers) {
if (testPaper.paperNumber == paperNumber) {
testPaper.queryScores.put(deletedQuestionNumber, 0); // Mark as invalid
break;
}
}
}
}
class OutputProcessor {
public static void evaluateTestPapers(List<TestPaper> testPapers) {
for (TestPaper testPaper : testPapers) {
int totalScore = 0;
for (int score : testPaper.queryScores.values()) {
totalScore += score;
}
if (totalScore != 100) {
System.out.println("alert: full score of test paper" + testPaper.paperNumber + " is not 100 points");
}
}
}
public static void gradeAnswerSheets(List<Query> queries, List<TestPaper> testPapers, List<AnswerSheet> answerSheets, Map<String, String> students) {
for (AnswerSheet answerSheet : answerSheets) {
boolean hasAnswer = false;
for (String answer : answerSheet.answers) {
if (!answer.isEmpty()) {
hasAnswer = true;
break;
}
}
if (!hasAnswer) {
continue;
}
for (int i = 0; i < queries.size(); i++) {
String answer = i < answerSheet.answers.size() ? answerSheet.answers.get(i) : "";
if (!answer.isEmpty()) {
Query query = queries.get(i);
String correctAnswer = query.answer;
boolean isCorrect = answer.equals(correctAnswer);
System.out.println(query.question + "~" + answer + "~" + isCorrect);
}
}
StringBuilder scoreString = new StringBuilder();
int totalScore = 0;
boolean firstAnswer = true;
for (int i = 0; i < queries.size(); i++) {
Query query = queries.get(i);
String answer = i < answerSheet.answers.size() ? answerSheet.answers.get(i) : "";
if (!answer.isEmpty()) {
String correctAnswer = query.answer;
boolean isCorrect = answer.equals(correctAnswer);
int score = testPapers.get(answerSheet.paperNumber - 1).queryScores.getOrDefault(query.number, 0);
if (isCorrect) {
totalScore += score;
} else {
score = 0;
}
if (!firstAnswer) {
scoreString.append(" ");
}
scoreString.append(score);
firstAnswer = false;
}
}
scoreString.append("~").append(totalScore);
for (Map.Entry<String, String> entry : students.entrySet()) {
String studentNumber = entry.getKey();
String studentName = entry.getValue();
System.out.println(studentNumber + " " + studentName + ": " + scoreString.toString());
}
}
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<Query> queries = new ArrayList<>();
List<TestPaper> testPapers = new ArrayList<>();
List<AnswerSheet> answerSheets = new ArrayList<>();
Map<String, String> students = new HashMap<>();
String input;
while (!(input = scanner.nextLine()).equals("end")) {
if (input.startsWith("#N:")) {
InputProcessor.processQueryInput(input, queries);
} else if (input.startsWith("#T:")) {
InputProcessor.processTestPaperInput(input, testPapers);
} else if (input.startsWith("#S:")) {
InputProcessor.processAnswerSheetInput(input, answerSheets);
} else if (input.startsWith("#X:")) {
InputProcessor.processStudentInput(input, students);
} else if (input.startsWith("#D:")) {
InputProcessor.processDeletionInput(input, testPapers);
}
}
OutputProcessor.evaluateTestPapers(testPapers);
OutputProcessor.gradeAnswerSheets(queries, testPapers, answerSheets, students);
}
}
类图

下面对代码进行解释
Query类表示一个问题,包括问题编号、问题内容和答案。
TestPaper类表示一张试卷,包括试卷编号和问题编号与得分的映射关系。
AnswerSheet类表示一张答题卡,包括答题卡编号和学生的答案列表。
InputProcessor类包含了处理输入的方法,分别处理问题输入、试卷输入、答题卡输入、学生信息输入以及试卷删除操作。
OutputProcessor类包含了评估试卷和评分答题卡的方法。
Main类为程序的入口,通过输入不同格式的指令来执行相应的操作,包括添加问题、试卷、答题卡,添加学生信息,以及删除试卷等操作。
在Main类的main方法中,通过循环读取输入直到输入"end"结束,根据输入的指令调用对应的处理方法来处理数据。最后通过OutputProcessor类的方法对试卷进行评估和对答题卡进行评分。
本次PTA我做的很差,许多测试点都没有过,因为上次的代码没有分出多个类,导致这次代码的增加功能十分困难,而且经常会有编译错误,当我改成多个类之后,发现有许多地方都有问题,导致这次PTA做得十分失败。
改进建议
(1)在每个类旁边写注释,变量名应该用中文对应英文,最好加注释,防止改动的时候找不到位置,以及不知道这个变量是什么,干什么的。
(2)OutputProcessor 类 模块化:将评分逻辑拆分为较小的方法,以提高可读性和可维护性。
总结
(1)
这三次PTA十分有意义,让我看到了我的不足与他人的差距。我学会了
1.正则表达式。
2.ArrayList,LinkedList和HashMap的使用。
3.对单一职责原则的理解(每个类负责一件事),还要确保封装性。3.对单一职责原则的理解(每个类负责一件事),还要确保封装性。
4.调试代码
(2)
关于List,我学得并不行,有时会把自己搞晕,不知道获取的数据去哪了,还有删除我用得并不熟练。在之后的时间里,我要去认真去看看课,以及看看网上的处理法。
(3)
对类的处理并不清晰,就是因为之前未分出多个类,导致后来修改异常艰难,老是会报错。下一次要考类之间的关系,所以我要先考虑清楚在写代码。
(4)
最后一次没做完也有自身的原因,我看到最后一题后,心里十分茫然,不知从何下手,开始有点逃避问题。到了最后,时间不够,自身水平也不行,导致最后一次分数十分低。我面对之后的问题应该好好思考,不懂的多问问,不做“鸵鸟”。