PTA题目集7-8的总结
1.前言:
PTA题目集7新增了互斥开关,窗帘,多并联电路和多串联电路。由于之前的输入信息中设备的引脚没有作用,所以我的正则表达式只用来提取设备的名字。而互斥开关有三个引脚,不同引脚的电压也不一样,所以这次题目集要提取引脚的编号。因此我打算沿用上次题目集的代码,修改Main函数中的部分代码。
PTA题目集8新增了二极管,并联中包含并联。输出方式也改变了,要输出每个设备的各引脚电压,如果电路出现无穷大的电流造成短路,所有元器件信息不输出,仅输出提示“short circuit error”。讲真,看完题目我心都凉了,真的很复杂。在和舍友讨论后,我大概理解处理引脚电压了。由于我PTA6的代码只能识别到主电路中有M就找并联电路的信息,不能识别并联中的串联是否有并联,只能处理一次并联信息。如果我在上一次代码中加入了识别并联中的串联是否有并联的代码,只是面向结果编程。所以我决定重写,让代码能实现无论多少层并联都能处理。
2.设计与分析:
题目集7
1.输入:
由于本次题目集有多并联电路和多串联电路,会出现多个T,M的电路名字需要识别,所以我用HashMap<String, String>存储T,M电路信息(key存储电路名字,value存储电路信息)。控制设备的调节信息还是用ArrayList存储,但是需要用字符串subString(1,str.length()),不存储#。
2.分析代码
(1)代码复杂度:
由图中可以看出,只有我自己创建的处理设备的类和Main类代码复杂,其他设备类都较为简单。
由图中可以看出,Main函数的方法少,但是复杂,主要是我设计了一个方法来处理电路信息,比如创建设备,分配电压等。
(2)设计思路:
由类图可以看出本次题目集与上次题目集的设计的类差别不大,只是在Main函数中计算电阻及电压的方式不同。本次题目集先用正则表达式将主电路的电阻计算出来,如果主函数有T,正则表达式提取出串联的名字,通过hashmap的get方法获取串联电路信息,再使用方法计算这条电路的电阻;如果主函数有M,正则表达式提取出并联的名字,通过hashmap的get方法获取并联电路信息,通过正则表达式提取并联部分的各串联电路的名字,再依次使用方法计算各条电路的电阻。重复此操作,传电压和电路信息,创建设备,输入设备信息。
控制设备新增了互斥开关,有三个引脚,但是输出1,2引脚接通状态信息。因此如果检测到互斥开关的1,2引脚,判断状态,如果是1,2接通,则该设备的setOpen()方法传1,否则传0。
受控设备新增了窗帘,但是窗帘的打开比例是由整个电路的室内灯光的光照强度和设备电压决定的。因此,我设置了一个全局变量用来记录整个电路的室内灯光的光照强度,遇到白炽灯或者是日光灯就加上设备的光照强度。处理完电路信息后,再设置窗帘的打开比例。
(3)重点代码分析:
与上次题目集相比,我修改了正则表达式。上一次题目集的正则表达式用在了Main函数的方法中,用来识别设备计算电阻或是分配电压。考虑到本次题目集有多并联电路和多串联电路,因此我设计了两个正则表达式识别信息,一个用来识别受控设备和控制设备,一个用来设别串联电路和并联电路。本次题目集的第一个正则表达式识别到了T或是M,则用Main函数的方法计算电压;第二个正则表达式先提取设备的名字,如果设备的名字包括H,再提取设备的编号,再加上这个设备的电阻。
正则表达式
Pattern p = Pattern.compile("\\s([^-]*)-IN\\]\\s\\[[^-]*-OUT");
Matcher m = p.matcher(mainCircuit);
Pattern p1 = Pattern.compile("\\s([^-]*)-(\\d)\\]\\s\\[[^-]*-(\\d)");
Matcher m1 = p1.matcher(mainCircuit);
在计算电压时,检测到互斥开关H后,由于互斥开关输出的是1,2引脚和1,3引脚的电阻不一样的,开关状态不一样,会有多种情况。电路中可能会出现两次同一个互斥开关的信息,而输入信息中可能会出现切换互斥开关的信息,所以我设计了一个方法来检测在分析电路信息时遇到的互斥开关是否是接通的。如果互斥开关接通则判断两个引脚是否包含2,是则电阻+5,否则电阻+10。
判断互斥开关的状态
public static int detection(String str) {
Pattern p = Pattern.compile("\\s(H\\d*)-(\\d)\\]\\s\\[[^-]*-(\\d)");
Matcher m = p.matcher(str);
int count = 0;
while (m.find()) {
String name = m.group(1);
for (int i = 0; i < list.size(); i++) {
if ((list.get(i).substring(1,list.get(i).length())).equals(name)) {
count++;
}
}
if(m.group(2).equals("2")||m.group(3).equals("2")) {
if (count % 2 == 0) {
return 1;
}
else {
return 0;
}
}
if(m.group(2).equals("3")||m.group(3).equals("3")) {
if (count % 2 == 0) {
return 0;
}else {
return 1;
}
}
}return -100;
}
题目集8
(1)代码复杂度:
(2)设计思路:
从类图看,可以发现我新增了两个类:一个是计算串联部分电阻的类;一个是计算并联部分电阻的类,而这个类会使用计算串联部分电阻的类,通过计算并联电路的电阻公式得到此并联电路的电阻。如果它检测到并联中的小串联包含并联,会再创建一个计算该并联电阻的类,可以循环下去,计算并联中包含并联的更复杂的情况。
从类图可看出,受控设备有两个double类型引脚,还有一个记录该设备电压的double类型的Pin。我先分配该设备的电压,再用set()方法设置该设备的前一个引脚的电压,后一个引脚的电压通过前一个引脚的电压减去该设备电压计算得到。
考虑到互斥开关有三个引脚,因此设置了Pin1,2,3,Pin。控制设备的第一个引脚也是用set方法传参,Pin是通过information这个类来设置,得到经过该设备后的电压值,再去set后一个引脚的电压。上面的方法不适用于互斥开关,因为互斥开关有电阻。因此,如果是互斥开关,要检测第一个引脚的编号,再去set电压值。还要检测这条电路的互斥开关的引脚是1,2还是1,3,计算互斥开关的电压,再用第一个引脚的电压减去该设备电压从而计算出第二个引脚的电压。
(3)重点代码分析:
我设计的并联电路类可以处理多种情况,例如并联电路不通,并联电路短路,并联电路部分不通,并联电路全通,并联电路前面设备是否可通,并联电路是否包含并联电路。
并联电路类
class Parallel {
private double R;
public double getR() {
return R;
}
public void setR(double r) {
R = r;
}
private HashMap<String, String> voltage ;
private ArrayList<String> list;
private HashMap<String, String> circuit;
public Parallel(String name,ArrayList<String> list,HashMap<String, String> voltage,HashMap<String, String> circuit) {
this.list=list;this.voltage=voltage;this.circuit=circuit;
String circuit1 = circuit.get(name);
ArrayList<Double> resistance1 = new ArrayList<>();
Pattern p = Pattern.compile("T\\d*");
Matcher m = p.matcher(circuit1);
int count=0;int count1=0;int flag=0;double R=0;
while (m.find()) {
String name1=m.group();//找到了T2
String circuit2 = voltage.get(name1);//找到了T2后面的连接信息
Pattern p1 = Pattern.compile("M\\d*");
Matcher m1 = p1.matcher(circuit2);
if(m1.find()) {//检测大并联中是否含有小并联
Concatenation concatenation=new Concatenation(circuit2,list);
Parallel parallel=new Parallel(m1.group(),list, voltage, circuit);
if(parallel.getR()==0) {//并联直接走,只有开关
if(concatenation.getR()==0) {//无电压,大并联短路
flag=1;
}else if(concatenation.getR()==-1){//并联不通
resistance1.add(0.0);
}else {
resistance1.add(concatenation.getR());
}
}else if(parallel.getR()==-1) {//并联不通
resistance1.add(0.0);
}else {
if(concatenation.getR()==-1) {//小并联前面部分不通
resistance1.add(0.0);
}else {
resistance1.add(parallel.getR()+concatenation.getR());
}
}
}else {
if ((!circuit2.contains("D")) && (!circuit2.contains("A")) && (!circuit2.contains("R"))
&& (!circuit2.contains("B"))) {
if(circuit2.contains("K")&&state(circuit2)) {//有一条只含开关并可通行的电路
flag = 1;
}
}
Concatenation concatenation=new Concatenation(circuit2,list);
if(concatenation.getR()==-1) {
resistance1.add(0.0);//0则不通
}else {
resistance1.add(concatenation.getR());
}
}
}
if(flag==1) {//有一条只含开关并可通行的电路
setR(0);
}else {
for(int i=0;i<resistance1.size();i++) {
if(resistance1.get(i)!=0) {
R+=1/(resistance1.get(i));
}
}
if(R==0) {//并联电路不通
setR(-1);
}else {//有电阻
setR(1/R);
}
}
}
3.踩坑心得:
1.在写完PTA7的代码后,我进行测试,发现同一个互斥开关的信息输出了两次。通过调试发现,并联电路中使用同一个互斥开关时,我的代码检测到了设备就会创建,因此并联电路中两条电路出现同一个设备名时,会创建这个设备两次。因此,我在创建设备前先判断这个设备是否已经创建了。
互斥开关
else if (name.contains("H")) {
int flag3=0;int count = 0;
for(int i=0;i<device1.size();i++) {
if(name.equals(device1.get(i).getName())) {
flag3=1;break;
}
}
if(flag3==0) {
d1 = new Mutex_switch();
for (int i = 0; i < list.size(); i++) {
if ((list.get(i).substring(1,list.get(i).length())).equals(name)) {
count++;
}
}
if(count%2==0) {
((Mutex_switch) d1).setOpen(1);
}
else {
((Mutex_switch) d1).setOpen(0);
}
device1.add(d1);
device1.get(device1.size() - 1).setName(name);
}
}
2.我以为PTA8只要考虑互斥开关和二极管的引脚顺序,而其他设备的引脚默认1在前,2在后。直到发现提交后有一个测试样例中包含 D1-2] [D1-1 ,才发现所有设备的引脚都不做限制,哪个编号在前,哪个是输入引脚。
如果按照我当时的方法,就会导致引脚电压设置错位和引脚电压为负数的情况。
3.还是因为上面的测试样例,我发现部分设备的引脚与正确输出差了1,我觉得是double类型精度值问题,但是解决这个问题非常麻烦。因此我上网查了double类型加法如何避免精度值造成不准。由此,在Main函数写下了一个double类型的加法方法。
加法方法
public static double subtractionDouble(double m1, double m2) {
BigDecimal p1 = new BigDecimal(Double.toString(m1));
BigDecimal p2 = new BigDecimal(Double.toString(m2));
if(Math.abs(p1.subtract(p2).doubleValue())<Math.pow(1, -5)) {
return 0.0;
}else {
return p1.subtract(p2).doubleValue();
}
}
4.改进意见:
1.在PTA7中,我先在Main函数中求出主电路的总电阻,再去分配电压。因此我使用了两次相同的正则表达式,现在我觉得过于累赘了。有两种方法处理,第一种是将正则表达式移动到计算电压的方法中,这样条理清楚,并且在下一次使用电阻是方便调用;第二种方法采取我PTA8的方法处理,逻辑就很清晰,但是我放到PTA7中测试时还是错了三个测试点。
2.由于PTA8的发布时间在考试周,并且题目较难,所以这次我花费的时间没之前多,分数也比之前低。我听舍友说并联电路中的各个串联电路中,如果有电路不通,那这条电路的最后一个引脚的电压要和此并联的已通串联的最后一个引脚的电压一样。我觉得这种情况在我的代码的基础上太难实现。因为这不但要先获取到已通电路的最后一个引脚的电压,还得记住这个电压是此并联的电压。我希望老师能公布测试点或者展示优秀代码,让我学习如何处理。
3.PTA8的控制设备分档调速器和连续调速器没有写判断引脚序号的,新增的测试点发现了,但是只修改了开关的,提交发现还是没有加分,等之后写补练时再全修改了,看看能不能多加几分。
标签:总结,题目,引脚,PTA,互斥,电路,并联,电压,设备 From: https://www.cnblogs.com/homework-33/p/18273914