1、前言
这是第二次作业的博客总结,这次主要是在上次作业的基础上加大了难度,考验了我们写代码和自主学习的能力。
04:这次题目集主要学习了:使用LinkedHashSet删除arraylist中的重复数据,封装,了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等的用法。题目的数目较多,但只有少数题目难度较大,如菜单程序以及日期问题。
05:这次题目集主要学习了:正则表达式,题目较为简单。
06:这次题目只有一个菜单程序,是oop04菜单的升级,难度较大,也正是因为难,我没有写出来这道题。
2、设计与分析
题目集04
7-1 这道题是学习Java以来见过最复杂的题,光是题目的描述与要求就有很长。于是我选择了先写后面相对简单的题目,最后再来解决这个菜单问题。但是因为那个周末除了此次pta之外还有实验报告与第一次blog的总结要完成,于是在拿到及格分数之后我就把这题抛掷脑后,直到oop04结束我也没有继续研究这道题。
7-2 相对于菜单,这一题可以说是非常简单,但是这一题也非常的有意思。
题目并不复杂,但是它却要求我们用简单的方法完成,如果你使用的方法很粗暴,就会卡死在一个叫做 “很慢” 的测试点。我就在这个测试电上花了不少时间,最后是引入了flag来简化了代码才通过了测试点。
源码如下:
1 import java.util.Scanner; 2 import java.util.HashSet; 3 public class Main{ 4 public static void main(String[] args) { 5 Scanner in = new Scanner(System.in); 6 int n = in.nextInt(); 7 int flag = 1; 8 HashSet<Integer> array = new HashSet<Integer>(); 9 for(int i = 0;i < n;i++) { 10 if(!array.add(in.nextInt())){ 11 flag = 0; 12 break; 13 } 14 } 15 if(flag == 1){ 16 System.out.print("NO"); 17 }else if(flag == 0){ 18 System.out.print("YES"); 19 } 20 } 21 }
7-7
7-7这题有点像之前写过的日期题的一部分,这次出现让我们熟悉很多其他库方法的使用规则。
源码如下:
1 import java.time.LocalDate; 2 import java.time.temporal.ChronoUnit; 3 import java.util.Scanner; 4 public class Main { 5 public static void main(String[] args) { 6 Scanner in = new Scanner(System.in); 7 String s1 = in.nextLine(); 8 String s2 = in.nextLine(); 9 String [] date01 = s1.split("-"); 10 String [] date02 = s2.split("-"); 11 12 int year1 = Integer.parseInt(date01[0]); 13 int month1 = Integer.parseInt(date01[1]); 14 int day1 = Integer.parseInt(date01[2]); 15 16 int year2 = Integer.parseInt(date02[0]); 17 int month2 = Integer.parseInt(date02[1]); 18 int day2 = Integer.parseInt(date02[2]); 19 20 LocalDate date1 = LocalDate.of(year1, month1, day1); 21 LocalDate date2 = LocalDate.of(year2, month2, day2); 22 23 long Count1 = Math.abs(date1.until(date2, ChronoUnit.DAYS)); 24 long Count2 = Math.abs(date1.until(date2, ChronoUnit.WEEKS)); 25 26 if( date1.isBefore(date2) ) 27 System.out.println("第一个日期比第二个日期更早"); 28 else if(date1.isAfter(date2)) { 29 System.out.println("第一个日期比第二个日期更晚"); 30 } 31 32 System.out.println("两个日期间隔" + Count1 + "天" ); 33 System.out.println("两个日期间隔" + Count2 + "周" ); 34 } 35 }
题目集05
这次题目集的难度不是很大,前面四题主要是让我们熟悉了正则表达式的使用规则。后面两题则是前几次训练集中日期类的延申,让我们了解了聚合的意思以及一些用法。
7-5 参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format
- 当第一个数字为1且输入均有效,输出格式如下:
year-month-day
- 当第一个数字为2且输入均有效,输出格式如下:
year-month-day
- 当第一个数字为3且输入均有效,输出格式如下:
天数值
输入样例1:
在这里给出一组输入。例如:
3 2014 2 14 2020 6 14
输出样例1:
在这里给出相应的输出。例如:
2312
输入样例2:
在这里给出一组输入。例如:
2 1935 2 17 125340
输出样例2:
在这里给出相应的输出。例如:
1591-12-17
输入样例3:
在这里给出一组输入。例如:
1 1999 3 28 6543
输出样例3:
在这里给出相应的输出。例如:
2017-2-24
输入样例4:
在这里给出一组输入。例如:
0 2000 5 12 30
输出样例4:
在这里给出相应的输出。例如:
Wrong Format
因为在题目中已经说明了聚合,再结合类图可以知道这一题主要就是考察我们对聚合的理解,主要是对之前日期问题的进一步加工使类之间具有聚合关系。因为当时并不理解聚合,所以我在网上查了很多聚合和日期类问题的例子,才写出了这一题。现在知道了java中聚合是一种特殊的关联形式,它是两个类之间的关系,是一种HAS-A关系,是一种单向关联,使用聚合可以加强代码的可复用性。
源码如下:
1 import java.util.Scanner; 2 //Year类 3 class Year{ 4 int value; 5 6 public Year(){ 7 8 } 9 public Year(int value){ 10 this.value = value; 11 } 12 13 public int getValue(){ 14 return value; 15 } 16 public void setValue(int value){ 17 this.value = value; 18 } 19 20 public boolean isLeapYear(){ 21 if(( value%4 == 0 && value%100 != 0) || value%400 == 0) 22 return true; 23 else 24 return false; 25 } 26 27 public boolean validate(){ 28 if(value <= 2050 && value >= 1900) 29 return true; 30 else 31 return false; 32 } 33 34 public void yearIncrement(){ 35 value += 1; 36 } 37 38 public void yearReduction(){ 39 value -= 1; 40 } 41 } 42 43 class Month{ 44 int value; 45 Year year; 46 47 public Month(){ 48 49 } 50 public Month(int yearValue,int monthValue){ 51 this.year = new Year(yearValue); 52 this.value = monthValue; 53 } 54 55 public int getValue(){ 56 return value; 57 } 58 public Year getYear(){ 59 return year; 60 } 61 62 public void setValue(int value){ 63 this.value = value; 64 } 65 public void setYear(Year year){ 66 this.year = year; 67 } 68 //日期复位(1) 69 public void resetMin(){ 70 value=1; 71 } 72 //月份设置为12 73 public void resetMax(){ 74 value=12; 75 } 76 //效验数据合法性 77 public boolean validate(){ 78 if(value >= 1 && value <= 12) 79 return true; 80 else 81 return false; 82 } 83 //月份加一 84 public void dayIncrement(){ 85 value +=1; 86 } 87 //月份减一 88 public void dayReduction(){ 89 value -= 1; 90 } 91 } 92 //Day类 93 class Day{ 94 int value; 95 Month month; 96 int a[]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 97 //默认构造方法 98 public Day(){ 99 100 } 101 //带参构造方法 102 public Day(int yearValue,int monthValue,int dayValue){ 103 this.month = new Month(yearValue , monthValue); 104 this.value = dayValue; 105 } 106 //getter 107 public int getValue(){ 108 return value; 109 } 110 public Month getMonth(){ 111 return month; 112 } 113 //setter 114 public void setValue(int value){ 115 this.value = value; 116 } 117 public void setMonth(Month value){ 118 this.month = value; 119 } 120 //日期复位(1) 121 public void resetMin(){ 122 value = 1; 123 } 124 //日期设为该月最大值 125 public void resetMax(){ 126 value = a[month.getValue()]; 127 } 128 //效验数据合法性 129 public boolean validate(){ 130 if(this.getMonth().getYear().isLeapYear()) 131 a[2]=29; 132 if(value >= 1 && value <= a[month.getValue()]) 133 return true; 134 else 135 return false; 136 } 137 //日期加一 138 public void dayIncrement() { 139 value += 1; 140 } 141 //日期减一 142 public void dayReduction() { 143 value -= 1; 144 } 145 } 146 //DateUtil类 147 class DateUtil{ 148 Day day; 149 //默认构造方法 150 public DateUtil(){ 151 152 } 153 //带参构造方法 154 public DateUtil(int d,int m,int y){ 155 this.day = new Day(d,m,y); 156 } 157 //getter 158 public Day getDay(){ 159 return day; 160 } 161 //setter 162 public void setDay(Day d){ 163 this.day = d; 164 } 165 166 //效验数据合法性 167 public boolean checkInputValidity(){ 168 if(this.getDay().getMonth().getYear().validate() && this.getDay().getMonth().validate()&&this.getDay().validate()) 169 return true; 170 else 171 return false; 172 } 173 //比较两个日期大小 174 public boolean compareDates(DateUtil date) { 175 if(date.getDay().getMonth().getYear().getValue() < this.getDay().getMonth().getYear().getValue()) 176 return false; 177 else if(date.getDay().getMonth().getYear().getValue() == this.getDay().getMonth().getYear().getValue()&&date.getDay().getMonth().getValue()<this.getDay().getMonth().getValue()) 178 return false; 179 else if(date.getDay().getMonth().getYear().getValue() == this.getDay().getMonth().getYear().getValue()&&date.getDay().getMonth().getValue()==this.getDay().getMonth().getValue()&&date.getDay().getValue()<this.getDay().getValue()) 180 return false; 181 else 182 return true; 183 } 184 //判定两个日期是否相等 185 public boolean equalTwoDates(DateUtil date){ 186 if(this.getDay().getValue() == date.getDay().getValue() && this.getDay().getMonth().getValue() == date.getDay().getMonth().getValue() && this.getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()) 187 return true; 188 else 189 return false; 190 } 191 //日期值格式化 192 public String showDate(){ 193 return this.getDay().getMonth().getYear().getValue() + "-" + this.getDay().getMonth().getValue() + "-" + this.getDay().getValue(); 194 } 195 196 //求下n天 197 public DateUtil getNextNDays(int n){ 198 int a[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 199 int y = 0,m = 0,d = 0,sum = 0,i = 0; 200 for(i = this.getDay().getMonth().getValue()+1;i<=12;i++){ 201 sum += a[i]; 202 } 203 sum += a[this.getDay().getMonth().getValue()] - this.getDay().getValue(); 204 if(this.getDay().getMonth().getYear().isLeapYear() && this.getDay().getMonth().getValue()<=2)//闰年 205 sum++; 206 //该年剩余天数 207 if(sum > n){//该年剩余天数大于n 208 y = this.getDay().getMonth().getYear().getValue(); 209 if(this.getDay().getMonth().getYear().isLeapYear()){//如果是闰年 210 a[2]=29; 211 } 212 int e = a[this.getDay().getMonth().getValue()];//该月的天数 213 e = e-this.getDay().getValue();//本月剩余的天数 214 if(e >= n){//如果n天后在本月 215 m = this.getDay().getMonth().getValue(); 216 d = n+this.getDay().getValue(); 217 } 218 else{//如果n天后不在本月 219 n = n-e; 220 m = this.getDay().getMonth().getValue()+1; 221 i = m; 222 while(n-a[i] > 0 && i <= 12){//找到月 223 n -= a[i]; 224 m++; 225 i++; 226 } 227 d = n;//找到天 228 } 229 } 230 else{//该年剩余天数小于n 231 n -= sum; 232 y = this.getDay().getMonth().getYear().getValue()+1; 233 int c = 365;//平年天数 234 if(new Year(y).isLeapYear()){//闰年天数 235 c++; 236 } 237 while(n > c){//找到年 238 n -= c; 239 y++; 240 c = 365; 241 if(new Year(y).isLeapYear()) 242 c++; 243 } 244 i = 1; 245 while(n > a[i] && i <= 12){//找到月 246 n -= a[i]; 247 i++; 248 } 249 m = i; 250 d = n;//找到天 251 } 252 return new DateUtil(y, m, d); 253 } 254 //求前n天 255 public DateUtil getPreviousNDays(int n){ 256 int a[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 257 int y = 0,m = 0,d = 0,sum = 0,i = 0,t = 0; 258 for(i = this.getDay().getMonth().getValue()+1 ; i <= 12 ; i++){ 259 sum += a[i]; 260 } 261 sum += a[this.getDay().getMonth().getValue()] - this.getDay().getValue(); 262 if(this.getDay().getMonth().getYear().isLeapYear() && this.getDay().getMonth().getValue()<=2)//闰年 263 sum++; 264 t = 365 - sum;//该日期所在年份已经过的天数 265 if(this.getDay().getMonth().getYear().isLeapYear()){//如果是闰年 266 t++; 267 } 268 if (t > n){//如果前n天在该年 269 y = this.getDay().getMonth().getYear().getValue(); 270 int e = this.getDay().getValue();//本月已经过的天数 271 if(e > n){//如果前n天在本月 272 m = this.getDay().getMonth().getValue(); 273 d = e-n; 274 } 275 else{//如果前n天不在本月 276 n -= e; 277 m = this.getDay().getMonth().getValue()-1; 278 i = m; 279 while(n > a[i] && i >= 0){//找到月 280 n -= a[i]; 281 m--; 282 i--; 283 } 284 d = a[i]-n;//找到天 285 if(new Year(y).isLeapYear() && m == 2){ 286 d++; 287 } 288 } 289 } 290 else{//如果前n天不在该年 291 n -= t; 292 y = this.getDay().getMonth().getYear().getValue()-1; 293 int c = 365; 294 if(new Year(y).isLeapYear()){ 295 c++; 296 } 297 while(n > c){//找到年 298 n -= c; 299 y--; 300 c = 365; 301 if(new Year(y).isLeapYear()) 302 c++; 303 } 304 i = 12; 305 while(a[i]<n && i >= 0){//找到月 306 n -= a[i]; 307 i--; 308 } 309 m = i; 310 d = a[i] - n;//找到天 311 if(new Year(c).isLeapYear() && m == 2){ 312 d++; 313 } 314 } 315 return new DateUtil(y, m, d); 316 } 317 //求两个日期之间的天数 318 public int getDaysofDates(DateUtil date){ 319 if(this.equalTwoDates(date)){//如果两天的日期相等 320 return 0; 321 } 322 DateUtil dateutil1 = this; 323 DateUtil dateutil2 = date; 324 if(!this.compareDates(date)){//如果日期大小不对 325 dateutil1 = date; 326 dateutil2 = this; 327 } 328 int a[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 329 int i,j,ts = 0; 330 for(i = dateutil1.getDay().getMonth().getYear().getValue()+1 ; i < dateutil2.getDay().getMonth().getYear().getValue() ; i++){//两个日期的年数之和 331 ts += 365; 332 if(new Year(i).isLeapYear()) 333 ts++; 334 } 335 if(dateutil1.getDay().getMonth().getYear().getValue() == dateutil2.getDay().getMonth().getYear().getValue() && dateutil1.getDay().getMonth().getValue() == dateutil2.getDay().getMonth().getValue()){//年份相同,月份相同,日不同 336 ts = dateutil2.getDay().getValue() - dateutil1.getDay().getValue(); 337 } 338 else if(dateutil1.getDay().getMonth().getYear().getValue() == dateutil2.getDay().getMonth().getYear().getValue() && dateutil1.getDay().getMonth().getValue() != dateutil2.getDay().getMonth().getValue()){//年份相同,月份不同 339 if(dateutil1.getDay().getMonth().getYear().isLeapYear())//是闰年 340 a[2] = 29; 341 ts += a[dateutil1.getDay().getMonth().getValue()] - dateutil1.getDay().getValue() + dateutil2.getDay().getValue();//小日期该月剩余的天数 342 for(j = dateutil1.getDay().getMonth().getValue()+1 ; j < dateutil2.getDay().getMonth().getValue() ; j++)//月份天数和 343 ts += a[j]; 344 } 345 else if(dateutil1.getDay().getMonth().getYear().getValue() != dateutil2.getDay().getMonth().getYear().getValue()){//年份不同 346 ts += a[dateutil1.getDay().getMonth().getValue()] - dateutil1.getDay().getValue() + dateutil2.getDay().getValue();//小日期在该月剩余的天数 347 //大日期在该月已经过的天数 348 for(j = dateutil1.getDay().getMonth().getValue() + 1;j<=12;j++)//小日期在该年剩余的天数 349 ts += a[j]; 350 for(j = dateutil2.getDay().getMonth().getValue() - 1 ; j > 0 ; j--)//大日期在该年已经过的天数 351 ts += a[j]; 352 if(dateutil1.getDay().getMonth().getYear().isLeapYear() && 353 dateutil1.getDay().getMonth().getValue() <= 2)//如果小日期该年为闰年且该天在1月或2月 354 ts++; 355 if(dateutil2.getDay().getMonth().getYear().isLeapYear() && 356 dateutil2.getDay().getMonth().getValue() > 2)//如果大日期该年为闰年且该天在1月或2月后 357 ts++; 358 } 359 return ts; 360 } 361 } 362 //主类 363 public class Main { 364 public static void main(String[] args) { 365 Scanner in=new Scanner(System.in); 366 int a = in.nextInt();//输入判断类型 367 int year = in.nextInt(); 368 int month= in.nextInt(); 369 int day = in.nextInt();//输入年月日 370 int n; 371 DateUtil ryq = new DateUtil(year, month, day); 372 if(a==1){//求下n天 373 n = in.nextInt();//输入n 374 if(!ryq.checkInputValidity() || n < 0){//如果数据不合法 375 System.out.println("Wrong Format"); 376 System.exit(0); 377 } 378 else System.out.println(ryq.getNextNDays(n).showDate()); 379 } 380 else if(a == 2){ 381 n = in.nextInt();//输入n 382 if(!ryq.checkInputValidity() || n < 0){//如果数据不合法 383 System.out.println("Wrong Format"); 384 System.exit(0); 385 } 386 else 387 System.out.println(ryq.getPreviousNDays(n).showDate()); 388 } 389 else if(a == 3){ 390 int year1 = in.nextInt(); 391 int month1 = in.nextInt(); 392 int day1 = in.nextInt();//输入第二个年月日 393 DateUtil days = new DateUtil(year1, month1, day1); 394 if(!ryq.checkInputValidity() || !days.checkInputValidity()){//如果数据不合法 395 System.out.println("Wrong Format"); 396 System.exit(0); 397 } 398 else 399 System.out.println(ryq.getDaysofDates(days)); 400 } 401 else 402 System.out.println("Wrong Format"); 403 } 404 }
7-6与7-5的要求是一样的,只不过给的类图不同,解题思路不同,但是方法还是差不多的。
7-6 参考题目7-3的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format
- 当第一个数字为1且输入均有效,输出格式如下:
year1-month1-day1 next n days is:year2-month2-day2
- 当第一个数字为2且输入均有效,输出格式如下:
year1-month1-day1 previous n days is:year2-month2-day2
- 当第一个数字为3且输入均有效,输出格式如下:
The days between year1-month1-day1 and year2-month2-day2 are:值
输入样例1:
在这里给出一组输入。例如:
3 2014 2 14 2020 6 14
输出样例1:
在这里给出相应的输出。例如:
The days between 2014-2-14 and 2020-6-14 are:2312
输入样例2:
在这里给出一组输入。例如:
2 1834 2 17 7821
输出样例2:
在这里给出相应的输出。例如:
1834-2-17 previous 7821 days is:1812-9-19
输出样例3:
在这里给出一组输入。例如:
1 1999 3 28 6543
输出样例3:
在这里给出相应的输出。例如:
1999-3-28 next 6543 days is:2017-2-24
输入样例4:
在这里给出一组输入。例如:
0 2000 5 12 30
输出样例4:
在这里给出相应的输出。例如:
Wrong Format
思路一样故不赘述。源码如下:
1 import java.util.Scanner; 2 3 class Year{ 4 int value; 5 public Year(){ 6 7 } 8 public Year(int value){ 9 this.value = value; 10 } 11 12 public int getValue(){ 13 return value; 14 } 15 public void setValue(int value){ 16 this.value = value; 17 } 18 19 public boolean isLeapYear(){ 20 if(( value%4 == 0 && value%100 != 0) || value%400 == 0) 21 return true; 22 else 23 return false; 24 } 25 public boolean validate(){ 26 if(value <= 2050 && value >= 1900) 27 return true; 28 else 29 return false; 30 } 31 32 } 33 //Month类 34 class Month{ 35 int value; 36 public Month(){ 37 38 } 39 public Month(int value){ 40 this.value = value; 41 } 42 43 public int getValue(){ 44 return value; 45 } 46 47 public void setValue(int value){ 48 this.value = value; 49 } 50 51 //日期复位(1) 52 public void resetMin(){ 53 value = 1; 54 } 55 //月份设置为12 56 public void resetMax(){ 57 value = 12; 58 } 59 //效验数据合法性 60 public boolean validate(){ 61 if(value >= 1 && value <= 12) 62 return true; 63 else 64 return false; 65 } 66 } 67 //Day类 68 class Day{ 69 int value; 70 int a[]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 71 //默认构造方法 72 public Day(){ 73 74 } 75 //带参构造方法 76 public Day(int value){ 77 this.value = value; 78 } 79 //getter 80 public int getValue(){ 81 return value; 82 } 83 //setter 84 public void setValue(int value){ 85 this.value = value; 86 } 87 } 88 class DateUtil{ 89 Year year; 90 Month month; 91 Day day; 92 int[] mon_maxnum = {0,31,28,31,30,31,30,31,31,30,31,30,31}; 93 94 public DateUtil(){ 95 96 } 97 public DateUtil(int y,int m,int d){ 98 this.day = new Day(d); 99 this.month = new Month(m); 100 this.year = new Year(y); 101 } 102 103 public Year getYear(){ 104 return year; 105 } 106 public Month getMonth(){ 107 return month; 108 } 109 public Day getDay(){ 110 return day; 111 } 112 public void setYear(Year year){ 113 this.year = year; 114 } 115 public void setMonth(Month month){ 116 this.month = month; 117 } 118 public void setDay(Day day){ 119 this.day = day; 120 } 121 int value; 122 public void setDayMin(){ 123 value = 1; 124 } 125 public void setDayMax(){ 126 value = mon_maxnum[this.getMonth().getValue()]; 127 } 128 129 public boolean checkInputValidity(){ 130 if(this.getDay().getValue() >=1 && this.getDay().getValue() <=31 && 131 this.getMonth().getValue() >= 1 && this.getMonth().getValue() <= 12 && 132 this.getYear().getValue() <= 2020 && this.getYear().getValue() >= 1820){ 133 return true; 134 }else{ 135 return false; 136 } 137 } 138 139 //求下n天 140 public DateUtil getNextNDays(int n){ 141 int y = 0,m = 0,d = 0,sum = 0,i = 0; 142 for(i = this.getMonth().getValue() + 1 ; i <= 12 ; i++){ 143 sum += mon_maxnum[i]; 144 } 145 sum += mon_maxnum[this.getMonth().getValue()] - this.getDay().getValue(); 146 if(this.getYear().isLeapYear() && this.getMonth().getValue() <= 2)//闰年 147 sum++; 148 //该年剩余天数 149 if(sum > n){//该年剩余天数大于n 150 y = this.getYear().getValue(); 151 if(this.getYear().isLeapYear()){//如果是闰年 152 mon_maxnum[2]=29; 153 } 154 int e = mon_maxnum[this.getMonth().getValue()];//该月的天数 155 e -= this.getDay().getValue();//本月剩余的天数 156 if(e >= n){//如果n天后在本月 157 m = this.getMonth().getValue(); 158 d = n + this.getDay().getValue(); 159 } 160 else{//如果n天后不在本月 161 n -= e; 162 m = this.getMonth().getValue() + 1; 163 i = m; 164 while(n > mon_maxnum[i] && i <= 12){//找到月 165 n -= mon_maxnum[i]; 166 m++; 167 i++; 168 } 169 d = n;//找到天 170 } 171 } 172 else{//该年剩余天数小于n 173 n -= sum; 174 y = this.getYear().getValue() + 1; 175 int c = 365;//平年天数 176 if(new Year(y).isLeapYear()){//闰年天数 177 c++; 178 } 179 while(n > c){//找到年 180 n -= c; 181 y++; 182 c = 365; 183 if(new Year(y).isLeapYear()) 184 c++; 185 } 186 i = 1; 187 while(n > mon_maxnum[i] && i <= 12){//找到月 188 n -= mon_maxnum[i]; 189 i++; 190 } 191 m = i; 192 d = n;//找到天 193 } 194 return new DateUtil(y, m, d); 195 } 196 //求前n天 197 public DateUtil getPreviousNDays(int n){ 198 int y = 0,m = 0,d = 0,sum = 0,i = 0,t = 0; 199 for(i = this.getMonth().getValue()+1 ; i <= 12 ; i++){ 200 sum += mon_maxnum[i]; 201 } 202 sum += mon_maxnum[this.getMonth().getValue()] - this.getDay().getValue(); 203 if(this.getYear().isLeapYear() && this.getMonth().getValue()<=2)//闰年 204 sum++; 205 t = 365 - sum;//该日期所在年份已经过的天数 206 if(this.getYear().isLeapYear()){//如果是闰年 207 t++; 208 } 209 if (t > n){//如果前n天在该年 210 y = this.getYear().getValue(); 211 int e = this.getDay().getValue();//本月已经过的天数 212 if(e > n){//如果前n天在本月 213 m = this.getMonth().getValue(); 214 d = e - n; 215 } 216 else{//如果前n天不在本月 217 n -= e; 218 m = this.getMonth().getValue() - 1; 219 i = m; 220 while(n > mon_maxnum[i] && i >= 0){//找到月 221 n -= mon_maxnum[i]; 222 m--; 223 i--; 224 } 225 d = mon_maxnum[i] - n;//找到天 226 if(new Year(y).isLeapYear() && m == 2){ 227 d++; 228 } 229 } 230 } 231 else{//如果前n天不在该年 232 n -= t; 233 y = this.getYear().getValue()-1; 234 int c = 365; 235 if(new Year(y).isLeapYear()){ 236 c++; 237 } 238 while(n > c){//找到年 239 n -= c; 240 y--; 241 c = 365; 242 if(new Year(y).isLeapYear()) 243 c++; 244 } 245 i = 12; 246 while(mon_maxnum[i] < n && i >= 0){//找到月 247 n -= mon_maxnum[i]; 248 i--; 249 } 250 m = i; 251 d = mon_maxnum[i] - n;//找到天 252 if(new Year(c).isLeapYear() && m == 2){ 253 d++; 254 } 255 } 256 return new DateUtil(y, m, d); 257 } 258 259 260 public boolean compareDates(DateUtil date) { 261 if(date.getYear().getValue() < this.getYear().getValue()) 262 return false; 263 else if(date.getYear().getValue() == this.getYear().getValue() && 264 date.getMonth().getValue() < this.getMonth().getValue()) 265 return false; 266 else if(date.getYear().getValue() == this.getYear().getValue() && 267 date.getMonth().getValue() == this.getMonth().getValue() && 268 date.getDay().getValue() < this.getDay().getValue()) 269 return false; 270 else 271 return true; 272 } 273 //判定两个日期是否相等 274 public boolean equalTwoDates(DateUtil date){ 275 if(this.getDay().getValue() == date.getDay().getValue() && 276 this.getMonth().getValue() == date.getMonth().getValue() && 277 this.getYear().getValue() == date.getYear().getValue()) 278 return true; 279 else 280 return false; 281 } 282 283 public int getDaysofDates(DateUtil date){ 284 if(this.equalTwoDates(date)){//如果两天的日期相等 285 return 0; 286 } 287 DateUtil dateutil1 = this; 288 DateUtil dateutil2 = date; 289 if(!this.compareDates(date)){//如果日期大小不对 290 dateutil1 = date; 291 dateutil2 = this; 292 } 293 int i,j,ts = 0; 294 for(i = dateutil1.getYear().getValue() + 1 ; i < dateutil2.getYear().getValue() ; i++){//两个日期的年数之和 295 ts += 365; 296 if(new Year(i).isLeapYear()) 297 ts++; 298 } 299 if(dateutil1.getYear().getValue() == dateutil2.getYear().getValue() && dateutil1.getMonth().getValue() == dateutil2.getMonth().getValue()){//年份相同,月份相同,日不同 300 ts = dateutil2.getDay().getValue() - dateutil1.getDay().getValue(); 301 } 302 else if(dateutil1.getYear().getValue() == dateutil2.getYear().getValue() && dateutil1.getMonth().getValue() != dateutil2.getMonth().getValue()){//年份相同,月份不同 303 if(dateutil1.getYear().isLeapYear())//是闰年 304 mon_maxnum[2] = 29; 305 ts += mon_maxnum[dateutil1.getMonth().getValue()] - dateutil1.getDay().getValue() + dateutil2.getDay().getValue();//小日期该月剩余的天数 306 for(j = dateutil1.getMonth().getValue()+1 ; j < dateutil2.getMonth().getValue() ; j++)//月份天数和 307 ts += mon_maxnum[j]; 308 } 309 else if(dateutil1.getYear().getValue() != dateutil2.getYear().getValue()){//年份不同 310 ts += mon_maxnum[dateutil1.getMonth().getValue()] - dateutil1.getDay().getValue() + dateutil2.getDay().getValue();//小日期在该月剩余的天数 311 //大日期在该月已经过的天数 312 for(j = dateutil1.getMonth().getValue() + 1;j <= 12; j++)//小日期在该年剩余的天数 313 ts += mon_maxnum[j]; 314 for(j = dateutil2.getMonth().getValue() - 1 ; j > 0 ; j--)//大日期在该年已经过的天数 315 ts += mon_maxnum[j]; 316 if(dateutil1.getYear().isLeapYear() && dateutil1.getMonth().getValue() <= 2)//如果小日期该年为闰年且该天在1月或2月 317 ts++; 318 if(dateutil2.getYear().isLeapYear() && dateutil2.getMonth().getValue() > 2)//如果大日期该年为闰年且该天在1月或2月后 319 ts++; 320 } 321 return ts; 322 } 323 324 //日期值格式化 325 public String showDate(){ 326 return this.getYear().getValue() + "-" + this.getMonth().getValue() + "-" + this.getDay().getValue(); 327 } 328 } 329 330 public class Main{ 331 public static void main(String[] args) { 332 Scanner in = new Scanner(System.in); 333 int a = in.nextInt();//输入判断类型 334 int year = in.nextInt(); 335 int month= in.nextInt(); 336 int day = in.nextInt();//输入年月日 337 int n;//输入n 338 339 DateUtil ryq = new DateUtil(year, month, day); 340 if(a==1){//求下n天 341 n = in.nextInt(); 342 if(!ryq.checkInputValidity() || n < 0){//如果数据不合法 343 System.out.println("Wrong Format"); 344 System.exit(0); 345 } 346 else 347 System.out.print(ryq.getYear().getValue() + "-" + ryq.getMonth().getValue() 348 + "-" + ryq.getDay().getValue() + " next " + n + " days is:"); 349 System.out.println(ryq.getNextNDays(n).showDate()); 350 } 351 else if(a == 2){ 352 n = in.nextInt();//输入n 353 if(!ryq.checkInputValidity() || n < 0){//如果数据不合法 354 System.out.println("Wrong Format"); 355 System.exit(0); 356 } 357 else 358 System.out.print(ryq.getYear().getValue() + "-" + ryq.getMonth().getValue() 359 + "-" + ryq.getDay().getValue() + " previous " + n + " days is:"); 360 System.out.println(ryq.getPreviousNDays(n).showDate()); 361 } 362 else if(a == 3){ 363 int year1 = in.nextInt(); 364 int month1 = in.nextInt(); 365 int day1 = in.nextInt();//输入第二个年月日 366 DateUtil days = new DateUtil(year1, month1, day1); 367 if(!ryq.checkInputValidity() || !days.checkInputValidity()){//如果数据不合法 368 System.out.println("Wrong Format"); 369 System.exit(0); 370 } 371 else 372 System.out.println("The days between " + ryq.getYear().getValue() + "-" + ryq.getMonth().getValue() 373 + "-" + ryq.getDay().getValue() + " and " + days.getYear().getValue() + "-" + days.getMonth().getValue() 374 + "-" + days.getDay().getValue() + " are:"+ ryq.getDaysofDates(days)); 375 } 376 else 377 System.out.println("Wrong Format"); 378 } 379 }
题目集06
只有菜单一题,但是难度很大,主要涉及的知识点是类的设计和类与类的关系处理。当时读题就花了很长时间,最后因为畏难心理以及很多同学摆烂的影响,没有写出来这一题。日后解决再来补充。
7-1
本体大部分内容与菜单计价程序-3相同,增加的部分用加粗文字进行了标注。
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
菜单由一条或多条菜品记录组成,每条记录一行
每条菜品记录包含:菜名、基础价格 两个信息。
订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。
桌号标识独占一行,包含两个信息:桌号、时间。
桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。
点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。
不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。
删除记录格式:序号 delete
标识删除对应序号的那条点菜记录。
如果序号不对,输出"delete error"
代点菜信息包含:桌号 序号 菜品名称 份额 分数
代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。
程序最后按输入的桌号从小到大的顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。
每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。
折扣的计算方法(注:以下时间段均按闭区间计算):
周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。
周末全价,营业时间:9:30-21:30
如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"
参考以下类的模板进行设计(本内容与计价程序之前相同,其他类根据需要自行定义):
菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }
菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish[] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
Dish addDish(String dishName,int unit_price)//添加一道菜品信息
}
点菜记录类:保存订单上的一道菜品记录
Record {
int orderNum;//序号
Dish d;//菜品\\
int portion;//份额(1/2/3代表小/中/大份)
int getPrice()//计价,计算本条记录的价格
}
订单类:保存用户点的所有菜的信息。
Order {
Record[] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。
delARecordByOrderNum(int orderNum)//根据序号删除一条记录
findRecordByNum(int orderNum)//根据序号查找一条记录
}
本次课题比菜单计价系列-3增加的异常情况:
1、菜谱信息与订单信息混合,应忽略夹在订单信息中的菜谱信息。输出:"invalid dish"
2、桌号所带时间格式合法(格式见输入格式部分说明,其中年必须是4位数字,月、日、时、分、秒可以是1位或2位数),数据非法,比如:2023/15/16 ,输出桌号+" date error"
3、同一桌菜名、份额相同的点菜记录要合并成一条进行计算,否则可能会出现四舍五入的误差。
4、重复删除,重复的删除记录输出"deduplication :"+序号。
5、代点菜时,桌号不存在,输出"Table number :"+被点菜桌号+" does not exist";本次作业不考虑两桌记录时间不匹配的情况。
6、菜谱信息中出现重复的菜品名,以最后一条记录为准。
7、如果有重复的桌号信息,如果两条信息的时间不在同一时间段,(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒)以内算统一时段),此时输出结果按不同的记录分别计价。
8、重复的桌号信息如果两条信息的时间在同一时间段,此时输出结果时合并点菜记录统一计价。前提:两个的桌号信息的时间都在有效时间段以内。计算每一桌总价要先合并符合本条件的饭桌的点菜记录,统一计价输出。
9、份额超出范围(1、2、3)输出:序号+" portion out of range "+份额,份额不能超过1位,否则为非法格式,参照第13条输出。
10、份数超出范围,每桌不超过15份,超出范围输出:序号+" num out of range "+份数。份数必须为数值,最高位不能为0,否则按非法格式参照第16条输出。
11、桌号超出范围[1,55]。输出:桌号 +" table num out of range",桌号必须为1位或多位数值,最高位不能为0,否则按非法格式参照第16条输出。
12、菜谱信息中菜价超出范围(区间(0,300)),输出:菜品名+" price out of range "+价格,菜价必须为数值,最高位不能为0,否则按非法格式参照第16条输出。
13、时间输入有效但超出范围[2022.1.1-2023.12.31],输出:"not a valid time period"
14、一条点菜记录中若格式正确,但数据出现问题,如:菜名不存在、份额超出范围、份数超出范围,按记录中从左到右的次序优先级由高到低,输出时只提示优先级最高的那个错误。
15、每桌的点菜记录的序号必须按从小到大的顺序排列(可以不连续,也可以不从1开始),未按序排列序号的输出:"record serial number sequence error"。当前记录忽略。(代点菜信息的序号除外)
16、所有记录其它非法格式输入,统一输出"wrong format"
17、如果记录以“table”开头,对应记录的格式或者数据不符合桌号的要求,那一桌下面定义的所有信息无论正确或错误均忽略,不做处理。如果记录不是以“table”开头,比如“tab le 55 2023/3/2 12/00/00”,该条记录认为是错误记录,后面所有的信息并入上一桌一起计算。
本次作业比菜单计价系列-3增加的功能:
菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+基础价格+"T"
例如:麻婆豆腐 9 T
菜价的计算方法:
周一至周五 7折, 周末全价。
注意:不同的四舍五入顺序可能会造成误差,请按以下步骤累计一桌菜的菜价:
计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格。
最后将所有记录的菜价累加得到整桌菜的价格。
输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数
最后一条记录以“end”结束。
输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:
1、桌号,格式:table+英文空格+桌号+”:”
2、按顺序输出当前这一桌每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9 T
table 31 2023/2/1 14/20/00
1 麻婆豆腐 1 16
2 油淋生菜 1 2
2 delete
2 delete
end
输出样例:
在这里给出相应的输出。例如:
table 31:
1 num out of range 16
2 油淋生菜 18
deduplication 2
table 31: 0 0
输入样例1:
份数超出范围+份额超出范围。例如:
麻婆豆腐 12
油淋生菜 9 T
table 31 2023/2/1 14/20/00
1 麻婆豆腐 1 16
2 油淋生菜 4 2
end
输出样例1:
份数超出范围+份额超出范围。例如:
table 31:
1 num out of range 16
2 portion out of range 4
table 31: 0 0
输入样例2:
桌号信息错误。例如:
麻婆豆腐 12
油淋生菜 9 T
table a 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
输出样例2:
在这里给出相应的输出。例如:
wrong format
输入样例3:
混合错误:桌号信息格式错误+混合的菜谱信息(菜谱信息忽略)。例如:
麻婆豆腐 12
油淋生菜 9 T
table 55 2023/3/31 12/000/00
麻辣香锅 15
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
输出样例3:
在这里给出相应的输出。例如:
wrong format
输入样例4:
错误的菜谱记录。例如:
麻婆豆腐 12.0
油淋生菜 9 T
table 55 2023/3/31 12/00/00
麻辣香锅 15
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
输出样例4:
在这里给出相应的输出。例如:
wrong format
table 55:
invalid dish
麻婆豆腐 does not exist
2 油淋生菜 14
table 55: 14 10
输入样例5:
桌号格式错误(以“table”开头)+订单格式错误(忽略)。例如:
麻婆豆腐 12
油淋生菜 9 T
table a 2023/3/15 12/00/00
1 麻婆 豆腐 1 1
2 油淋生菜 2 1
end
输出样例5:
在这里给出相应的输出。例如:
wrong format
输入样例6:
桌号格式错误,不以“table”开头。例如:
麻婆豆腐 12
油淋生菜 9 T
table 1 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
tab le 2 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
输出样例6:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 12
2 油淋生菜 14
wrong format
record serial number sequence error
record serial number sequence error
table 1: 26 17
其他用例请参考公开的测试用例
3、踩坑心得
oop04训练集给我留下的印象很深,有两题有叫做 “很慢” 的测试点,有时候写完了代码,带入几个常用的例子进去出来的结果都是对的但是就是过不了这个测试点。仔细想想,他叫很慢,是不是意思就是你的代码跑的很慢?写的不够简单?然后就把代码修改优化,果然通过了这个测试点。所以说写代码不仅仅是要求正确,在正确的基础上更要求简洁高效。
再就是学习了正则表达式以及日期的库方法之后我发现Java中有很多简洁的方法,Java的学习之旅还是很长的,广泛的学习能让我们在以后的很多场景节约时间。
最后最重要的就是不要粗心,英文和中文的标点符号使用不当真的会浪费很多时间去检查错误。还有就是代码的规范问题,写的不规范查错误太痛苦了(连夜去看阿里的规范手册)。
4、改进建议
1、写题目一定不能有畏难心理,不能看到题目有难度就放手不做,这样我们永远也解决不了难题。我们遇到难的问题可以把他分解成许许多多的简单的问题,遇到不会的知识点就去网上学习,去问室友同学老师,只有不断的问问题才能强化自己的写代码能力。
2、Java这个领域是很大的,我们在课余时间可以学习一下这个领域的“黑科技”。就像是在学习正则表达式之前解决oop05的问题就会很复杂,虽然不是鼓励我们什么都学,但是适当的学习课上没学到的东西对我们的Java学习绝对是有帮助的。
3、写一些复杂的题目可以先把框架弄出来再去写,就像是这次聚合日期类的题目,照着类图写很显然降低了这个题目的难度。
5、总结
最大的收获就是写复杂的题目先把类图画出来可以让题目变得简单(虽然类图不好解决)。遇到自己无法解决的问题可以多去思考,多花时间去磨它,滴水穿石,如果每次都不去思考,那几年之后遇到这种难题还是不能解决。最大的问题是上课听的就不是很明白,下课之后还不愿意花时间去理解,必须改正这种心态,多花时间在Java的学习上。
标签:总结,int,PTA,getValue,getDay,value,public,getMonth From: https://www.cnblogs.com/wzryq/p/17365887.html