PTA集08-10的总结
- (一)前言:题目集8-10主要考察根据类图的提示完成题目的要求,看清类图中类间的关系,需要我们厘清好关系,做到这一点题目就不会太难。前面的题目集的拓展性对后面的题目集有帮助,需要不断的迭代,虽然有类图的提示,但是在一些细节的地方需要注意,需要不断的调试,找出问题。只要题目集8通过了,那么题目集9和10的费用计算方面会流畅一点通过,此外还有用户通话记录、短信记录的存储也十分重要,因此厘清类图关系很重要。
- (二)题目
题目集08 7-1
实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
输入格式:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码除区号外由是7-8位数字组成。
本题只考虑计费类型0-座机计费,电信系列2、3题会逐步增加计费类型。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
注意:
本题非法输入只做格式非法的判断,不做内容是否合理的判断(时间除外,否则无法计算),比如:
1、输入的所有通讯信息均认为是同一个月的通讯信息,不做日期是否在同一个月还是多个月的判定,直接将通讯费用累加,因此月租只计算一次。
2、记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
3、用户区号不为南昌市的区号也作为正常用户处理。
输出格式:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,
单位元)。假设每个用户初始余额是100元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
1 import java.util.ArrayList;
2 import java.text.SimpleDateFormat;
3 import java.util.Date;
4 import java.text.ParseException;
5 import java.text.SimpleDateFormat;
6 import java.util.ArrayList;
7 import java.util.Scanner;
8
9
10 public class Main {
11 public static void main(String args[]){
12
13 ProcessingData processingData = new ProcessingData();
14 processingData.process();
15
16 }
17
18 }
19 abstract class CallChargeRule extends ChargeRule{
20
21 public double callCost(ArrayList<CallRecord> callRecords) {
22 return 0;
23 }
24 }
25 class CallRecord extends CommunicationRecord{
26 private Date startTime;
27 private Date endTime;
28 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
29 //拨号地点区号
30 private String callingAddressAreaCode;
31 //接听地点区号
32 private String answerAddressAreaCode;
33
34 public Date getStartTime() {
35 return startTime;
36 }
37
38 public void setStartTime(Date startTime) {
39 this.startTime = startTime;
40 }
41
42 public Date getEndTime() {
43 return endTime;
44 }
45
46 public void setEndTime(Date endTime) {
47 this.endTime = endTime;
48 }
49
50 public String getCallingAddressAreaCode() {
51 return callingAddressAreaCode;
52 }
53
54 public void setCallingAddressAreaCode(String callingAddressAreaCode) {
55 this.callingAddressAreaCode = callingAddressAreaCode;
56 }
57
58 public String getAnswerAddressAreaCode() {
59 return answerAddressAreaCode;
60 }
61
62 public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
63 this.answerAddressAreaCode = answerAddressAreaCode;
64 }
65 }
66 abstract class ChargeMode {
67 private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
68
69 public double callCost(UserRecords userRecords){
70 double allCost=0;
71
72 return allCost;
73 }
74 public double getMonthlyRent(){
75 return 20;
76 }
77
78 public ArrayList<ChargeRule> getChargeRules() {
79 return chargeRules;
80 }
81
82 public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
83 this.chargeRules = chargeRules;
84 }
85 }
86 abstract class ChargeRule {
87
88 public void chargeRule(){
89
90 }
91
92 }
93 abstract class CommunicationRecord {
94 protected String callingNumber;
95 protected String answerNUmber;
96
97 public String getCallingNumber() {
98 return callingNumber;
99 }
100
101 public void setCallingNumber(String callingNumber) {
102 this.callingNumber = callingNumber;
103 }
104
105 public String getAnswerNUmber() {
106 return answerNUmber;
107 }
108
109 public void setAnswerNUmber(String answerNUmber) {
110 this.answerNUmber = answerNUmber;
111 }
112 }
113 class JudgeDate {
114
115 public boolean isDate(String str_input,String rDateFormat){
116
117 SimpleDateFormat formatter = new SimpleDateFormat(rDateFormat);
118 formatter.setLenient(false);
119 try {
120 formatter.format(formatter.parse(str_input));
121 } catch (Exception e) {
122 return false;
123 }
124 return true;
125
126 }
127
128 }
129 class LandlinePhoneCharging extends ChargeMode{//固定电话
130 private double monthlyRent = 20;
131 public LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
132 public LandPhoneInProvinceRule landPhoneInProvinceRule =new LandPhoneInProvinceRule();
133 public LandPhoneInLandRule landPhoneInLandRule = new LandPhoneInLandRule();
134 @Override
135 public double callCost(UserRecords userRecords) {
136 double allCost=0;
137 allCost=landPhoneInCityRule.callCost(userRecords.getCallingInCityRecords())+
138 landPhoneInLandRule.callCost(userRecords.getCallingInLandRecords())+
139 landPhoneInProvinceRule.callCost(userRecords.getCallingInProvinceRecords());
140 return allCost;
141 }
142
143 @Override
144 public double getMonthlyRent() {
145 return monthlyRent;
146 }
147
148 @Override
149 public ArrayList<ChargeRule> getChargeRules() {
150 return super.getChargeRules();
151 }
152
153 @Override
154 public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
155 super.setChargeRules(chargeRules);
156 }
157 }
158 class LandPhoneInCityRule extends CallChargeRule{
159 @Override
160 public double callCost(ArrayList<CallRecord> callRecords) {
161 double cost =0;
162 for(CallRecord c:callRecords){
163 if((c.getEndTime().getTime()-c.getStartTime().getTime()==0)) continue;
164 else if((c.getEndTime().getTime()-c.getStartTime().getTime()>0) )
165 cost+=0.1*Math.ceil( (double)(c.getEndTime().getTime()-c.getStartTime().getTime())/60000.0);
166 }
167 return cost;
168 }
169 }
170 class LandPhoneInLandRule extends CallChargeRule{
171 @Override
172 public double callCost(ArrayList<CallRecord> callRecords) {
173 double cost =0 ;
174 for(CallRecord c:callRecords){
175 if((c.getEndTime().getTime()-c.getStartTime().getTime()==0)) continue;
176 else if((c.getEndTime().getTime()-c.getStartTime().getTime()>0) )
177 cost+=0.6*Math.ceil( (double)(c.getEndTime().getTime()-c.getStartTime().getTime())/60000);
178 }
179 return cost;
180 }
181 }
182 class LandPhoneInProvinceRule extends CallChargeRule{
183 @Override
184 public double callCost(ArrayList<CallRecord> callRecords) {
185 double cost =0 ;
186 for(CallRecord c:callRecords){
187 if((c.getEndTime().getTime()-c.getStartTime().getTime()==0)) continue;
188 else if((c.getEndTime().getTime()-c.getStartTime().getTime()>0) )
189 cost+=0.3*Math.ceil((double) (c.getEndTime().getTime()-c.getStartTime().getTime())/60000.0);
190 }
191 return cost;
192 }
193 }
194 class MessageRecord extends CommunicationRecord{
195 //短信记录
196 private String message;
197
198 public String getMessage() {
199 return message;
200 }
201
202 public void setMessage(String message) {
203 this.message = message;
204 }
205 }
206 class ProcessingData {
207
208 final int N = 10000;
209 User []user = new User [N];
210 UserRecords userRecords[] = new UserRecords[N];
211 CallRecord callRecord = new CallRecord();
212 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
213
214
215 Scanner in = new Scanner(System.in);
216 String inCityRegex = "u-0791\\d{7,8}\\s(0|1|2)";
217 String inCityRegex1= "0791\\d{7,8}";
218 String inProvinceRegex = "(079\\d|0701)\\d{7,8}";
219 String inLandRegex = "\\d{10,12}";
220 String s = "t-\\d{11,12}\\s\\d{10,12}(\\s\\d{4}.([1-9]|10|11|12).[^0]\\d?\\s\\d{2}:\\d{2}:\\d{2}){2}";
221 String str,number;
222 int i =0,j=0;
223
224
225 public void process(){
226
227 str = in.nextLine();
228 JudgeDate judgeDate = new JudgeDate();
229 //simpleDateFormat.setLenient(false);//严格验证
230 while(!str.equals("end")){
231 if(str.matches(inCityRegex)){
232 number = str.substring(2,str.length());
233 number = number.substring(0,number.length()-2);
234 boolean isRepetition = false;
235 for(int j=0; j<i ;j++){
236 if(user[j].getNumber().equals(number)) {
237 isRepetition =true;
238 break;
239 }
240 }
241 if(!isRepetition){
242 user[i] = new User();
243 user[i].setNumber(number);
244 i++;
245 }
246 }
247 if(str.matches(s)){
248 str =str.substring(2);
249 String []s1 = str.split("\\s");
250 callRecord = new CallRecord();
251 callRecord.setCallingAddressAreaCode(s1[0]);
252 callRecord.setAnswerAddressAreaCode(s1[1]);
253
254 s1[2] = s1[2]+" "+s1[3];
255 s1[3] = s1[4]+" "+s1[5];
256 if(judgeDate.isDate(s1[2],"yyyy.MM.dd HH:mm:ss")&&judgeDate.isDate(s1[3],"yyyy.MM.dd HH:mm:ss")) {
257 Date startTime = new Date();
258 Date endTime = new Date();
259 try {
260 startTime = simpleDateFormat.parse(s1[2]);
261 } catch (ParseException e) {
262 throw new RuntimeException(e);
263 }
264 try {
265 endTime = simpleDateFormat.parse(s1[3]);
266 } catch (ParseException e) {
267 throw new RuntimeException(e);
268 }
269 if (endTime.getTime() >= startTime.getTime()) {
270 callRecord.setStartTime(startTime);
271 callRecord.setEndTime(endTime);
272 boolean isExistNumber = false;//号码是否存在
273 for (j = 0; j < i; j++) {
274 if (user[j].getNumber().equals(s1[0])) {
275 isExistNumber=true;
276 break;
277 }
278 }
279 if (isExistNumber){
280 boolean isSameRecord = false;
281 if (s1[1].matches(inCityRegex1)) {
282 user[j].getUserRecords().addCallingInCityRecords(callRecord);
283 }
284 else if (s1[1].matches(inProvinceRegex)) {
285 user[j].getUserRecords().addCallingInProvinceRecords(callRecord);
286 }
287 else if(s1[1].matches(inLandRegex)) {
288 user[j].getUserRecords().addCallingInLandRecords(callRecord);
289 }
290
291 }
292 }
293 }
294
295 }
296 str = in.nextLine();
297 }
298
299 User temp = new User();
300 if(i>1) {
301 for (int n = 0; n < i-1; n++) {
302 for (int m = 0; m < i-n-1; m++)
303 if (user[m + 1].getNumber().compareTo( user[m].getNumber() ) <0) {
304 temp = user[m];
305 user[m] = user[m+1];
306 user[m+1] = temp;
307 }
308 }
309 }
310
311 for (int m=0; m<i; m++){
312 System.out.println(user[m].getNumber()+" "+String.format("%.1f",user[m].callCost())+" "+String.format("%.1f",user[m].getBalance()) );
313 }
314
315 }
316 }
317 class User {//用户类
318 //用户记录
319 private UserRecords userRecords = new UserRecords();
320 //余额
321 private double balance = 100;
322 //计费方式
323 private ChargeMode chargeMode = new LandlinePhoneCharging();
324 //号码
325 private String number;
326
327 public double callBalance(){
328
329 return balance-chargeMode.getMonthlyRent()-chargeMode.callCost(userRecords);
330 }
331 public double callCost(){
332
333 return chargeMode.callCost(userRecords);
334 }
335
336 public UserRecords getUserRecords() {
337 return userRecords;
338 }
339
340 public void setUserRecords(UserRecords userRecords) {
341 this.userRecords = userRecords;
342 }
343
344 public double getBalance() {
345 return balance-chargeMode.getMonthlyRent()-chargeMode.callCost(userRecords);
346 }
347
348
349 public ChargeMode getChargeMode() {
350 return chargeMode;
351 }
352
353 public void setChargeMode(ChargeMode chargeMode) {
354 this.chargeMode = chargeMode;
355 }
356
357 public String getNumber() {
358 return number;
359 }
360
361 public void setNumber(String number) {
362 this.number = number;
363 }
364 }
365 class UserRecords {//用户记录类,保存用户各种通话、短信的记录,各种计费规则将使用其中的部分或者全部记录。
366 //市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
367 //市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
368 //以及发送短信、接收短信的记录。
369 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<>();
370 private ArrayList<CallRecord> callingProvinceRecords = new ArrayList<>();
371 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<>();
372 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<>();
373
374 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<>();
375 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<>();
376 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<>();
377 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<>();
378
379 public ArrayList<CallRecord> getCallingInCityRecords() {
380 return callingInCityRecords;
381 }
382
383 public void addCallingInCityRecords(CallRecord callRecord) {
384 callingInCityRecords.add(callRecord);
385 }
386
387 public ArrayList<CallRecord> getCallingInProvinceRecords() {
388 return callingProvinceRecords;
389 }
390
391 public void addCallingInProvinceRecords(CallRecord callRecord) {
392 callingProvinceRecords.add(callRecord);
393 }
394
395 public ArrayList<CallRecord> getCallingInLandRecords() {
396 return callingInLandRecords;
397 }
398
399 public void addCallingInLandRecords(CallRecord callRecord) {
400 callingInLandRecords.add(callRecord);
401 }
402
403 public ArrayList<CallRecord> getAnswerInCityRecords() {
404 return answerInCityRecords;
405 }
406
407 public void addAnswerInCityRecords(CallRecord callRecord) {
408 answerInCityRecords.add(callRecord);
409 }
410
411 public ArrayList<CallRecord> getAnswerInProvinceRecords() {
412 return answerInProvinceRecords;
413 }
414
415 public void addAnswerInProvinceRecords(CallRecord callRecord) {
416 answerInProvinceRecords.add(callRecord);
417 }
418
419 public ArrayList<CallRecord> getAnswerInLandRecords() {
420 return answerInLandRecords;
421 }
422
423 public void addAnswerInLandRecords(CallRecord callRecord) {
424 answerInLandRecords.add(callRecord);
425 }
426
427 public ArrayList<MessageRecord> getSendMessageRecords() {
428 return sendMessageRecords;
429 }
430
431 public void addSendMessageRecords(MessageRecord sendMessageRecord) {
432 sendMessageRecords.add(sendMessageRecord);
433 }
434
435 public ArrayList<MessageRecord> getReceiveMessageRecords() {
436 return receiveMessageRecords;
437 }
438
439 public void addReceiveMessageRecords(MessageRecord receiveMessageRecord) {
440 receiveMessageRecords.add(receiveMessageRecord);
441 }
442 }
1.设计与分析
关键类图用户类

首先使用一个正则表达式对输入的内容进行判断,是否符合开户的正常格式,再用一个正则表达式来判断是否符合通话记录的格式,不同用户的的通话记录需要分开来,可以使用ArrayList来存储多个用户,用户类中已经存在通话记录的列表,计费时需要注意不同的区号(3-4位数字),此外是对所有的通话费用计总后再输出。
2.踩坑心得
1.重复开户的情况判断:

先对号码进行判断,重复则不进行开户
2.不要遗漏掉每月的月租费用

3.单纯靠正则表达式是无法完全判断出时间是否正确(即符合正常的时间,包括闰年、平年的一个月的具体天数和小时、分钟、秒是否正常),需要加一个方法来判断

4.通话时间中后者的时间晚于前者
5.对于不足一分钟的时间算作一分钟,可以使用Math.ceil(),实现向上取整。
6.对于本市、本省区号与国内区号的判断要分清出先后顺序,先判断是否为本市的号码,其次再判断是否为本省的电话号码,最后再判断是否为国内(其实最后一步也可以不用判断,因为没有考虑国外号码的情况)
7.不要忽视题目中最后的要求,将号码从小到大进行排序
3.改进建议
存储用户信息可以采用HashMap,便于排序,因为第一次的代码采用的是冒泡排序,
题目集09 7-1
题目(在题目集08的基础上加了以下要求)
实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
1、针对市内座机用户采用的计费方式(与电信计费系列1内容相同):
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
假设本市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
2、针对手机用户采用实时计费方式:
月租15元,市内省内接电话均免费,市内拨打市内电话0.1元/分钟,市内拨打省内电话0.2元/分钟,市内拨打省外电话0.3元/分钟,省内漫游打电话0.3元/分钟,省外漫游接听0.3元/分钟,省外漫游拨打0.6元/分钟;
注:被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,比如以下案例中,南昌市手机用户13307912264在区号为020的广州接听了电话,主叫号码应被计算为拨打了一个省外长途,同时,手机用户13307912264也要被计算省外接听漫游费:
import java.util.ArrayList;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.*;
public class Main {
public static void main(String args[]){
ProcessingDate processingData = new ProcessingDate();
processingData.process();
}
}
abstract class CallChargeRule extends ChargeRule{
public abstract double callCost(ArrayList<CallRecord> callRecords);
}
class CallRecord extends CommunicationRecord{
private Date startTime;
private Date endTime;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
//拨号地点区号
private String callingAddressAreaCode;
//接听地点区号
private String answerAddressAreaCode;
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getCallingAddressAreaCode() {
return callingAddressAreaCode;
}
public void setCallingAddressAreaCode(String callingAddressAreaCode) {
this.callingAddressAreaCode = callingAddressAreaCode;
}
public String getAnswerAddressAreaCode() {
return answerAddressAreaCode;
}
public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
this.answerAddressAreaCode = answerAddressAreaCode;
}
}
abstract class ChargeMode {
private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
public double callCost(UserRecords userRecords){
double allCost=0;
return allCost;
}
public double getMonthlyRent(){
return 20;
}
public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
this.chargeRules = chargeRules;
}
}
abstract class ChargeRule {
public void chargeRule(){
}
}
abstract class CommunicationRecord {
protected String callingNumber;
protected String answerNUmber;
public String getCallingNumber() {
return callingNumber;
}
public void setCallingNumber(String callingNumber) {
this.callingNumber = callingNumber;
}
public String getAnswerNUmber() {
return answerNUmber;
}
public void setAnswerNUmber(String answerNUmber) {
this.answerNUmber = answerNUmber;
}
}
class JudgeDate {
public boolean isDate(String str_input,String rDateFormat){
SimpleDateFormat formatter = new SimpleDateFormat(rDateFormat);
formatter.setLenient(false);
try {
formatter.format(formatter.parse(str_input));
} catch (Exception e) {
return false;
}
return true;
}
}
class LandlinePhoneCharging extends ChargeMode{//固定电话
private double monthlyRent = 20;
public LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
public LandPhoneInProvinceRule landPhoneInProvinceRule =new LandPhoneInProvinceRule();
public LandPhoneInLandRule landPhoneInLandRule = new LandPhoneInLandRule();
@Override
public double callCost(UserRecords userRecords) {
double allCost=0;
allCost=landPhoneInCityRule.callCost(userRecords.getCallingInCityRecords())+
landPhoneInLandRule.callCost(userRecords.getCallingInLandRecords())+
landPhoneInProvinceRule.callCost(userRecords.getCallingInProvinceRecords());
return allCost;
}
public double getMonthlyRent() {
return monthlyRent;
}
}
class LandPhoneInCityRule extends CallChargeRule{
@Override
public double callCost(ArrayList<CallRecord> callRecords) {
double cost =0 ;
for(CallRecord c:callRecords){
if((c.getEndTime().getTime()-c.getStartTime().getTime())==0) continue;
else if((c.getEndTime().getTime()-c.getStartTime().getTime() )>0 )
cost+=0.1*Math.ceil((double) (c.getEndTime().getTime()-c.getStartTime().getTime())/60000.0);
}
return cost;
}
}
class LandPhoneInLandRule extends CallChargeRule{
@Override
public double callCost(ArrayList<CallRecord> callRecords) {
double cost =0 ;
for(CallRecord c:callRecords){
if((c.getEndTime().getTime()-c.getStartTime().getTime())==0) continue;
else if((c.getEndTime().getTime()-c.getStartTime().getTime())>0 )
cost+=0.6*Math.ceil( (double)(c.getEndTime().getTime()-c.getStartTime().getTime())/60000);
}
return cost;
}
}
class LandPhoneInProvinceRule extends CallChargeRule{
@Override
public double callCost(ArrayList<CallRecord> callRecords) {
double cost =0 ;
for(CallRecord c:callRecords){
if((c.getEndTime().getTime()-c.getStartTime().getTime())==0) continue;
else if((c.getEndTime().getTime()-c.getStartTime().getTime())>0 )
cost+=0.3*Math.ceil( (double)(c.getEndTime().getTime()-c.getStartTime().getTime())/60000);
}
return cost;
}
}
class MessageRecord extends CommunicationRecord{
//短信记录
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class MobilePhoneCharging extends ChargeMode{
final int monthlyRent =15;
public MobilePhoneInCityRule mobilePhoneInCityRule = new MobilePhoneInCityRule();
public MobilePhoneInProvinceRule mobilePhoneInProvinceRule = new MobilePhoneInProvinceRule();
public MobilePhoneInLandRule mobilePhoneInLandRule = new MobilePhoneInLandRule();
@Override
public double callCost(UserRecords userRecords) {
double allCost = 0;
allCost = mobilePhoneInCityRule.callCost(userRecords.getCallingInCityRecords())+
mobilePhoneInLandRule.callCost(userRecords.getCallingInLandRecords())+
mobilePhoneInProvinceRule.callCost(userRecords.getCallingInProvinceRecords())+
mobilePhoneInLandRule.answerCost(userRecords.getAnswerInLandRecords());
return allCost;
}
public double getMonthlyRent() {
return monthlyRent;
}
@Override
public ArrayList<ChargeRule> getChargeRules() {
return super.getChargeRules();
}
@Override
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
super.setChargeRules(chargeRules);
}
}
class MobilePhoneInCityRule extends CallChargeRule{
@Override
public double callCost(ArrayList<CallRecord> callRecords) {
double cost=0;
String cityAreaCode = "0791";
String provinceAreaCode = "(079\\d|0701)";
String landAreaCode = "\\d{3,4}";
for(CallRecord c:callRecords){
if((c.getEndTime().getTime()-c.getStartTime().getTime())==0) continue;
if(c.getAnswerAddressAreaCode().matches(cityAreaCode)){
cost+=0.1*Math.ceil((double) (c.getEndTime().getTime()-c.getStartTime().getTime())/60000.0);
} else if (c.getAnswerAddressAreaCode().matches(provinceAreaCode)) {
cost+=0.2*Math.ceil((double) (c.getEndTime().getTime()-c.getStartTime().getTime())/60000.0);
}
else if(c.getAnswerAddressAreaCode().matches(landAreaCode)){
cost+=0.3*Math.ceil((double) (c.getEndTime().getTime()-c.getStartTime().getTime())/60000.0);
}
}
return cost;
}
}
class MobilePhoneInLandRule extends CallChargeRule{
@Override
public double callCost(ArrayList<CallRecord> callRecords) {
double cost=0;
for(CallRecord c:callRecords){
if((c.getEndTime().getTime()-c.getStartTime().getTime())==0) continue;
else
cost+=0.6*Math.ceil( (double)(c.getEndTime().getTime()-c.getStartTime().getTime())/60000);
}
return cost;
}
public double answerCost(ArrayList<CallRecord> callRecords){
double cost=0;
for(CallRecord c:callRecords){
if((c.getEndTime().getTime()-c.getStartTime().getTime())==0) continue;
else
cost+=0.3*Math.ceil( (double)(c.getEndTime().getTime()-c.getStartTime().getTime())/60000);
}
return cost;
}
}
class MobilePhoneInProvinceRule extends CallChargeRule{
@Override
public double callCost(ArrayList<CallRecord> callRecords) {
double cost=0;
for(CallRecord c:callRecords){
if((c.getEndTime().getTime()-c.getStartTime().getTime())==0) continue;
else
cost+=0.3*Math.ceil( (double)(c.getEndTime().getTime()-c.getStartTime().getTime())/60000);
}
return cost;
}
}
class ProcessingDate {
List<User> user = new ArrayList<>();
CallRecord callRecord = new CallRecord();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
Scanner in = new Scanner(System.in);
String inCityRegex = "u-0791\\d{7,8}\\s0";
String phoneNumber = "u-1\\d{10}\\s1";
String inCityRegex1= "0791\\d{7,8}";
String inProvinceRegex = "(079\\d|0701)\\d{7,9}";
String inLandRegex = "\\d{10,12}";
String cityAreaCode = "0791";
String provinceAreaCode = "(079\\d|0701)";
String landAreaCode = "\\d{3,4}";
String s = "t-0\\d{10,11}\\s\\d{10,12}(\\s\\d{4}.([1-9]|10|11|12).[^0]\\d?\\s\\d{2}:\\d{2}:\\d{2}){2}";;
String s1 = "t-0\\d{10,11}\\s1\\d{10}\\s\\d{3,4}(\\s\\d{4}.([1-9]|10|11|12).[^0]\\d?\\s\\d{2}:\\d{2}:\\d{2}){2}";
String s2 = "t-1\\d{10}\\s\\d{3,4}\\s1\\d{10}\\s\\d{3,4}(\\s\\d{4}.([1-9]|10|11|12).[^0]\\d?\\s\\d{2}:\\d{2}:\\d{2}){2}";
String s3 ="t-1\\d{10}\\s\\d{3,4}\\s\\d{11,12}(\\s\\d{4}.([1-9]|10|11|12).[^0]\\d?\\s\\d{2}:\\d{2}:\\d{2}){2}";
String str,number;
public void process(){
str = in.nextLine();
JudgeDate judgeDate = new JudgeDate();
//simpleDateFormat.setLenient(false);//严格验证
while(!str.equals("end")){
int j=0;
if(str.matches(inCityRegex)||str.matches(phoneNumber)){//座机号或手机号
number = str.substring(2,str.length());
number = number.substring(0,number.length()-2);
boolean isRepetition = false;
for(j=0; j<user.size() ;j++){
if(user.get(j).getNumber().equals(number)) {
isRepetition =true;
break;
}
}
if(!isRepetition){
user.add(new User()) ;
user.get(user.size()-1).setNumber(number);
}
}
if(str.matches(s)){//座机打座机
str =str.substring(2);
String []s1 = str.split("\\s");
callRecord = new CallRecord();
// callRecord.setCallingAddressAreaCode(s1[0]);
// callRecord.setAnswerAddressAreaCode(s1[1]);
s1[2] = s1[2]+" "+s1[3];
s1[3] = s1[4]+" "+s1[5];
if(judgeDate.isDate(s1[2],"yyyy.MM.dd HH:mm:ss")&&judgeDate.isDate(s1[3],"yyyy.MM.dd HH:mm:ss")) {
Date startTime = new Date();
Date endTime = new Date();
try {
startTime = simpleDateFormat.parse(s1[2]);
} catch (ParseException e) {
throw new RuntimeException(e);
}
try {
endTime = simpleDateFormat.parse(s1[3]);
} catch (ParseException e) {
throw new RuntimeException(e);
}
if (endTime.getTime() >= startTime.getTime()) {
callRecord.setStartTime(startTime);
callRecord.setEndTime(endTime);
boolean isExistNumber = false;//号码是否存在
for (j = 0; j < user.size(); j++) {
if (user.get(j).getNumber().equals(s1[0])) {
isExistNumber=true;
break;
}
}
if (isExistNumber){
if (s1[1].matches(inCityRegex1)) {
user.get(j).getUserRecords().addCallingInCityRecords(callRecord);
}
else if (s1[1].matches(inProvinceRegex)) {
user.get(j).getUserRecords().addCallingInProvinceRecords(callRecord);
}
else if(s1[1].matches(inLandRegex)) {
user.get(j).getUserRecords().addCallingInLandRecords(callRecord);
}
}
}
}
}
if(str.matches(s1)){//座机打电话
str =str.substring(2);
String []s = str.split("\\s");
callRecord = new CallRecord();
callRecord.setAnswerAddressAreaCode(s[2]);
s[3]=s[3]+" "+s[4];
s[4]=s[5]+" "+s[6];
if(judgeDate.isDate(s[3],"yyyy.MM.dd HH:mm:ss")&&judgeDate.isDate(s[4],"yyyy.MM.dd HH:mm:ss")) {
Date startTime = new Date();
Date endTime = new Date();
try {
startTime = simpleDateFormat.parse(s[3]);
} catch (ParseException e) {
throw new RuntimeException(e);
}
try {
endTime = simpleDateFormat.parse(s[4]);
} catch (ParseException e) {
throw new RuntimeException(e);
}
if (endTime.getTime() >= startTime.getTime()) {
callRecord.setStartTime(startTime);
callRecord.setEndTime(endTime);
boolean isExistNumber = false;//号码是否存在
boolean isAnswerNumber = false;
for (j = 0; j < user.size(); j++) {
if (user.get(j).getNumber().equals(s[0])) {
isExistNumber=true;
break;
}
}
if (isExistNumber){
if(s[2].matches(cityAreaCode)){
user.get(j).getUserRecords().addCallingInCityRecords(callRecord);
}
else if(s[2].matches(provinceAreaCode)){
user.get(j).getUserRecords().addCallingInProvinceRecords(callRecord);
}
else if(s[2].matches(landAreaCode)){
user.get(j).getUserRecords().addCallingInLandRecords(callRecord);
}
}
for (j = 0; j < user.size(); j++) {
if (user.get(j).getNumber().equals(s[1])) {
isAnswerNumber=true;
break;
}
}
if(isAnswerNumber&&s[2].matches(landAreaCode)&&!s[2].matches(provinceAreaCode)){
user.get(j).getUserRecords().addAnswerInLandRecords(callRecord);
}
}
}
}
if(str.matches(s2)){//手机打手机
str =str.substring(2);
String []s = str.split("\\s");
callRecord = new CallRecord();
callRecord.setCallingAddressAreaCode(s[1]);
callRecord.setAnswerAddressAreaCode(s[3]);
s[4] = s[4]+" "+s[5];
s[5] =s[6]+" "+s[7];
if(judgeDate.isDate(s[4],"yyyy.MM.dd HH:mm:ss")&&judgeDate.isDate(s[5],"yyyy.MM.dd HH:mm:ss")) {
Date startTime = new Date();
Date endTime = new Date();
try {
startTime = simpleDateFormat.parse(s[4]);
} catch (ParseException e) {
throw new RuntimeException(e);
}
try {
endTime = simpleDateFormat.parse(s[5]);
} catch (ParseException e) {
throw new RuntimeException(e);
}
if (endTime.getTime() >= startTime.getTime()) {
callRecord.setStartTime(startTime);
callRecord.setEndTime(endTime);
boolean isExistNumber = false;//号码是否存在
boolean isAnswerNumber = false;
for (j = 0; j < user.size(); j++) {
if (user.get(j).getNumber().equals(s[0])) {
isExistNumber=true;
break;
}
}
if (isExistNumber){
if(s[1].matches(cityAreaCode)){//市内
user.get(j).getUserRecords().addCallingInCityRecords(callRecord);
} else if (s[1].matches(provinceAreaCode)) {
user.get(j).getUserRecords().addCallingInProvinceRecords(callRecord);
}
else if(s[1].matches(landAreaCode)){
user.get(j).getUserRecords().addCallingInLandRecords(callRecord);
}
}
for (j = 0; j < user.size(); j++) {
if(user.get(j).getNumber().equals(s[2])){
isAnswerNumber=true;
break;
}
}
if(isAnswerNumber&&s[3].matches(landAreaCode)&&!s[3].matches(provinceAreaCode)){
user.get(j).getUserRecords().addAnswerInLandRecords(callRecord);
}
}
}
}
if(str.matches(s3)){//座机
str =str.substring(2);
String []s = str.split("\\s");
callRecord = new CallRecord();
callRecord.setCallingAddressAreaCode(s[1]);
String f ;
f=s[2].substring(0,4);
if(f.matches("0791")){
callRecord.setAnswerAddressAreaCode("0791");
}
else if(f.matches(inProvinceRegex)){
callRecord.setAnswerAddressAreaCode("0792");
}
else {
callRecord.setAnswerAddressAreaCode("071");
}
s[3] = s[3]+" "+s[4];
s[5] = s[5]+" "+s[6];
if(judgeDate.isDate(s[3],"yyyy.MM.dd HH:mm:ss")&&judgeDate.isDate(s[5],"yyyy.MM.dd HH:mm:ss")){
Date startTime = new Date();
Date endTime = new Date();
try {
startTime = simpleDateFormat.parse(s[3]);
} catch (ParseException e) {
throw new RuntimeException(e);
}
try {
endTime = simpleDateFormat.parse(s[5]);
} catch (ParseException e) {
throw new RuntimeException(e);
}
if (endTime.getTime() >= startTime.getTime()) {
callRecord.setStartTime(startTime);
callRecord.setEndTime(endTime);
boolean isExistNumber = false;//号码是否存在
boolean isAnswerNumber = false;
for (j = 0; j < user.size(); j++) {
if (user.get(j).getNumber().equals(s[0])) {
isExistNumber=true;
break;
}
}
if (isExistNumber){
if(s[1].matches(cityAreaCode)){//市内
user.get(j).getUserRecords().addCallingInCityRecords(callRecord);
} else if (s[1].matches(provinceAreaCode)) {
user.get(j).getUserRecords().addCallingInProvinceRecords(callRecord);
}
else if(s[1].matches(landAreaCode)){
user.get(j).getUserRecords().addCallingInLandRecords(callRecord);
}
}
}
}
}
str = in.nextLine();
}
User temp = new User();
if(user.size()>1) {
for (int n = 0; n < user.size()-1; n++) {
for (int m = 0; m < user.size()-n-1; m++)
if (user.get(m+1).getNumber().compareTo( user.get(m).getNumber() ) <0) {
temp = user.get(m);
user.set(m,user.get(m+1));
user.set(m+1,temp);
}
}
}
for (int m=0; m< user.size(); m++){
System.out.println(user.get(m).getNumber()+" "+String.format("%.1f",user.get(m).callCost())+" "+String.format("%.1f",user.get(m).getBalance()) );
}
}
}
class User {//用户类
//用户记录
private UserRecords userRecords = new UserRecords();
//余额
private double balance = 100;
//计费方式
private ChargeMode chargeMode = new LandlinePhoneCharging();
private ChargeMode chargeMode1 = new MobilePhoneCharging();
//号码
private String number;
public double callBalance(){
return balance-chargeMode.getMonthlyRent()-chargeMode.callCost(userRecords)-chargeMode1.getMonthlyRent()-chargeMode1.callCost(userRecords);
}
public double callCost(){
if(number.matches("0791\\d{7,9}"))
return chargeMode.callCost(userRecords);
else
return chargeMode1.callCost(userRecords);
}
public UserRecords getUserRecords() {
return userRecords;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public double getBalance() {
if(number.matches("0791\\d{7,9}"))
return balance-chargeMode.getMonthlyRent()-chargeMode.callCost(userRecords);
else if(number.matches("1\\d{10}")) {
double a =chargeMode1.getMonthlyRent();
double b =chargeMode1.callCost(userRecords);
return balance - chargeMode1.getMonthlyRent() - chargeMode1.callCost(userRecords);
}
return 0;
}
public ChargeMode getChargeMode() {
return chargeMode;
}
public void setChargeMode(ChargeMode chargeMode) {
this.chargeMode = chargeMode;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
class UserRecords {//用户记录类,保存用户各种通话、短信的记录,各种计费规则将使用其中的部分或者全部记录。
//市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
//市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
//以及发送短信、接收短信的记录。
private ArrayList<CallRecord> callingInCityRecords = new ArrayList<>();
private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<>();
private ArrayList<CallRecord> callingInLandRecords = new ArrayList<>();
private ArrayList<CallRecord> answerInCityRecords = new ArrayList<>();
private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<>();
private ArrayList<CallRecord> answerInLandRecords = new ArrayList<>();
private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<>();
private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<>();
public ArrayList<CallRecord> getCallingInCityRecords() {
return callingInCityRecords;
}
public void addCallingInCityRecords(CallRecord callRecord) {
callingInCityRecords.add(callRecord);
}
public ArrayList<CallRecord> getCallingInProvinceRecords() {
return callingInProvinceRecords;
}
public void addCallingInProvinceRecords(CallRecord callRecord) {
callingInProvinceRecords.add(callRecord);
}
public ArrayList<CallRecord> getCallingInLandRecords() {
return callingInLandRecords;
}
public void addCallingInLandRecords(CallRecord callRecord) {
callingInLandRecords.add(callRecord);
}
public ArrayList<CallRecord> getAnswerInCityRecords() {
return answerInCityRecords;
}
public void addAnswerInCityRecords(CallRecord callRecord) {
answerInCityRecords.add(callRecord);
}
public ArrayList<CallRecord> getAnswerInProvinceRecords() {
return answerInProvinceRecords;
}
public void addAnswerInProvinceRecords(CallRecord callRecord) {
answerInProvinceRecords.add(callRecord);
}
public ArrayList<CallRecord> getAnswerInLandRecords() {
return answerInLandRecords;
}
public void addAnswerInLandRecords(CallRecord callRecord) {
answerInLandRecords.add(callRecord);
}
public ArrayList<MessageRecord> getSendMessageRecords() {
return sendMessageRecords;
}
public void addSendMessageRecords(MessageRecord sendMessageRecord) {
sendMessageRecords.add(sendMessageRecord);
}
public ArrayList<MessageRecord> getReceiveMessageRecords() {
return receiveMessageRecords;
}
public void addReceiveMessageRecords(MessageRecord receiveMessageRecord) {
receiveMessageRecords.add(receiveMessageRecord);
}
}
1.设计与分析
与题目集08的分析差不多,只需添加几种情况和新的计费方式,手机打手机、手机打座机、座机打手机,此外还需注意对区号的判断,手机在省外接听电话需要费用。
2.踩坑心得(大多数坑在题目集08中已经出现,通过了题目08后面的题目集就相对容易)
1.注意对区号的保存,正则表达式在原先的基础需要稍微改动一点,以便对应不同的计费方式
2.注意月租的费用不要使用到20,用15,不要继承了月租费用20
题目集10 7-1
题目(在原先的基础上添加了对短信的计费)
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
import java.util.ArrayList;
import java.util.Scanner;
import java.util.*;
public class Main {
public static void main(String args[]){
ProcessingDate processingData = new ProcessingDate();
processingData.process();
}
}
abstract class CommunicationRecord {
protected String callingNumber;
protected String answerNUmber;
public String getCallingNumber() {
return callingNumber;
}
public void setCallingNumber(String callingNumber) {
this.callingNumber = callingNumber;
}
public String getAnswerNUmber() {
return answerNUmber;
}
public void setAnswerNUmber(String answerNUmber) {
this.answerNUmber = answerNUmber;
}
}
class MessageRecord extends CommunicationRecord{
//短信记录
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class ProcessingDate {
List<User> user = new ArrayList<>();
Scanner in = new Scanner(System.in);
String phoneNumber = "u-1\\d{10}\\s(1|3)";
String m = "m-1\\d{10}\\s1\\d{10}\\s(\\d|\\w|\\s|,|[.])+";
String str,number;
public void process(){
str = in.nextLine();
while(!str.equals("end")){
int j=0;
if(str.matches(phoneNumber)){//手机号
number = str.substring(2,str.length());
number = number.substring(0,number.length()-2);
boolean isRepetition = false;
for(j=0; j<user.size() ;j++){
if(user.get(j).getNumber().equals(number)) {
isRepetition =true;
break;
}
}
if(!isRepetition){
user.add(new User()) ;
user.get(user.size()-1).setNumber(number);
}
}
if(str.matches(m)){//发短信
MessageRecord messageRecord = new MessageRecord();
String []s =new String[3];
str=str.substring(2);
s[0] = str.substring(0,11);
s[1] = str.substring(12,23);
s[2] = str.substring(24);
boolean isExistNumber = false;//号码是否存在
for (j = 0; j < user.size(); j++) {
if (user.get(j).getNumber().equals(s[0])) {
isExistNumber=true;
break;
}
}
if(isExistNumber){
if(s[2].length()>10){
double num=Math.ceil((double)s[2].length()/10.0);
for(int l =0;l<num;l++){
messageRecord.setMessage(s[2]);
user.get(j).getMessageRecords().add(messageRecord);
}
}
else {
messageRecord.setMessage(s[2]);
user.get(j).getMessageRecords().add(messageRecord);
}
}
}
str = in.nextLine();
}
User temp = new User();
if(user.size()>1) {
for (int n = 0; n < user.size()-1; n++) {
for (int m = 0; m < user.size()-n-1; m++)
if (user.get(m+1).getNumber().compareTo( user.get(m).getNumber() ) <0) {
temp = user.get(m);
user.set(m,user.get(m+1));
user.set(m+1,temp);
}
}
}
for (int m=0; m< user.size(); m++){
System.out.println(user.get(m).getNumber()+" "+String.format("%.1f",user.get(m).callCost())+" "+String.format("%.1f",user.get(m).getBalance()) );
}
}
}
class User {//用户类
private double cost=0;
private ArrayList<MessageRecord> messageRecords =new ArrayList<>();
private String number;
public double callCost(){
if(messageRecords.size()<=3){
cost = messageRecords.size()*0.1;
}
else if(messageRecords.size()>5){
cost =(messageRecords.size()-5)*0.3+0.7;
}
else {
cost = (messageRecords.size()-3)*0.2+0.3;
}
return cost;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public double getBalance() {
return 100-this.cost;
}
public ArrayList<MessageRecord> getMessageRecords() {
return messageRecords;
}
public void setMessageRecords(ArrayList<MessageRecord> messageRecords) {
this.messageRecords = messageRecords;
}
public double getCost() {
return cost;
}
public void setCost(double cost) {
this.cost = cost;
}
}
1.设计与分析
重点在于正则表示“ String m = "m-1\\d{10}\\s1\\d{10}\\s(\\d|\\w|\\s|,|[.])+"; ”,
2.踩坑心得
超3条是指超出3条的部分按0.2一条,超5条类似。
- 总结:
对于本次PTA的题目集重点在于突破题目集8,突破题目集8之后题目集9和10就变得相对容易,考察了看类图的能力及把类图功能实现的能力。12-15周学到了对javafx的具体操作,如对实验四中农夫过河代码的界面,用到了javafx中的图象插入、按钮的监听、界面的变化,以及对于宾馆客房系统预定的类图绘制,及写对应的代码,弄清楚了谁是Actor。在领域类图上需要进一步的研究,领域模型:显示最重要的业务概念和它们之间关系,是真实世界各个事物的表示(现实世界的可视化抽象字典)而不是软件中各构件的表示。(类:表示业务概念,通常只包含重要属性,少甚至不包含操作;关联、泛化:表达概念之间的关系),首先,发现类和对象:尽可能多的找出概念类,其次,建立类之间的关联(关联、继承、依赖),最后, 添加类的重要属性(类的语义完整性、类的作用等)。


浙公网安备 33010602011771号