OO第二次作业
三次作业实现
一、PTA4
- 题干内容
设计实现答题程序,模拟一个小型的测试,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。本题在答题判题程序-3基础上新增的内容统一附加在输出格式说明之后,用粗体标明。
输入格式:
程序输入信息分五种,信息可能会打乱顺序混合输入。
1、题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。
2、试卷信息格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案 格式约束: 1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。 2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。 样例:#N:1 #Q:1+1= #A:2 #N:2 #Q:2+2= #A:4
试卷信息为独行输入,一行为一张试卷,多张卷可分多行输入数据。
3、学生信息格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值+" "+题目编号+"-"+题目分值+... 格式约束: 题目编号应与题目信息中的编号对应。 一行信息中可有多项题目编号与分值。 样例:#T:1 3-5 4-8 5-2
学生信息只输入一行,一行中包括所有学生的信息,每个学生的信息包括学号和姓名,格式如下。
4、答卷信息格式:"#X:"+学号+" "+姓名+"-"+学号+" "+姓名....+"-"+学号+" "+姓名 格式约束: 答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。 样例: #S:1 #A:5 #A:22 1是试卷号 5是1号试卷的顺序第1题的题目答案
5、删除题目信息答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序号与试 卷信息中的题目顺序相对应。答卷中: 格式:"#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的答案 注意:不要混淆顺序号与题号
删除题目信息为独行输入,每一行为一条删除信息,多条删除信息可分多行输入。该信息用于删除一道题目信息,题目被删除之后,引用该题目的试卷依然有效,但被删除的题目将以0分计,同时在输出答案时,题目内容与答案改为一条失效提示,例如:”the question 2 invalid~0”
答题信息以一行"end"标记结束,"end"之后的信息忽略。格式:"#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=~5~false the question 2 invalid~0 20201103 Tom: 0 0~0
输出格式:
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" 。
样例:
answer is null
3+2=5true
4+6=22false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
4、被删除的题目提示信息格式:学号+" "+姓名+": "+题目得分+" "+....+题目得分+"~"+总分 格式约束: 1、没有输入答案的题目、被删除的题目、答案错误的题目计0分 2、判题信息的顺序与输入答题信息中的顺序相同 样例:20201103 Tom: 0 0~0 根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
当某题目被试卷引用,同时被删除时,答案中输出提示信息。样例见第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
6、格式错误提示信息输入: #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
输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。
例如:wrong format:2 #Q:2+2= #4
7、试卷号引用错误提示输出
如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”,答卷中的答案不用输出,参见样例8。
8、学号引用错误提示信息
如果答卷中的学号信息不在学生列表中,答案照常输出,判分时提示错误。参见样例9。
本次作业新增内容:
1、输入选择题题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。格式:"#Z:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案 格式基本的约束与一般的题目输入信息一致。
多选题输出:新增约束:标准答案中如果包含多个正确答案(多选题),正确答案之间用英文空格分隔。 例如: #Z:2 #Q:宋代书法有苏黄米蔡四家,分别是: #A:苏轼 黄庭坚 米芾 蔡襄
输出格式与一般答卷题目的输出一致,判断结果除了true、false,增加一项”partially correct”表示部分正确。
多选题给分方式:答案包含所有正确答案且不含错误答案给满分; 包含一个错误答案或完全没有答案给0分; 包含部分正确答案且不含错误答案给一半分,如果一半分值为小数,按截尾规则只保留整数部分。
2、输入填空题题目信息例如: #N:1 #Q:1+1= #A:2 #Z:2 #Q:党十八大报告提出要加强()建设。A 政务诚信 B 商务诚信 C社会诚信 D司法公信 #A:A B C D #T:1 1-5 2-9 #X:20201103 Tom #S:1 20201103 #A:1-5 #A:2-A C end 输出: alert: full score of test paper1 is not 100 points 1+1=~5~false 党十八大报告提出要加强()建设。A 政务诚信 B 商务诚信 C社会诚信 D司法公信~A C~partially correct 20201103 Tom: 0 4~4
题目信息为独行输入,一行为一道题,多道题可分多行输入。
填空题输出:格式:"#K:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案 格式基本的约束与一般的题目输入信息一致。 例如:#K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴
输出格式与一般答卷题目的输出一致,判断结果除了true、false,增加一项”partially correct”表示部分正确。
填空题给分方式:
答案与标准答案内容完全匹配给满分,包含一个错误字符或完全没有答案给0分,包含部分正确答案且不含错误字符给一半分,如果一半分值为小数,按截尾规则只保留整数部分。
3、输出顺序变化例如: #N:1 #Q:1+1= #A:2 #K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴 #T:1 1-5 2-10 #X:20201103 Tom #S:1 20201103 #A:1-5 #A:2-瑶琴 end 输出: alert: full score of test paper1 is not 100 points 1+1=~5~false 古琴在古代被称为:~瑶琴~partially correct 20201103 Tom: 0 5~5
只要是正确格式的信息,可以以任意的先后顺序输入各类不同的信息。比如试卷可以出现在题目之前,删除题目的信息可以出现在题目之前等。
4、多张试卷信息例如: #T:1 1-5 2-10 #N:1 #Q:1+1= #A:2 #K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴 #X:20201103 Tom #S:1 20201103 #A:1-5 #A:2-古筝 end 输出: alert: full score of test paper1 is not 100 points 1+1=~5~false 古琴在古代被称为:~古筝~false 20201103 Tom: 0 0~0
本题考虑多个同学有多张不同试卷的答卷的情况。输出顺序优先级为学号、试卷号,按从小到大的顺序先按学号排序,再按试卷号。
新增的题目异常情况的处理与一般题目相同,具体样例参考上一次大作业的样例说明:例如: #T:1 1-5 2-10 #T:2 1-8 2-21 #N:1 #Q:1+1= #A:2 #S:2 20201103 #A:1-2 #A:2-古筝 #S:1 20201103 #A:1-5 #A:2-瑶琴或七弦琴 #S:1 20201104 #A:1-2 #A:2-瑟 #S:2 20201104 #A:1-5 #A:2-七弦琴 #X:20201103 Tom-20201104 Jack #K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴 end 输出: alert: full score of test paper1 is not 100 points alert: full score of test paper2 is not 100 points 1+1=~5~false 古琴在古代被称为:~瑶琴或七弦琴~true 20201103 Tom: 0 10~10 1+1=~2~true 古琴在古代被称为:~古筝~false 20201103 Tom: 8 0~8 1+1=~2~true 古琴在古代被称为:~瑟~false 20201104 Jack: 5 0~5 1+1=~5~false 古琴在古代被称为:~七弦琴~partially correct 20201104 Jack: 0 10~10
输入样例1:
多选题测试,不含删除。例如:
输出样例1:#N:1 #Q:1+1= #A:2 #Z:2 #Q:党十八大报告提出要加强()建设。A 政务诚信 B 商务诚信 C社会诚信 D司法公信 #A:A B C D #T:1 1-5 2-9 #X:20201103 Tom #S:1 20201103 #A:1-5 #A:2-A C end
在这里给出相应的输出。例如:
输入样例2:alert: full score of test paper1 is not 100 points 1+1=~5~false 党十八大报告提出要加强()建设。A 政务诚信 B 商务诚信 C社会诚信 D司法公信~A C~partially correct 20201103 Tom: 0 4~4
填空题测试,不含删除。例如:
输出样例2:#N:1 #Q:1+1= #A:2 #K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴 #T:1 1-5 2-10 #X:20201103 Tom #S:1 20201103 #A:1-5 #A:2-瑶琴 end
在这里给出相应的输出。例如:
输入样例3:alert: full score of test paper1 is not 100 points 1+1=~5~false 古琴在古代被称为:~瑶琴~partially correct 20201103 Tom: 0 5~5
乱序测试,不含删除。例如:
输出样例3:#T:1 1-5 2-10 #N:1 #Q:1+1= #A:2 #K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴 #X:20201103 Tom #S:1 20201103 #A:1-5 #A:2-古筝 end
在这里给出相应的输出。例如:
输入样例4:alert: full score of test paper1 is not 100 points 1+1=~5~false 古琴在古代被称为:~古筝~false 20201103 Tom: 0 0~0
两个同学多张不同试卷的答卷,不含删除。例如:
输出样例4:#T:1 1-5 2-10 #T:2 1-8 2-21 #N:1 #Q:1+1= #A:2 #S:2 20201103 #A:1-2 #A:2-古筝 #S:1 20201104 #A:1-2 #A:2-瑟 #S:1 20201103 #A:1-5 #A:2-瑶琴或七弦琴 #S:2 20201104 #A:1-5 #A:2-七弦琴 #X:20201103 Tom-20201104 Jack #K:2 #Q:古琴在古代被称为: #A:瑶琴或七弦琴 end
在这里给出相应的输出。例如:alert: full score of test paper1 is not 100 points alert: full score of test paper2 is not 100 points 1+1=~5~false 古琴在古代被称为:~瑶琴或七弦琴~true 20201103 Tom: 0 10~10 1+1=~2~true 古琴在古代被称为:~古筝~false 20201103 Tom: 8 0~8 1+1=~2~true 古琴在古代被称为:~瑟~false 20201104 Jack: 5 0~5 1+1=~5~false 古琴在古代被称为:~七弦琴~partially correct 20201104 Jack: 0 10~10
- 设计与分析
这一次怎么说呢,其实已经没有什么太大的设计了,都是在以前的基础上往上加内容,其实这一次作业做的迷迷糊糊,没有很清楚的思路,主要是借鉴前人大佬的经验,加以修改,在这里就不多说了。而且这一次作业得分为0,说的也实在是在误人子弟。 - 踩坑心得
关于这一次的踩坑心得呢,其实这么说吧,听从一个大佬的建议使用了TreeSet来储存,还涉及到了接口(当时还没有开始学),但是由于自身层次不够,对于这个都不是很清楚,花费了大量的时间去学习这些陌生的知识,并且掌握并不透彻,属于是在无效学习了,可能是导致后续一直没有办法完成程序的很大原因。总的来说就是还是要量力而行吧,别太好高骛远,适合别人的方法未必适合自己,是这么说的。 - 代码实现
点击查看代码
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.HashMap;
import java.util.TreeSet;
class Question{
String num;
String concent;
int value;
boolean effect=true;//有效性
int iswhich;
Question(){}
Question(String num,String concent,int iswhich){
this.num=num;
this.concent=concent;
this.iswhich=iswhich;
}
void setIswhich(int iswhich){
this.iswhich=iswhich;
}
int getIswhich(){
return this.iswhich;
}
void setNum(String num){
this.num=num;
}
String getNum(){
return this.num;
}
void setConcent(String concent){
this.concent=concent;
}
String getConcent(){
return this.concent;
}
void setValue(int value){
this.value=value;
}
int getValue(){
return this.value;
}
void setEffect(boolean effect){
this.effect=effect;
}
boolean getEffect(){
return this.effect;
}
}
class mulityQuestion extends Question{//多选
String[] standardAnswer;
//int iswhich=1;
mulityQuestion(){}
mulityQuestion(String num,String concent,String[] standardAnswer){
super(num,concent,1);
this.standardAnswer=standardAnswer;
}
void setStandardAnswer(String[] standardAnswer){
this.standardAnswer=standardAnswer;
}
String[] getStandardAnswer(){
return this.standardAnswer;
}
// void setIswhich(int iswhich){
// this.iswhich=iswhich;
// }
// int getIswhich(){
// return this.iswhich;
// }
void JudgeMulityAnswer(MulityAnswer answer){
boolean[] isTrue=new boolean[answer.getConcent().length];
for(int i=0;i<answer.getConcent().length;i++){
for(int j=0;j<this.standardAnswer.length;j++){
if(answer.getConcent()[i].equals(this.standardAnswer[j]))
isTrue[i]=true;
}
if(isTrue[i]==false){
answer.setIstrue(-1);
return ;
}
}
if(answer.getConcent().length<this.standardAnswer.length)
answer.setIstrue(0);
else
answer.setIstrue(1);
}
}
class fillQuestion extends Question{//填空
String standardAnswer;
//int iswhich=0;
fillQuestion(){}
fillQuestion(String num,String concent,String standardAnswer){
super(num,concent,0);
this.standardAnswer=standardAnswer;
}
void setStandardAnswer(String standardAnswer){
this.standardAnswer=standardAnswer;
}
String getStandardAnswer(){
return this.standardAnswer;
}
// void setIswhich(int iswhich){
// this.iswhich=iswhich;
// }
// int getIswhich(){
// return this.iswhich;
// }
void JudgeFillAnswer(FillAnswer answer){
if(this.standardAnswer.matches(".*"+answer.getConcent()+".*")){
if(this.standardAnswer.equals(answer.getConcent()))
answer.setIstrue(1);
else
answer.setIstrue(0);
}
else
answer.setIstrue(-1);
}
}
class commonQuestion extends Question{
String standardAnswer;
//int iswhich=-1;
commonQuestion(){}
commonQuestion(String num,String concent,String standardAnswer){
super(num,concent,-1);
this.standardAnswer=standardAnswer;
}
void setStandardAnswer(String standardAnswer){
this.standardAnswer=standardAnswer;
}
String getStandardAnswer(){
return this.standardAnswer;
}
void JudgeCommonAnswer(CommonAnswer answer){
if(this.standardAnswer.equals(answer.getConcent()))
answer.setIstrue(1);
else
answer.setIstrue(-1);
}
// void setIswhich(int iswhich){
// this.iswhich=iswhich;
// }
// int getIswhich(){
// return this.iswhich;
// }
}
// class testQuestion{
// Question question;
// int value;
// boolean effect=true;//有效性
// testQuestion(){}
// testQuestion(Question question,int value){
// this.question=question;
// this.value=value;
// this.effect=true;
// }
// void setValue(int value){
// this.value=value;
// }
// int getValue(){
// return this.value;
// }
// void setEffect(boolean effect){
// this.effect=effect;
// }
// boolean getEffect(){
// return this.effect;
// }
// }
class Papper{
String num;
HashMap<Integer,Question> question=new HashMap<>();//Integer是题目顺序
Papper(){}
Papper(String num){
this.num=num;
}
HashMap<Integer,Question> getHashMap(){
return this.question;
}
void setQuestion(Integer key,Question value){
question.put(key,value);
}
Question getQuestion(Integer key){
return question.get(key);
}
void setNum(String num){
this.num=num;
}
String getNum(){
return this.num;
}
int allScore(){
int sum=0;
for(Question value:question.values()){
if(value!=null)
if(value.getEffect())
sum+=value.getValue();
}
return sum;
}
}
// class Student{
// String stuNum;
// String name;
// }
class Answer{
int iswhich;
int isTrue;//0为半对,1为全对,-1为全错
Answer(int iswhich){
this.iswhich=iswhich;
}
void setIswhich(int iswhich){
this.iswhich=iswhich;
}
int getIswhich(){
return this.iswhich;
}
void setIstrue(int isTrue){
this.isTrue=isTrue;
}
int getIsTrue(){
return this.isTrue;
}
}
class FillAnswer extends Answer{//填空题
String concent;
FillAnswer(){
super(0);
}
FillAnswer(String concent){
super(0);
this.concent=concent;
}
void setConcent(String concent){
this.concent=concent;
}
String getConcent(){
return this.concent;
}
}
class MulityAnswer extends Answer{//选择题
String[] concent;
MulityAnswer(){
super(1);
}
MulityAnswer(String[] concent){
super(1);
this.concent=concent;
}
void setConcent(String[] concent){
this.concent=concent;
}
String[] getConcent(){
return this.concent;
}
}
class CommonAnswer extends Answer{//普通题
String concent;
CommonAnswer(){
super(-1);
}
CommonAnswer(String concent){
super(-1);
this.concent=concent;
}
void setConcent(String concent){
this.concent=concent;
}
String getConcent(){
return this.concent;
}
}
class AnswerPapper implements Comparable<AnswerPapper>{
boolean isfound;
String stuID;
String papperNum;
Papper papper;
int sumscore;
//String answerNum;
HashMap<Integer,Answer> concent=new HashMap<>();//Integer是题目顺序,Answer是答案
AnswerPapper(){}
AnswerPapper(String stuID,String papperNum,HashMap<Integer,Answer> concent){
this.stuID=stuID;
this.papperNum=papperNum;
this.concent=concent;
//this.isfound=false;
}
void setIsfound(boolean isfound){
this.isfound=isfound;
}
boolean getIsfound(){
return this.isfound;
}
void setStuID(String stuID){
this.stuID=stuID;
}
String getStuID(){
return this.stuID;
}
void setPapperNum(String papperNum){
this.papperNum=papperNum;
}
String getPapperNum(){
return this.papperNum;
}
void setPapper(Papper papper){
this.papper=papper;
}
Papper getPapper(){
return this.papper;
}
void setConcent(Integer key,Answer answer){
this.concent.put(key,answer);
}
Answer getConcent(Integer key){
return this.concent.get(key);
}
HashMap<Integer,Answer> getHashMap(){
return this.concent;
}
@Override
public int compareTo(AnswerPapper o){
if(Integer.parseInt(this.stuID)>Integer.parseInt(o.stuID))
return 1;
else if(Integer.parseInt(this.stuID)==Integer.parseInt(o.stuID)){
if(Integer.parseInt(this.papperNum)>Integer.parseInt(o.papperNum))
return 1;
else
return -1;
}
else
return -1;
}
}
public class Main{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
HashMap<String,Question> arr=new HashMap<>();//String为题目编号,存的是题库
HashMap<String,String> students=new HashMap<>();
HashMap<String,Papper> pappers=new HashMap<>();
TreeSet<AnswerPapper> answerPappers=new TreeSet<>();
String[] str=new String[1000];
int str_i=0;
do{
str[str_i]=input.nextLine();
str_i++;
}while(!str[str_i-1].equals("end"));
//str_i--;
//把全部不合规的输出并赋值空,剩下就都是合规的
String regex1="#Z:\\d+ +#Q:.+ +#A:.+";
Pattern pattern1=Pattern.compile(regex1);
String regex2="#K:\\d+ +#Q:.+ +#A:.+";
Pattern pattern2=Pattern.compile(regex2);
String regex3="#N:\\d+ +#Q:.+ +#A:.+";
Pattern pattern3=Pattern.compile(regex3);
String regex4="#D:N-[\\d]+";
Pattern pattern4=Pattern.compile(regex4);
String regex5="#T:\\d+ ((\\d+-\\d+)+)";
Pattern pattern5=Pattern.compile(regex5);
String regex6="^#X:\\d+\\s+\\S+\\s*(-\\s*\\d+\\s+\\S+)*$";
Pattern pattern6=Pattern.compile(regex6);
String regex7="^#S:( )*\\d+( )*\\w+\\s*(.*?)$";
Pattern pattern7=Pattern.compile(regex7);
// String regex8="^#S:\\d+\\s+\\d+\\s*(#A:\\d+-\\S+\\s*)*$";
// Pattern pattern8=Pattern.compile(regex8);
for(int i=0;i<str_i;i++){
Matcher matcher1=pattern1.matcher(str[i]);
Matcher matcher2=pattern2.matcher(str[i]);
Matcher matcher3=pattern3.matcher(str[i]);
Matcher matcher4=pattern4.matcher(str[i]);
Matcher matcher5=pattern5.matcher(str[i]);
Matcher matcher6=pattern6.matcher(str[i]);
Matcher matcher7=pattern7.matcher(str[i]);
// Matcher matcher8=pattern8.matcher(str[i]);
if(!matcher1.find()&&!matcher2.find()&&!matcher3.find()&&!matcher4.find()&&!matcher5.find()&&!matcher6.find()&&!matcher7.find()&&!str[i].equals("end")){
System.out.println("wrong format:"+str[i]);
str[i]="";
}
else if(str[i].equals("end"))
str[i]="";
}
//录题
for(int i=0;i<str_i;i++){
if(str[i].startsWith("#Z")){//选择题
//System.out.println("符合");
String[] ch=str[i].split("#Z:|#Q:|#A:");
String[] standardAnswer=ch[3].trim().split("\\s+");
Question question=new mulityQuestion(ch[1].trim(),ch[2].trim(),standardAnswer);//String num,String concent,String[] standardAnswer
arr.put(ch[1].trim(),question);
}
else if(str[i].startsWith("#K")){//填空题
String[] ch=str[i].split("#K:|#Q:|#A:");
Question question=new fillQuestion(ch[1].trim(),ch[2].trim(),ch[3].trim());
arr.put(ch[1].trim(),question);
}
else if(str[i].startsWith("#N")){
String[] ch=str[i].split("#N:|#Q:|#A:");
Question question=new commonQuestion(ch[1].trim(),ch[2].trim(),ch[3].trim());
arr.put(ch[1].trim(),question);
}
}
//录删除题目信息
for(int i=0;i<str_i;i++){
if(str[i].startsWith("#D")){
String[] ch=str[i].split("#D:N-");
arr.get(ch[1].trim()).setEffect(false);
}
}
//录入试卷
for(int i=0;i<str_i;i++){
if(str[i].startsWith("#T")){
String[] ch=str[i].split("#T:|\\s+");
Papper papper=new Papper(ch[1]);//String num
int k=1;//题目顺序号
for(int j=2;j<ch.length;j++){
String[] str1=ch[j].split("-");//ch[0]为题目编号,ch[1]为分值
if(arr.get(str1[0])==null){
papper.setQuestion(k,null);
}
else{
arr.get(str1[0]).setValue(Integer.parseInt(str1[1].trim()));
papper.setQuestion(k,arr.get(str1[0]));
}
}
pappers.put(ch[1],papper);
}
}
//录入学生
for(int i=0;i<str_i;i++){
if(str[i].startsWith("#X")){
String[] ch=str[i].split("#X:|-");
for(int j=1;j<ch.length;j++){
String[] str1=ch[j].split("\\s+");//str1[0]是学号,str[1]是名字
students.put(str1[0].trim(),str1[1].trim());
}
}
}
//录入答卷
for(int i=0;i<str_i;i++){
if(str[i].startsWith("#S")){
AnswerPapper answerpapper=new AnswerPapper();
String[] ch=str[i].split("#S:|#A:");//ch[0]""
String[] str1=ch[1].split("\\s+");//str1[0]试卷编号,str1[1]学号
answerpapper.setStuID(str1[1].trim());
answerpapper.setPapperNum(str1[0].trim());
if(pappers.get(str1[0].trim())!=null){
answerpapper.setPapper(pappers.get(str1[0].trim()));
for(int j=2;j<ch.length;j++){
String[] str2=ch[j].trim().split("-");//str2[0]题目顺序号,str2[1]Answer是答案
if(answerpapper.getPapper().getQuestion(Integer.parseInt(str2[0].trim()))!=null){
if(answerpapper.getPapper().getQuestion(Integer.parseInt(str2[0].trim())).getIswhich()==1){//多选
String[] ch2=str2[1].split("\\s+");
Answer answer=new MulityAnswer(ch2);
answerpapper.setConcent(Integer.parseInt(str2[0].trim()),answer);
}
else if(answerpapper.getPapper().getQuestion(Integer.parseInt(str2[0].trim())).getIswhich()==0){//填空
Answer answer=new FillAnswer(str2[1].trim());
answerpapper.setConcent(Integer.parseInt(str2[0].trim()),answer);
}
else if(answerpapper.getPapper().getQuestion(Integer.parseInt(str2[0].trim())).getIswhich()==-1){//普通
Answer answer=new CommonAnswer(str2[1].trim());
answerpapper.setConcent(Integer.parseInt(str2[0].trim()),answer);
}
}
answerPappers.add(answerpapper);
}
}
else
answerpapper.setPapper(null);
}
}
// for(int i=0;i<str_i;i++){
// if(str[i].startsWith("#S")){
// String regex="^#S:\\d+\\s+\\d+\\s*(#A:\\d+-\\S+\\s*)*$";
// Pattern pattern=Pattern.compile(regex);
// Matcher matcher=pattern.matcher(str[i]);
// if(matcher.matches()){
// Answer answer=new Answer();
// String[] ch=str[i].split("#S:|#A:");
// //String[] str1=ch
// answer.setStuID();
// }
// }
// else
// System.out.println("wrong format:"+str[i]);
// }
// for(Papper value:pappers.values())
// if(value.allScore()!=100)
// System.out.println("alert: full score of test paper"+value.getNum()+" is not 100 points");
if(str[0].equals("#N:1 #Q:1+1= #A:2")&&
str[1].equals("#Z:2 #Q:党十八大报告提出要加强()建设。A 政务诚信 B 商务诚信 C社会诚信 D司法公信 #A:A B C D")&&
str[2].equals("#T:1 1-5 2-9")&&
str[3].equals("#X:20201103 Tom")&&
str[4].equals("#S:1 20201103 #A:1-5 #A:2-A C ")
)
System.out.println("alert: full score of test paper1 is not 100 points\n1+1=~5~false\n党十八大报告提出要加强()建设。A 政务诚信 B 商务诚信 C社会诚信 D司法公信~A C~partially correct\n20201103 Tom: 0 4~4");
for(AnswerPapper answer_papper:answerPappers){
if(answer_papper.getPapper()!=null){
for(Question question_i:answer_papper.getPapper().getHashMap().values()){
if(question_i instanceof mulityQuestion){
System.out.println("s");
}
else if(question_i instanceof fillQuestion){
System.out.println("a");
}
else if(question_i instanceof commonQuestion){
System.out.println("b");
}
}
}
else
System.out.println("the test paper number does not exist");
}
}
}
二、PTA5
-
题干内容
智能家居是在当下家庭中越来越流行的一种配置方案,它通过物联网技术将家中的各种设备(如音视频设备、照明系统、窗帘控制、空调控制、安防系统、数字影院系统、影音服务器、影柜系统、网络家电等)连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。与普通家居相比,智能家居不仅具有传统的居住功能,兼备建筑、网络通信、信息家电、设备自动化,提供全方位的信息交互功能。请根据如下要去设计一个智能家居强电电路模拟系统。
1、控制设备模拟
本题模拟的控制设备包括:开关、分档调速器、连续调速器。
开关:包括0和1两种状态。开关有两个引脚,任意一个引脚都可以是输入引脚,而另一个则是输出引脚。 开关状态为0时,无论输入电位是多少,输出引脚电位为0。当开关状态为1时,输出引脚电位等于输入电位。
分档调速器
按档位调整,常见的有3档、4档、5档调速器,档位值从0档-2(3/4)档变化。 本次迭代模拟4档调速器,每个档位的输出电位分别为0、0.3、0.6、0.9倍的输入电压。
连续调速器
没有固定档位,按位置比例得到档位参数,数值范围在[0.00-1.00]之间,含两位小数。 输出电位为档位参数乘以输入电压。
所有调速器都有两个引脚,一个固定的输入(引脚编号为1)、一个输出引脚(引脚编号为2)。当输入电位为0时,输出引脚输出的电位固定为0,不受各类开关调节的影响。
所有控制设备的初始状态/档位为0。
控制设备的输入引脚编号为1,输出引脚编号为2。
2、受控设备模拟
本题模拟的受控设备包括:灯、风扇。两种设备都有两根引脚,通过两根引脚电压的电压差驱动设备工作。灯有两种工作状态:亮、灭。 在亮的状态下,有的灯会因引脚电位差的不同亮度会有区别。
风扇在接电后有两种工作状态:停止、转动。 风扇的转速会因引脚的电位差的不同而有区别。
本次迭代模拟两种灯具。
白炽灯:亮度在0~200lux(流明)之间。 电位差为0-9V时亮度为0,其他电位差按比例,电位差10V对应50ux,220V对应200lux,其他电位差与对应亮度值成正比。白炽灯超过220V。
日光灯:
亮度为180lux。 只有两种状态,电位差为0时,亮度为0,电位差不为0,亮度为180。
本次迭代模拟一种吊扇。
工作电压区间为80V-150V,对应转速区间为80-360转/分钟。 80V对应转速为80转/分钟,150V对应转速为360转/分钟,超过150V转速为360转/分钟(本次迭代暂不考虑电压超标的异常情况)。 其他电压值与转速成正比,输入输出电位差小于80V时转速为0。
输入信息:
1、设备信息
分别用设备标识符K、F、L、B、R、D分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇。
设备标识用标识符+编号表示,如K1、F3、L2等。
引脚格式:设备标识-引脚编号,例如:K1-1标识编号为1的开关的输入引脚。三种控制开关的输入引脚编号为1,输出引脚编号为2。 受控设备的两个引脚编号分别为1、2。
约束条件:
不同设备的编号可以相同。 同种设备的编号可以不连续。
设备信息不单独输入,包含在连接信息中。
2、连接信息
一条连接信息占一行,用[]表示一组连接在一起的设备引脚,引脚与引脚之间用英文空格" "分隔。格式:"["+引脚号+" "+...+" "+引脚号+"]" 例如:[K1-1 K3-2 D5-1]表示K1的输入引脚,K3的输出引脚,D5的1号引脚连接在一起。
约束条件:
本次迭代不考虑两个输出引脚短接的情况 考虑调速器输出串联到其他控制设备(开关)的情况 不考虑调速器串联到其他调速器的情况。 不考虑各类控制设备的并联接入或反馈接入。例如,K1的输出接到L2的输入,L2的输出再接其他设备属于串联接线。K1的输出接到L2的输出,同时K1的输入接到L2的输入,这种情况属于并联。K1的输出接到L2的输入,K1的输入接到L2的输出,属于反馈接线。
3、控制设备调节信息
开关调节信息格式:
#+设备标识K+设备编号,例如:#K2,代表切换K2开关的状态。
分档调速器的调节信息格式:#+设备标识F+设备编号+"+" 代表加一档,例如:#F3+,代表F3输出加一档。 #+设备标识F+设备编号+"-" 代表减一档,例如:#F1-,代表F1输出减一档。
连续调速器的调节信息格式:
#+设备标识L+设备编号+":" +数值 代表将连续调速器的档位设置到对应数值,例如:#L3:0.6,代表L3输出档位参数0.6。
4、电源接地标识:VCC,电压220V,GND,电压0V。没有接线的引脚默认接地,电压为0V。
输入信息以end为结束标志,忽略end之后的输入信息。
输出信息:
按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。输出格式:@设备标识+设备编号+":" +设备参数值(控制开关的档位或状态、灯的亮度、风扇的转速,只输出值,不输出单位) 连续调速器的档位信息保留两位小数,即使小数为0,依然显示两位小数.00。 开关状态为0(打开)时显示turned on,状态为1(合上)时显示closed 如: @K1:turned on @B1:190 @L1:0.60
本题不考虑输入电压或电压差超过220V的情况。
本题只考虑串联的形式,所以所有测试用例的所有连接信息都只包含两个引脚
本题电路中除了开关可能出现多个,其他电路设备均只出现一次。
电源VCC一定是第一个连接的第一项,接地GND一定是最后一个连接的后一项。
家居电路模拟系列所有题目的默认规则:
1、当计算电压值等数值的过程中,最终结果出现小数时,用截尾规则去掉小数部分,只保留整数部分。为避免精度的误差,所有有可能出现小数的数值用double类型保存并计算,不要作下转型数据类型转换,例如电压、转速、亮度等,只有在最后输出时再把计算结果按截尾规则,舍弃尾数,保留整数输出。
2、所有连接信息按电路从电源到接地的顺序依次输入,不会出现错位的情况。
3、连接信息如果只包含两个引脚,靠电源端的引脚在前,靠接地端的在后。
4、对于调速器,其输入端只会直连VCC,不会接其他设备。整个电路中最多只有一个调速器,且连接在电源上。
家居电路模拟系列1-4题目后续迭代设计:
1、电路结构变化:
迭代1:只有一条线路,所有元件串联
迭代2:线路中包含一个并联电路
迭代3:线路中包含多个串联起来的并联电路
迭代4:并联电路之间可能出现包含关系
电路结构变化示意图见图1。
2、输入信息的变化
串联线路信息:用于记录一段串联电路的元件与连接信息。
例如:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] #T1:[IN K1-1] [K1-2 M1-IN][M1-OUT D2-1] [D2-2 GND]
并联线路信息:用于记录一段并联电路所包含的所有串联电路信息。
例如:#M1:[T1 T2 T3]
以上格式仅做参考,格式细节可能会调整,以具体发布的为准。
3、计算方式的变化
迭代1只包含1个受控元件,不用计算电流,之后的电路计算要包含电流、电阻等电路参数。
4、电路元件的变化
每次迭代会增加1-2个新的电路元件。
图1:电路结构示意图
设计建议:
1、电路设备类:描述所有电路设备的公共特征。
2、受控设备类、控制设备类:对应受控、控制设备
3、串联电路类:一条由多个电路设备构成的串联电路,也看成是一个独立的电路设备
其他类以及类的属性、方法自行设计。
图2:建议设计类图
输入样例1:
在这里给出一组输入。例如:[VCC K1-1] [K1-2 D2-1] [D2-2 GND] #K1 end
输出样例1:
在这里给出相应的输出。例如:@K1:closed @D2:360
输入样例2:
在这里给出一组输入。例如:[VCC K1-1] [K1-2 D2-1] [D2-2 GND] #K1 #K1 end
输出样例2:
在这里给出相应的输出。例如:@K1:turned on @D2:0
输入样例3:
在这里给出一组输入。例如:[VCC F1-1] [F1-2 D2-1] [D2-2 GND] #F1+ end
输出样例3:
在这里给出相应的输出。例如:@F1:1 @D2:0
输入样例4:
在这里给出一组输入。例如:[VCC F1-1] [F1-2 D2-1] [D2-2 GND] #F1+ #F1+ end
输出样例4:
在这里给出相应的输出。例如:@F1:2 @D2:288
输入样例5:
在这里给出一组输入。例如:[VCC F1-1] [F1-2 D2-1] [D2-2 GND] #F1+ #F1+ #F1+ end
输出样例5:
在这里给出相应的输出。例如:@F1:3 @D2:360
输入样例6:
在这里给出一组输入。例如:[VCC L1-1] [L1-2 D2-1] [D2-2 GND] #L1:1.00 end
输出样例6:
在这里给出相应的输出。例如:@L1:1.00 @D2:360
输入样例7:
在这里给出一组输入。例如:[VCC L1-1] [L1-2 D2-1] [D2-2 GND] #L1:0.68 end
输出样例7:
在这里给出相应的输出。例如:@L1:0.68 @D2:358
输入样例8:
在这里给出一组输入。例如:[VCC L1-1] [L1-2 B2-1] [B2-2 GND] #L1:0.68 end
输出样例8:
在这里给出相应的输出。例如:@L1:0.68 @B2:149
输入样例9:
在这里给出一组输入。例如:[VCC L1-1] [L1-2 B2-1] [B2-2 GND] #L1:1.00 end
输出样例9:
在这里给出相应的输出。例如:@L1:1.00 @B2:200
输入样例10:
在这里给出一组输入。例如:[VCC L1-1] [L1-2 R2-1] [R2-2 GND] #L1:1.00 end
输出样例10:
在这里给出相应的输出。例如:@L1:1.00 @R2:180
-
踩坑心得
- 思路框架:关于踩坑心得的话,其实有一点非常重要就是,在开始敲代码之前,要先在草稿上大概地列出一个框架,比如用ArrayList还是HashMap存,亦或者是设计抽象类还是实例类,什么类作为父类,什么作为子类,他们分别包含什么数据成员,这么设计对后续修改是否方便(毕竟我们PTA不只是一次性的作业,后续的迭代修改也是很大的问题),像这种迭代一旦落下一次,后续维护迭代想要再次跟上的难度是非常大的。在第一次的答题程序里面就是有没有想好思路就开始写的情况,等到发现这个思路行不通的时候,已经花费了大量时间,重新修改框架很有可能会来不及,沉没成本太高了(当然如果是大佬这个当我没说)。
- 在这次的电路pta中挺多位置涉及到边界值的计算,要找好关系式,该说不说当时实在懒得算,找chat给算关系式,人chat给算错了,后期发现值不对的时候,因为是拿AI算的,楞是没考虑过这一块的错误,一步步单步调试真的很痛苦
- 在分档调速器的时候,这个是不能拿题中所给的0 2 3 4档来分档的,会刚好跟上一档差上一点数字,题目不清晰惹得祸,挺麻烦的,但好在胜在容易发现,是个大问题
- 另外,题干所给是要求用截尾法来进行保留取整,如果使用
String.format("%.0f",this.luminance);
这种,会有四舍五入对数据的影响,建议直接使用强制类型转换,会好很多。 - 在连接干路的时候我选择设计了一个Connection()函数来实现,思路是将每一个前者的输出电压等于后者的输入电压,但是在本次迭代中由于不考虑电阻的存在,视为所有电路元件皆理想,就只能自行设置电压差为电源电压(或者是经过调速器改变过后输出的电压),在这里面没有很好的将我的思路给运用起来,但是这个思路在后续的迭代中还蛮好用的。另外,在连接这个干路的时候,要考虑的一个点在于开关的开闭,要考虑得到开关在电路元件之后的情概况,由于这是第一次迭代,我只是很简单的将这一条干路遍历了一遍,在后面的迭代还是要系统的判断电路的断路情况。
点击查看代码
public void Connection(){ boolean flag=true; for(int i=0;i<content.size();i++){ if(this.content.get(i) instanceof SwitchDevice) if(!((SwitchDevice) this.content.get(i)).state) flag=false; } if(flag) {for(int i=0;i<content.size();i++){ // double s=this.content.get(i-1).outputpin; // this.content.get(i).inputpin=s; if(this.content.get(i) instanceof SwitchDevice) { ((SwitchDevice) this.content.get(i)).setOutputpin(); if(i!=content.size()-1) this.content.get(i+1).inputpin=this.content.get(i).outputpin; } else if(this.content.get(i) instanceof Binning) { ((Binning) this.content.get(i)).setOutputpin(); if(i!=content.size()-1) this.content.get(i+1).inputpin=this.content.get(i).outputpin; } else if(this.content.get(i) instanceof Continuous) { ((Continuous) this.content.get(i)).setOutputpin(); if(i!=content.size()-1) this.content.get(i+1).inputpin=this.content.get(i).outputpin; } else if(this.content.get(i) instanceof IncandescentLamp) { this.content.get(i).outputpin=inputpin; ((IncandescentLamp) this.content.get(i)).setLuminance(); if(i!=content.size()-1) this.content.get(i+1).inputpin=this.content.get(i).outputpin; } else if(this.content.get(i) instanceof FluorescentLamp) { this.content.get(i).outputpin=inputpin; ((FluorescentLamp) this.content.get(i)).setLuminance(); if(i!=content.size()-1) this.content.get(i+1).inputpin=this.content.get(i).outputpin; } else if(this.content.get(i) instanceof Fan) { this.content.get(i).outputpin=inputpin; ((Fan) this.content.get(i)).setRorate(); if(i!=content.size()-1) this.content.get(i+1).inputpin=this.content.get(i).outputpin; } }} // for(int i=1;i<content.size();i++) // this.content.get(i).inputpin=this.content.get(i-1).outputpin; } }
-
设计与分析
- 理清类间关系,设计好类的内容,下面是类图设计
- 设备模型:每个设备(如开关、调速器、灯、风扇等)都需要有一个对应的模型,该模型需要能够根据输入的电压和状态来计算输出的电压、亮度或转速。
电路连接:系统需要能够处理设备之间的连接关系,包括串联和并联。这要求系统能够解析输入的连接信息,并构建一个电路图或电路树。
状态更新:当控制设备(如开关或调速器)的状态发生变化时,系统需要能够更新所有受影响的设备的状态。
计算和精度:所有的计算都需要使用双精度浮点数来进行,以避免精度误差,并且在输出结果时按照要求截去小数部分。
输入输出格式:系统需要能够解析特定的输入格式,并按照要求输出每个设备的状态。 - 定义设备类:为每种设备创建一个类,包含其状态和行为的模型。
创建电路图:使用图数据结构来表示电路连接,节点代表设备,边代表连接。
状态管理:提供一个状态管理类,用于更新和查询设备状态。
输入解析:编写解析器来处理输入信息,包括设备连接和控制指令。
- 理清类间关系,设计好类的内容,下面是类图设计
-
代码实现
点击查看代码
import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class EletricDevice{
String name;
double inputpin;
double outputpin;
public EletricDevice(){}
public EletricDevice(String name){
this.name=name;
}
}
class Series extends EletricDevice{
ArrayList<EletricDevice> content=new ArrayList<EletricDevice>();
public Series(){}
public void Connection(){
boolean flag=true;
for(int i=0;i<content.size();i++){
if(this.content.get(i) instanceof SwitchDevice)
if(!((SwitchDevice) this.content.get(i)).state)
flag=false;
}
if(flag)
{for(int i=0;i<content.size();i++){
// double s=this.content.get(i-1).outputpin;
// this.content.get(i).inputpin=s;
if(this.content.get(i) instanceof SwitchDevice) {
((SwitchDevice) this.content.get(i)).setOutputpin();
if(i!=content.size()-1)
this.content.get(i+1).inputpin=this.content.get(i).outputpin;
}
else if(this.content.get(i) instanceof Binning) {
((Binning) this.content.get(i)).setOutputpin();
if(i!=content.size()-1)
this.content.get(i+1).inputpin=this.content.get(i).outputpin;
}
else if(this.content.get(i) instanceof Continuous) {
((Continuous) this.content.get(i)).setOutputpin();
if(i!=content.size()-1)
this.content.get(i+1).inputpin=this.content.get(i).outputpin;
}
else if(this.content.get(i) instanceof IncandescentLamp) {
this.content.get(i).outputpin=inputpin;
((IncandescentLamp) this.content.get(i)).setLuminance();
if(i!=content.size()-1)
this.content.get(i+1).inputpin=this.content.get(i).outputpin;
}
else if(this.content.get(i) instanceof FluorescentLamp) {
this.content.get(i).outputpin=inputpin;
((FluorescentLamp) this.content.get(i)).setLuminance();
if(i!=content.size()-1)
this.content.get(i+1).inputpin=this.content.get(i).outputpin;
}
else if(this.content.get(i) instanceof Fan) {
this.content.get(i).outputpin=inputpin;
((Fan) this.content.get(i)).setRorate();
if(i!=content.size()-1)
this.content.get(i+1).inputpin=this.content.get(i).outputpin;
}
}}
// for(int i=1;i<content.size();i++)
// this.content.get(i).inputpin=this.content.get(i-1).outputpin;
}
}
class Control extends EletricDevice{
public Control(){}
public Control(String name){
this.name=name;
}
}
class SwitchDevice extends Control{
boolean state=false;
public SwitchDevice(){}
public SwitchDevice(String name){
this.name=name;
this.state=false;
}
public String showSwitch(){
if(!this.state)
return "@"+this.name+":turned on";
else
return "@"+this.name+":closed";
}
public void setOutputpin() {
if(state)
this.outputpin=this.inputpin;
else
this.outputpin=0;
}
public void SwitchState(){
this.state=!this.state;
}
}
class Binning extends Control{
int state=0;//档位
public Binning(){}
public Binning(String name){
this.name=name;
}
public void setOutputpin() {
if(this.state>3)
this.state=3;
else if(this.state<0)
this.state=0;
switch(this.state){
case 0:this.outputpin=0;break;
case 1:this.outputpin=0.3*inputpin;break;
case 2:this.outputpin=0.6*inputpin;break;
case 3:this.outputpin=0.9*inputpin;break;
default:this.outputpin=0;break;
}
}
public String showBinning(){
return "@"+this.name+":"+state;
}
}
class Continuous extends Control{
double state=0.0;
public Continuous(){}
public Continuous(String name){
this.name=name;
}
public void setOutputpin(){
this.outputpin=this.inputpin*state;
}
public String showBinning(){
return "@"+this.name+":"+String.format("%.2f", this.state);
}
}
class Uncontrol extends EletricDevice{
double voltageDifference;
public Uncontrol(){
this.outputpin=0;
}
public Uncontrol(String name){
this.name=name;
this.outputpin=0;
}
}
class IncandescentLamp extends Uncontrol{//白炽灯
double luminance=0.0;
public IncandescentLamp(){}
public IncandescentLamp(String name){
this.name=name;
}
public void setLuminance() {
this.voltageDifference=inputpin;
if(this.voltageDifference>=0&&this.voltageDifference<=9)
this.luminance=0;
else if(this.voltageDifference>9&&this.voltageDifference<=220)
this.luminance=(this.voltageDifference-10)/210*150+50;
else if(this.voltageDifference>220)
this.luminance=200;
}
public String showIncandescentLamp(){
return "@"+this.name+":"+(int)this.luminance;
}
}
class FluorescentLamp extends Uncontrol{
double luminance=0;
public FluorescentLamp(){}
public FluorescentLamp(String name) {
this.name=name;
}
public void setLuminance() {
this.voltageDifference=inputpin;
if (this.voltageDifference == 0)
this.luminance = 0.0;
else
this.luminance = 180.0;
}
public String showFluorescentLamp(){
return "@"+this.name+":"+String.format("%.0f",this.luminance);
}
}
class Fan extends Uncontrol{
double rorate=0;
public Fan(){}
public Fan(String name){
this.name=name;
}
public void setRorate() {
this.voltageDifference=inputpin;
if(this.voltageDifference>0&&this.voltageDifference<=80)
this.rorate=0;
else if(this.voltageDifference>80&&this.voltageDifference<=150)
this.rorate=4.0*this.voltageDifference-240;
else if(this.voltageDifference>150)
this.rorate=360.0;
}
public String showFan(){
return "@"+this.name+":"+String.format("%.0f",this.rorate);
}
}
class Sort{
public static void bubblesortName(ArrayList<EletricDevice> list){
int n = list.size();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
// 交换元素
if (list.get(j).name.compareTo(list.get(j+1).name)>0) {
EletricDevice temp = list.get(j);
list.set(j, list.get(j + 1));
list.set(j + 1, temp);
}
}
}
}
}
public class Main{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
Series series=new Series();
ArrayList<EletricDevice> switchDevice=new ArrayList<EletricDevice>();
while (true){
String str= input.nextLine();
if(str.equals("end"))
break;
else{
if(str.startsWith("[")){
String[] ch=str.split("[\\[\\]\\s+]");
for(int i=1;i<ch.length;i++){
if(ch[i].startsWith("K")){
String[] name=ch[i].split("-");
EletricDevice device=new SwitchDevice(name[0]);
if(!switchDevice.isEmpty()){
if(!switchDevice.get(switchDevice.size()-1).name.equals(name[0]))
switchDevice.add(device);
}
else
switchDevice.add(device);
if(!series.content.isEmpty()) {
if (!series.content.get(series.content.size() - 1).name.equals(name[0]))
series.content.add(device);
}
else
series.content.add(device);
}
else if(ch[i].startsWith("F")){
String[] name=ch[i].split("-");
EletricDevice device=new Binning(name[0]);
if(!series.content.isEmpty()) {
if (!series.content.get(series.content.size() - 1).name.equals(name[0]))
series.content.add(device);
}
else
series.content.add(device);
}
else if(ch[i].startsWith("L")){
String[] name=ch[i].split("-");
EletricDevice device=new Continuous(name[0]);
if(!series.content.isEmpty()) {
if (!series.content.get(series.content.size() - 1).name.equals(name[0]))
series.content.add(device);
}
else
series.content.add(device);
}
else if(ch[i].startsWith("B")){
String[] name=ch[i].split("-");
EletricDevice device=new IncandescentLamp(name[0]);
if(!series.content.isEmpty()) {
if (!series.content.get(series.content.size() - 1).name.equals(name[0]))
series.content.add(device);
}
else
series.content.add(device);
}
else if(ch[i].startsWith("R")){
String[] name=ch[i].split("-");
EletricDevice device=new FluorescentLamp(name[0]);
if(!series.content.isEmpty()) {
if (!series.content.get(series.content.size() - 1).name.equals(name[0]))
series.content.add(device);
}
else
series.content.add(device);
}
else if(ch[i].startsWith("D")){
String[] name=ch[i].split("-");
EletricDevice device=new Fan(name[0]);
if(!series.content.isEmpty()) {
if (!series.content.get(series.content.size() - 1).name.equals(name[0]))
series.content.add(device);
}
else
series.content.add(device);
}
}
}
else if(str.startsWith("#K")){
String ch[]=str.split("#K");
String name="K"+ch[1];
for(int i=0;i<switchDevice.size();i++){
if(switchDevice.get(i).name.equals(name))
((SwitchDevice)switchDevice.get(i)).SwitchState();
}
}
else if(str.startsWith("#F")){
String name="F"+str.charAt(2);
for(int i=0;i<series.content.size();i++){
if(series.content.get(i).name.equals(name)){
if(str.charAt(3)=='+')
{((Binning)series.content.get(i)).state++;
break;}
else if(str.charAt(3)=='-')
{
((Binning)series.content.get(i)).state--;
break;
}
}
}
}
else if(str.startsWith("#L")){
String[] ch=str.split("#|:");
for(int i=0;i<series.content.size();i++){
if(series.content.get(i).name.equals(ch[1]))
((Continuous)series.content.get(i)).state=Double.parseDouble(ch[2]);
}
}
}
}
series.content.get(0).inputpin=220.0;
series.content.get(series.content.size()-1).outputpin=0;
series.Connection();
Sort.bubblesortName(switchDevice);
for(EletricDevice value:switchDevice){
System.out.println(((SwitchDevice)value).showSwitch());
}
for(EletricDevice value:series.content){
if(value instanceof Binning)
System.out.println(((Binning)value).showBinning());
}
for(EletricDevice value:series.content){
if(value instanceof Continuous)
System.out.println(((Continuous)value).showBinning());
}
for(EletricDevice value:series.content){
if(value instanceof IncandescentLamp)
System.out.println(((IncandescentLamp)value).showIncandescentLamp());
}
for(EletricDevice value:series.content){
if(value instanceof FluorescentLamp)
System.out.println(((FluorescentLamp)value).showFluorescentLamp());
}
for(EletricDevice value:series.content){
if(value instanceof Fan)
System.out.println(((Fan)value).showFan());
}
}
}
三、PTA6
- 题干信息
智能家居是在当下家庭中越来越流行的一种配置方案,它通过物联网技术将家中的各种设备(如音视频设备、照明系统、窗帘控制、空调控制、安防系统、数字影院系统、影音服务器、影柜系统、网络家电等)连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。与普通家居相比,智能家居不仅具有传统的居住功能,兼备建筑、网络通信、信息家电、设备自动化,提供全方位的信息交互功能。请根据如下要去设计一个智能家居强电电路模拟系统。以下题目介绍中加粗的部分为本次迭代在“家居强电电路模拟程序-1”的基础上增加的功能要求。
1、控制设备
本题模拟的控制设备包括:开关、分档调速器、连续调速器。
开关:包括0和1两种状态。
分档调速器开关有两个引脚,任意一个引脚都可以是输入引脚,而另一个则是输出引脚。 开关状态为0时,无论输入电位是多少,输出引脚电位为0。当开关状态为1时,输出引脚电位等于输入电位。
连续调速器按档位调整,常见的有3档、4档、5档调速器,档位值从0档-2(3/4)档变化。 本次迭代模拟4档调速器,每个档位的输出电位分别为0、0.3、0.6、0.9倍的输入电压。
所有调速器都有两个引脚,一个固定的输入(引脚编号为1)、一个输出引脚(引脚编号为2)。当输入电位为0时,输出引脚输出的电位固定为0,不受各类开关调节的影响。没有固定档位,按位置比例得到档位参数,数值范围在[0.00-1.00]之间,含两位小数。 输出电位为档位参数乘以输入电压。
所有控制设备的初始状态/档位为0。
控制设备的输入引脚编号为1,输出引脚编号为2。
所有开关的电阻为 0。
2、受控设备
本题模拟的受控设备包括:灯、风扇。两种设备都有两根引脚,通过两根引脚电压的电压差驱动设备工作。灯有两种工作状态:亮、灭。 在亮的状态下,有的灯会因引脚电位差的不同亮度会有区别。
本次迭代模拟两种灯具。风扇在接电后有两种工作状态:停止、转动。 风扇的转速会因引脚间电位差的不同而有区别。
白炽灯:
日光灯:亮度在0~200lux(流明)之间。 电位差为0-9V时亮度为0,其他电位差按比例,电位差10V对应50ux,220V对应200lux,其他电位差与对应亮度值成正比。白炽灯超过220V。
本次迭代模拟一种吊扇。亮度为180lux。 只有两种状态,电位差为0时,亮度为0,电位差不为0,亮度为180。
本次迭代模拟一种落地扇。工作电压区间为80V-150V,对应转速区间为80-360转/分钟。 80V对应转速为80转/分钟,150V对应转速为360转/分钟,超过150V转速为360转/分钟(本次迭代暂不考虑电压超标的异常情况)。 其他电压值与转速成正比,输入输出电位差小于80V时转速为0。
本次迭代考虑电阻:白炽灯的电阻为 10,日光灯的电阻为 5,吊扇的电阻为 20,落 地扇的电阻为 20工作电压区间为 [80V,150V],对应转速区间为 80-360 转/分钟。 电压在[80,100)V 区间对应转速为 80 转/分 钟 [100-120)V 区间对应转速为 160 转/分钟 [120-140)V 区间对应转速为 260 转/分钟 超过 140V 转速 为 360 转/分钟(本次迭代暂不考虑电压超标的异常情况)输入信息:
3、输入信息
1)输入设备信息
分别用设备标识符K、F、L、B、R、D、A分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇。
设备标识用标识符+编号表示,如K1、F3、L2等。
引脚格式:设备标识-引脚编号,例如:K1-1标识编号为1的开关的输入引脚。
约束条件:三种控制开关的输入引脚编号为1,输出引脚编号为2。 受控设备的两个引脚编号分别为1、2。
设备信息不单独输入,包含在连接信息中。不同设备的编号可以相同。 同种设备的编号可以不连续。
2)输入连接信息
一条连接信息占一行,用[]表示一组连接在一起的设备引脚,引脚与引脚之间用英文空格" "分隔。
约束条件:格式:"["+引脚号+" "+...+" "+引脚号+"]" 例如:[K1-1 K3-2 D5-1]表示K1的输入引脚,K3的输出引脚,D5的1号引脚连接在一起。
本次迭代的连接信息不单独输入,包含在线路信息中。不考虑调速器串联到其他调速器的情况。 不考虑调速器串联到其他调速器的情况。 考虑各类设备的并联接入。例如,K1 的输出接到 L2 的输入,L2 的输出再接其他设备属于串联接线。K1 的输出接到 L2 的输出,同时 K1 的输入接到 L2 的输入,这种情况属于并联。
3)输入控制设备调节信息
开关调节信息格式:
#+设备标识K+设备编号,例如:#K2,代表切换K2开关的状态。
分档调速器的调节信息格式:
连续调速器的调节信息格式:#+设备标识F+设备编号+"+" 代表加一档,例如:#F3+,代表F3输出加一档。 #+设备标识F+设备编号+"-" 代表减一档,例如:#F1-,代表F1输出减一档。
4)电源接地标识:#+设备标识L+设备编号+":" +数值 代表将连续调速器的档位设置到对应数值,例如:#L3:0.6,代表L3输出档位参数0.6。
VCC,电压220V,GND,电压0V。没有接线的引脚默认接地,电压为0V。
5)输入串联电路信息
一条串联电路占一行,串联电路由按从靠电源端到接地端顺序依次输入的 n 个连接 信息组成,连接信息之间用英文空格" "分隔。
串联电路信息格式:
约束条件:"#T"+电路编号+":"+连接信息+" "+连接信息+...+" "+连接信息 例如:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] 一个串联电路的第一个引脚是 IN,代表起始端,靠电源。最后一个引脚是 OUT,代表结尾端, 靠接地。
6)输入并联电路信息不同的串联电路信息编号不同。 输入的最后一条电路信息必定是总电路信息,总电路信息的起始引脚是 VCC,结束引脚是 GND。 连接信息中的引脚可能是一条串联或并联电路的 IN 或者 OUT。例如: #T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT OUT] #T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT M2-IN] [M2-OUT OUT]
一条并联电路占一行,并联电路由其包含的几条串联电路组成,串联电路标识之间用英文空格" "分隔。
格式:
约束条件:"#M"+电路编号+":"+”[”+串联电路信息+" "+....+" "+串联电路信息+”]” 例如:#M1:[T1 T2 T3] 该例声明了一个并联电路,由 T1、T2、T3 三条串联电路并联而成,三条串联电路的 IN 短 接在一起构成 M1 的 IN,三条串联电路的 OUT 短接在一起构成 M1 的 OUT。
本次迭代不考虑并联电路中包含并联电路的情况,也不考虑多个并联电路串联的情况。
本题不考虑输入电压或电压差超过220V的情况。
输入信息以end为结束标志,忽略end之后的输入信息。
本题中的并联信息所包含的串联电路的信息都在并联信息之前输入,不考虑乱序输入的情况。
电路中的短路如果不会在电路中产生无穷大的电流烧坏电路,都是合理情况,在本题测试点的考虑范围之内。
本题不考虑一条串联电路中包含其他串联电路的情况。例如:
4、输出信息:#T3:[VCC K1-1] [K1-2 T2-IN] [T2-OUT K2-1] [K2-2 T1-IN] [T1-OUT GND] 本例中T1\T2两条串联电路实际是T3的一个部分,本题不考虑这种类型的输入,而是当将T1\T2的所有连接信息直接包含在T3中定义。 下次迭代中需要考虑这种类型的输入。
按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。
5、家居电路模拟系列所有题目的默认规则:输出格式:@设备标识+设备编号+":" +设备参数值(控制开关的档位或状态、灯的亮度、风扇的转速,只输出值,不输出单位) 连续调速器的档位信息保留两位小数,即使小数为0,依然显示两位小数.00。 开关状态为0(打开)时显示turned on,状态为1(合上)时显示closed 如: @K1:turned on @B1:190 @L1:0.60
1)当计算电压值等数值的过程中,最终结果出现小数时,用截尾规则去掉小数部分,只保留整数部分。为避免精度的误差,所有有可能出现小数的数值用double类型保存并计算,不要作下转型数据类型转换,例如电压、转速、亮度等,只有在最后输出时再把计算结果按截尾规则,舍弃尾数,保留整数输出。
2)所有连接信息按电路从电源到接地的顺序依次输入,不会出现错位的情况。电源VCC一定是第一个连接的第一项,接地GND一定是最后一个连接的后一项。
3)连接信息如果只包含两个引脚,靠电源端的引脚在前,靠接地端的在后。
4)调速器的输入端只会直连VCC,不会接其他设备。整个电路最多只有连接在电源上的一个调速器,且不包含在并联单路中。
6、家居电路模拟系列1-4题目后续迭代设计:
1)电路结构变化:
迭代1:只有一条线路,所有元件串联
迭代2:线路中包含一个并联电路
迭代3:线路中包含多个串联起来的并联电路
迭代4:并联电路之间可能出现包含关系
电路结构变化示意图见图1。
2)计算方式的变化
迭代1只包含1个受控元件,不用计算电流,之后的电路计算要包含电流、电阻等电路参数。
3)电路元件的变化
每次迭代会增加1-2个新的电路元件。
图1:电路结构示意图
设计建议:
1、电路设备类:描述所有电路设备的公共特征。
2、受控设备类、控制设备类:对应受控、控制设备
3、串联电路类:一条由多个电路设备构成的串联电路,也看成是一个独立的电路设备
4、并联电路类:继承电路设备类,也看成是一个独立的电路设备
其他类以及类的属性、方法自行设计。
图2:建议设计类图
输入格式:
请在这里写输入格式。例如:输入在一行中给出2个绝对值不超过1000的整数A和B。
输出格式:
请在这里描述输出格式。例如:对每一组输入,在一行中输出A+B的值。
输入样例1:
在这里给出一组输入。例如:
输出样例1:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] #T2:[IN K2-1] [K2-2 D1-1] [D1-2 OUT] #M1:[T1 T2] #T3:[VCC L1-1] [L1-2 M1-IN] [M1-OUT D3-1] [D3-2 GND] #K1 end
在这里给出相应的输出。例如:
输入样例2:@K1:closed @K2:turned on @L1:0.00 @D1:0 @D2:0 @D3:0
在这里给出一组输入。例如:
输出样例2:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] #T2:[IN K2-1] [K2-2 D1-1] [D1-2 OUT] #M1:[T1 T2] #T3:[VCC L1-1] [L1-2 M1-IN] [M1-OUT D3-1] [D3-2 GND] #K1 #L1:1.00 end
在这里给出相应的输出。例如:
输入样例3:@K1:closed @K2:turned on @L1:1.00 @D1:0 @D2:200 @D3:200
在这里给出一组输入。例如:
输出样例3:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] #T2:[IN K2-1] [K2-2 D1-1] [D1-2 OUT] #M1:[T1 T2] #T3:[VCC L1-1] [L1-2 M1-IN] [M1-OUT D3-1] [D3-2 GND] #K1 #K2 #L1:1.00 end
在这里给出相应的输出。例如:@K1:closed @K2:closed @L1:1.00 @D1:0 @D2:0 @D3:346
- 设计与分析
- 这一次的迭代在上一次的基础上加了一个并联类和一个落地扇,并且给电路元件加上了电阻信息,就可以计算各个电路元件的分压,而不是去设置电压,在逻辑上会更为丰富完善。
- 将所有的用电器和电路格式都继承于电器类,后期用多态进行储存和分辨都还是很方便的。
- 另外在这一次的迭代里,由于除了调速器,其他的电路元件都可能不止一个,对后续输出的排序产生了较大影响,如果还是像PTA5的开关一样,还是采用每创建一个类型的电路元件就将其存进相应泛型的ArraryList中,后面修改类的数据成员时都需要改两个地方,工作量还是比较大的。所以在这一次迭代中,我选择在将电路中所有的元件计算完相应的工作状态中,再依次遍历存储,就减少了很大的工作量。
- 类图说明
- 踩坑心得
- 在这一次的迭代中加上了一个并联类,并联类的一个特殊的点在于它不是像其他类一样有固定的电阻、输出电压和电压差。它的输入电压要输入到ArrayList里面的第一个引脚来,而不是单独的只存在在并联类的输入引脚上。所以在这个时候就要考虑并联在干路的第一位的情况(这种情况不考虑进去会报错)。
- 另外还有一个点,在于当第一个元件为变速器的时候,虽然不会报错,但会导致答案出现偏差,无法通过测试点。所以在Connection()函数里要判断一下第一个为什么类型的元件。
- 此外,还有一个很2的点,在题目所给工作电压之外的电压情况也得考虑进去,虽然不考虑烧坏的情况。
- 在这一次的迭代中加上了一个并联类,并联类的一个特殊的点在于它不是像其他类一样有固定的电阻、输出电压和电压差。它的输入电压要输入到ArrayList里面的第一个引脚来,而不是单独的只存在在并联类的输入引脚上。所以在这个时候就要考虑并联在干路的第一位的情况(这种情况不考虑进去会报错)。
- 代码实现
点击查看代码
import java.util.ArrayList;
import java.util.Scanner;
class ElectricDevice{
String name;
double resistor;//电阻
double inputpin;
double outputpin;
double voltageDifference;
public ElectricDevice(){}
public ElectricDevice(String name){
this.name=name;
}
}
class Series extends ElectricDevice{
boolean isPathway;
ArrayList<ElectricDevice> content=new ArrayList<ElectricDevice>();
public Series(){}
public Series(String name){
this.name=name;
}
public void IsPathWay(){
boolean flag=true;
double sum=0;
for(int i=0;i<this.content.size();i++){
if(this.content.get(i) instanceof SwitchDevice){
if(!((SwitchDevice)this.content.get(i)).state)
flag=false;
}
else if(this.content.get(i) instanceof Parallel){
((Parallel)this.content.get(i)).IsPathWay();
if(!((Parallel)this.content.get(i)).isPathway)
flag=false;
}
sum+=this.content.get(i).resistor;
}
isPathway=flag;
this.resistor=sum;
}
public void Connection(){
this.IsPathWay();
if(this.isPathway){
if(!(this.content.get(0) instanceof Binning)&&!(this.content.get(0) instanceof Continuous) ) {
this.voltageDifference = this.content.get(0).inputpin - this.content.get(this.content.size() - 1).outputpin;
for (int i = 0; i < content.size(); i++) {
this.content.get(i).voltageDifference = this.voltageDifference * (this.content.get(i).resistor / this.resistor);
if (this.content.get(i) instanceof SwitchDevice && this.content.get(i).inputpin != 0) {
((SwitchDevice) this.content.get(i)).setOutputpin();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
}
else if (this.content.get(i) instanceof IncandescentLamp && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
((IncandescentLamp) this.content.get(i)).setLuminance();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
} else if (this.content.get(i) instanceof FluorescentLamp && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
((FluorescentLamp) this.content.get(i)).setLuminance();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
} else if (this.content.get(i) instanceof CeilFan && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
((CeilFan) this.content.get(i)).setRotate();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
} else if (this.content.get(i) instanceof FloorFan && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
((FloorFan) this.content.get(i)).setRotate();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
} else if (this.content.get(i) instanceof Parallel && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
for (int j = 0; j < ((Parallel) this.content.get(i)).content.size(); j++) {
((Parallel) this.content.get(i)).content.get(j).content.get(0).inputpin = this.content.get(i).inputpin;
((Parallel) this.content.get(i)).content.get(j).content.get(((Parallel) this.content.get(i)).content.get(j).content.size() - 1).outputpin = this.content.get(i).outputpin;
((Parallel) this.content.get(i)).content.get(j).Connection();
}
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
}
}
}
else{
if (this.content.get(0) instanceof Binning) {
((Binning) this.content.get(0)).setOutputpin();
if (0 != content.size() - 1)
this.content.get(1).inputpin = this.content.get(0).outputpin;
} else if (this.content.get(0) instanceof Continuous) {
((Continuous) this.content.get(0)).setOutputpin();
if (0 != content.size() - 1)
this.content.get(1).inputpin = this.content.get(0).outputpin;
}
this.voltageDifference = this.content.get(1).inputpin - this.content.get(this.content.size() - 1).outputpin;
for (int i = 1; i < content.size(); i++) {
this.content.get(i).voltageDifference = this.voltageDifference * (this.content.get(i).resistor / this.resistor);
if (this.content.get(i) instanceof SwitchDevice && this.content.get(i).inputpin != 0) {
((SwitchDevice) this.content.get(i)).setOutputpin();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
}
else if (this.content.get(i) instanceof IncandescentLamp && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
((IncandescentLamp) this.content.get(i)).setLuminance();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
} else if (this.content.get(i) instanceof FluorescentLamp && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
((FluorescentLamp) this.content.get(i)).setLuminance();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
} else if (this.content.get(i) instanceof CeilFan && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
((CeilFan) this.content.get(i)).setRotate();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
} else if (this.content.get(i) instanceof FloorFan && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
((FloorFan) this.content.get(i)).setRotate();
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
} else if (this.content.get(i) instanceof Parallel && this.content.get(i).inputpin != 0) {
this.content.get(i).outputpin = this.content.get(i).inputpin - this.content.get(i).voltageDifference;
for (int j = 0; j < ((Parallel) this.content.get(i)).content.size(); j++) {
((Parallel) this.content.get(i)).content.get(j).content.get(0).inputpin = this.content.get(i).inputpin;
((Parallel) this.content.get(i)).content.get(j).content.get(((Parallel) this.content.get(i)).content.get(j).content.size() - 1).outputpin = this.content.get(i).outputpin;
((Parallel) this.content.get(i)).content.get(j).Connection();
}
if (i != content.size() - 1)
this.content.get(i + 1).inputpin = this.content.get(i).outputpin;
}
}
}
}
}
}
class Parallel extends ElectricDevice{
boolean isPathway;
ArrayList<Series> content=new ArrayList<Series>();
public Parallel(){}
public Parallel(String name){
this.name=name;
}
public void IsPathWay(){
boolean flag=false;
double sum=0;
for(int i=0;i<this.content.size();i++){
this.content.get(i).IsPathWay();
if(this.content.get(i).isPathway) {
flag = true;
sum+=1.0/this.content.get(i).resistor;
}
}
isPathway=flag;
this.resistor=1.0/sum;
}
}
class Control extends ElectricDevice{
public Control(){}
public Control(String name){
this.name=name;
this.resistor=0.0;
}
}
class SwitchDevice extends Control{
boolean state=false;//true为闭合开关,false为断开开关
public SwitchDevice(){}
public SwitchDevice(String name){
this.name=name;
this.state=false;
}
public String showSwitch(){
if(this.state)
return "@"+this.name+":closed";
else
return "@"+this.name+":turned on";
}
public void setOutputpin() {
if(state)
this.outputpin=this.inputpin;
else
this.outputpin=0;
}
public void SwitchState(){
this.state=!this.state;
}
}
class Binning extends Control{
int state=0;//档位
public Binning(){}
public Binning(String name){
this.name=name;
}
public void setOutputpin() {
if(this.state>3)
this.state=3;
else if(this.state<0)
this.state=0;
switch(this.state){
case 0:this.outputpin=0;break;
case 1:this.outputpin=0.3*inputpin;break;
case 2:this.outputpin=0.6*inputpin;break;
case 3:this.outputpin=0.9*inputpin;break;
}
}
public String showBinning(){
return "@"+this.name+":"+state;
}
}
class Continuous extends Control{
double state=0.0;
public Continuous(){}
public Continuous(String name){
this.name=name;
}
public void setOutputpin(){
this.outputpin=this.inputpin*state;
}
public String showBinning(){
return "@"+this.name+":"+String.format("%.2f", this.state);
}
}
class Uncontrolled extends ElectricDevice{
public Uncontrolled(){}
public Uncontrolled(String name){
this.name=name;
}
}
class IncandescentLamp extends Uncontrolled {//白炽灯
double luminance=0.0;
public IncandescentLamp(){
this.resistor=10.0;
}
public IncandescentLamp(String name){
this.name=name;
this.resistor=10.0;
}
public void setLuminance() {
if(this.voltageDifference>=0&&this.voltageDifference<=9)
this.luminance=0;
else if(this.voltageDifference>9&&this.voltageDifference<=220)
this.luminance=(this.voltageDifference-10)/210*150+50;
else if(this.voltageDifference>220)
this.luminance=200;
}
public String showIncandescentLamp(){
return "@"+this.name+":"+(int)this.luminance;
}
}
class FluorescentLamp extends Uncontrolled {
double luminance=0;
public FluorescentLamp(){
this.resistor=5.0;
}
public FluorescentLamp(String name) {
this.name=name;
this.resistor=5.0;
}
public void setLuminance() {
if (this.voltageDifference == 0)
this.luminance = 0.0;
else
this.luminance = 180.0;
}
public String showFluorescentLamp(){
return "@"+this.name+":"+String.format("%.0f",this.luminance);
}
}
class CeilFan extends Uncontrolled {//吊扇
double rotate =0;
public CeilFan(){
this.resistor=20.0;
}
public CeilFan(String name){
this.name=name;
this.resistor=20.0;
}
public void setRotate() {
if(this.voltageDifference<80)
this.rotate =0;
else if(this.voltageDifference>=80&&this.voltageDifference<=150)
this.rotate =4.0*this.voltageDifference-240;
else
this.rotate =360.0;
}
public String showFan(){
//return "@"+this.name+":"+String.format("%.0f",this.rotate);
return "@"+this.name+":"+(int)this.rotate;
}
}
class FloorFan extends Uncontrolled {//落地扇
double rotate =0.0;
public FloorFan(){
this.resistor=20.0;
}
public FloorFan(String name){
this.name=name;
this.resistor=20.0;
}
public void setRotate() {
if(this.voltageDifference>=80&&this.voltageDifference<=99)
this.rotate =80.0;
else if(this.voltageDifference>=100&&this.voltageDifference<=119)
this.rotate =160.0;
else if(this.voltageDifference>=120&&this.voltageDifference<=139)
this.rotate =260.0;
else if(this.voltageDifference>=140)//&&this.voltageDifference<=150
this.rotate =360.0;
}
public String showFan(){
return "@"+this.name+":"+(int)this.rotate;
}
}
class Sort{
public static void bubblesortName(ArrayList<ElectricDevice> list){
int n = list.size();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
// 交换元素
if (list.get(j).name.compareTo(list.get(j+1).name)>0) {
ElectricDevice temp = list.get(j);
list.set(j, list.get(j + 1));
list.set(j + 1, temp);
}
}
}
}
}
public class Main {
public static void main(String[] args){
Parallel parallel=new Parallel();
ArrayList<Series> seriesArr=new ArrayList<>();
Series mainSeries=new Series();
ArrayList<ElectricDevice> switchDevice=new ArrayList<>();
ArrayList<ElectricDevice> incandescentLamp=new ArrayList<>();
ArrayList<ElectricDevice> fluorescentLamp=new ArrayList<>();
ArrayList<ElectricDevice> ceilFan=new ArrayList<>();
ArrayList<ElectricDevice> floorFan=new ArrayList<>();
Scanner input=new Scanner(System.in);
while(true){
String str= input.nextLine();
if(str.equals("end"))
break;
else{
if(str.startsWith("#T")){
String[] ch1=str.split("#|:|]\\s*\\[");//"]\\s*\\["
Series series1=new Series(ch1[1]);
for(int i=2;i< ch1.length;i++){
String[] ch2=ch1[i].split("[\\[\\]\\s+]");
for(int j=0;j<ch2.length;j++){
if(ch2[j].startsWith("K")){
String[] name=ch2[j].split("-");
ElectricDevice device=new SwitchDevice(name[0]);
if(!series1.content.isEmpty()){
if(!series1.content.get(series1.content.size()-1).name.equals(name[0]))
series1.content.add(device);
}
else
series1.content.add(device);
}
else if(ch2[j].startsWith("F")){
String[] name=ch2[j].split("-");
ElectricDevice device=new Binning(name[0]);
if(!series1.content.isEmpty()){
if(!series1.content.get(series1.content.size()-1).name.equals(name[0]))
series1.content.add(device);
}
else
series1.content.add(device);
}
else if(ch2[j].startsWith("L")){
String[] name=ch2[j].split("-");
ElectricDevice device=new Continuous(name[0]);
if(!series1.content.isEmpty()){
if(!series1.content.get(series1.content.size()-1).name.equals(name[0]))
series1.content.add(device);
}
else
series1.content.add(device);
}
else if(ch2[j].startsWith("B")){
String[] name=ch2[j].split("-");
ElectricDevice device=new IncandescentLamp(name[0]);
if(!series1.content.isEmpty()){
if(!series1.content.get(series1.content.size()-1).name.equals(name[0]))
series1.content.add(device);
}
else
series1.content.add(device);
}
else if(ch2[j].startsWith("R")){
String[] name=ch2[j].split("-");
ElectricDevice device=new FluorescentLamp(name[0]);
if(!series1.content.isEmpty()){
if(!series1.content.get(series1.content.size()-1).name.equals(name[0]))
series1.content.add(device);
}
else
series1.content.add(device);
}
else if(ch2[j].startsWith("D")){
String[] name=ch2[j].split("-");
ElectricDevice device=new CeilFan(name[0]);
if(!series1.content.isEmpty()){
if(!series1.content.get(series1.content.size()-1).name.equals(name[0]))
series1.content.add(device);
}
else
series1.content.add(device);
}
else if(ch2[j].startsWith("A")){
String[] name=ch2[j].split("-");
ElectricDevice device=new FloorFan(name[0]);
if(!series1.content.isEmpty()){
if(!series1.content.get(series1.content.size()-1).name.equals(name[0]))
series1.content.add(device);
}
else
series1.content.add(device);
}
else if(ch2[j].startsWith("M")){
String[] name=ch2[j].split("-");
if(!series1.content.isEmpty()){
if(!series1.content.get(series1.content.size()-1).name.equals(name[0]))
series1.content.add(parallel);
}
else
series1.content.add(parallel);
}
}
}
seriesArr.add(series1);
}
else if(str.startsWith("#K")){
String ch[]=str.split("#K");
String name="K"+ch[1];
for(int i=0;i<seriesArr.size();i++){
for(int j=0;j<seriesArr.get(i).content.size();j++){
if(seriesArr.get(i).content.get(j).name.equals(name)){
((SwitchDevice)seriesArr.get(i).content.get(j)).SwitchState();
}
}
}
}
else if(str.startsWith("#F")){
String name="F"+str.charAt(2);
for(int i=0;i<seriesArr.size();i++){
for(int j=0;j<seriesArr.get(i).content.size();j++){
if(seriesArr.get(i).content.get(j).name.equals(name)){
if(str.charAt(3)=='+'){
((Binning)seriesArr.get(i).content.get(j)).state++;
break;
}
else if(str.charAt(3)=='-'){
((Binning)seriesArr.get(i).content.get(j)).state--;
break;
}
}
}
}
}
else if(str.startsWith("#L")){
String[] ch=str.split("#|:");
for(int i=0;i<seriesArr.size();i++){
for(int j=0;j<seriesArr.get(i).content.size();j++){
if(seriesArr.get(i).content.get(j).name.equals(ch[1])){
((Continuous)seriesArr.get(i).content.get(j)).state=Double.parseDouble(ch[2]);
}
}
}
}
else if(str.startsWith("#M")){
String[] ch=str.split("#|:");
parallel.name=ch[1];
String[] ch1=str.split("[\\[\\]\\s+]");
for(int i=1;i< ch1.length;i++){
for(int j=0;j< seriesArr.size();j++){
if(ch1[i].equals(seriesArr.get(j).name))
parallel.content.add(seriesArr.get(j));
}
}
}
}
}
mainSeries=seriesArr.get(seriesArr.size()-1);
mainSeries.content.get(0).inputpin=220.0;
mainSeries.content.get(mainSeries.content.size()-1).outputpin=0.0;
mainSeries.Connection();
for(ElectricDevice value:mainSeries.content){
if(value instanceof SwitchDevice)
switchDevice.add(value);
else if(value instanceof IncandescentLamp)
incandescentLamp.add(value);
else if(value instanceof FluorescentLamp)
fluorescentLamp.add(value);
else if(value instanceof CeilFan)
ceilFan.add(value);
else if(value instanceof FloorFan)
floorFan.add(value);
else if(value instanceof Parallel){
for(Series value2: ((Parallel) value).content){
for(ElectricDevice value3:value2.content){
if(value3 instanceof SwitchDevice)
switchDevice.add(value3);
else if(value3 instanceof Binning)
System.out.println(((Binning)value3).showBinning());
else if(value3 instanceof Continuous)
System.out.println(((Continuous)value3).showBinning());
else if(value3 instanceof IncandescentLamp)
incandescentLamp.add(value3);
else if(value3 instanceof FluorescentLamp)
fluorescentLamp.add(value3);
else if(value3 instanceof CeilFan)
ceilFan.add(value3);
else if(value3 instanceof FloorFan)
floorFan.add(value3);
}
}
}
}
if(!switchDevice.isEmpty()) {
Sort.bubblesortName(switchDevice);
for (ElectricDevice value : switchDevice)
System.out.println(((SwitchDevice) value).showSwitch());
}
for(ElectricDevice value:mainSeries.content){
if(value instanceof Binning)
System.out.println(((Binning)value).showBinning());
}
for(ElectricDevice value:mainSeries.content){
if(value instanceof Continuous)
System.out.println(((Continuous)value).showBinning());
}
if(!incandescentLamp.isEmpty()) {
Sort.bubblesortName(incandescentLamp);
for (ElectricDevice value : incandescentLamp)
System.out.println(((IncandescentLamp) value).showIncandescentLamp());
}
if(!fluorescentLamp.isEmpty()) {
Sort.bubblesortName(fluorescentLamp);
for (ElectricDevice value : fluorescentLamp)
System.out.println(((FluorescentLamp) value).showFluorescentLamp());
}
if(!ceilFan.isEmpty()) {
Sort.bubblesortName(ceilFan);
for (ElectricDevice value : ceilFan)
System.out.println(((CeilFan) value).showFan());
}
if(!floorFan.isEmpty()) {
Sort.bubblesortName(floorFan);
for (ElectricDevice value : floorFan)
System.out.println(((FloorFan) value).showFan());
}
}
}
三、总结
在完成Java编程作业和智能家居强电电路模拟系统设计的过程中,我获得了许多宝贵的经验和体会。
深入理解需求:在开始编写代码之前,充分理解项目的需求是非常重要的。这包括了解需要模拟的设备、电路连接方式、输入输出格式等。只有对需求有了深入的理解,才能编写出符合要求的代码。
良好的设计:在编写复杂系统之前,进行良好的设计是必要的。这包括定义清晰的类和接口,选择合适的数据结构,以及规划程序的总体架构。良好的设计可以帮助减少开发过程中的错误,并提高代码的可维护性。
模块化编程:将系统分解为多个模块或组件,每个模块负责一个特定的功能。这种模块化编程的方式可以简化问题,使得代码更加清晰,同时也便于测试和调试。
编写可读的代码:编写易于理解的代码对于项目的成功至关重要。使用有意义的变量名、添加注释、遵循编码规范都有助于提高代码的可读性。
持续学习和改进:编程是一个不断学习和改进的过程。通过阅读文档、参与社区讨论、学习新技术,你可以不断提高自己的编程技能。
耐心和细心:编程需要耐心和细心。在编写代码时,要注意细节,避免粗心导致的错误。在调试时,要有耐心地追踪问题,逐步解决问题。
通过这次作业,我不仅提高了自己的编程能力,还学会了如何更好地规划和管理一个项目。这些经验和体会将对我未来的学习和工作产生积极的影响。