PTA题目集4~6总结
Posted rccxs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PTA题目集4~6总结相关的知识,希望对你有一定的参考价值。
一前言
题目集四主要考察的是对LocalDate,ArrayList,HashSet等Java自带类的使用
题目集五主要考察的是对正则表达式的使用,以及对其题目集三的时间题目的进行类结构的改变
题目集六只有一道题,主要是对题目集四的第一题进行加大难度
总的来说这几次的题目量比前面几次都要少,但是题目难度开始加深。
二设计与分析
由于部分题目过于简单,所以这里主要是对题目集四的7-1,题目集五的7-5,7-6,题目集六的7-1进行分析
题目集四7-1:当时见到这道题时认为难度较大且复杂,所以在这次题目集时放弃了写这道题,但由于题目集六的7-1题目是在此基础上的加深所以主要在后面分析
题目集五7-5:此题目主要是我们将前面题目集三的7-3的进行如下类图的类结构更改
所以我们主要是对类图进行分析,我们发现各个类之间是聚合的关系,每一个类与类之间聚合,所以我们按照此类图设计类时应该由year到month到day到DateUtil之间一个个写。最后的题目要求的主要功能则在DateUtil这里实现,因为这里是最后一个聚合。
代码如下:
import java.util.Scanner; public class Main public static void main(String[] args) Scanner input = new Scanner(System.in); int year = 0; int month = 0; int day = 0; int choice = input.nextInt(); if (choice == 1) // test getNextNDays method int m = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) System.out.println("Wrong Format"); System.exit(0); m = input.nextInt(); if (m < 0) System.out.println("Wrong Format"); System.exit(0); System.out.println(date.getNextNDays(m).showDate()); else if (choice == 2) // test getPreviousNDays method int n = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) System.out.println("Wrong Format"); System.exit(0); n = input.nextInt(); if (n < 0) System.out.println("Wrong Format"); System.exit(0); System.out.println(date.getPreviousNDays(n).showDate()); else if (choice == 3) //test getDaysofDates method year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); int anotherYear = Integer.parseInt(input.next()); int anotherMonth = Integer.parseInt(input.next()); int anotherDay = Integer.parseInt(input.next()); DateUtil fromDate = new DateUtil(year, month, day); DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); if (fromDate.checkInputValidity() && toDate.checkInputValidity()) System.out.println(fromDate.getDaysofDates(toDate)); else System.out.println("Wrong Format"); System.exit(0); else System.out.println("Wrong Format"); System.exit(0); public static class Day int value; int mon_maxnum[]= new int[]0,31,28,31,30,31,30,31,31,30,31,30,31;//数组储存各月份天数 Month month = new Month(); Day() Day(int yearValue,int monthValue,int dayValue) value = dayValue; month = new Month( yearValue, monthValue); public void setValue(int value) this.value = value; public int getValue() return value; public Month getMonth() return month; public void setMonth(Month month) this.month = month; public void resetMin() value = 1; public void resetMax() if(month.year.isLeapYear()) mon_maxnum[2]=29; else mon_maxnum[2]=28; value = mon_maxnum[month.value]; boolean validate() if(value>mon_maxnum[month.value]||value<1) return false; else return true; public void dayIncrement() value++; public void dayReduction() value--; public static class Month int value; Year year = new Year(); Month() Month(int yearValue,int monthValue) value = monthValue; year.setValue(yearValue); public void setValue(int value) this.value = value; public int getValue() return value; public Year getYear() return year; public void setYear(Year year) this.year = year; public void resetMin() value = 1; public void resetMax() value = 12; boolean validate() if(value>12||value<1) return false; else return true; public void monthIncrement() value++; public void montReduction() value--; public static class Year int value; Year() Year(int value) this.value = value; public int getValue() return value; public void setValue(int value) this.value = value; boolean validate() if(value>2050||value<1900) return false; else return true; boolean isLeapYear() if((value%4==0&&value%100!=0)||value%400==0) return true; return false; void yearIncrement() value++; void yearReduction() value--; public static class DateUtil Day day = new Day(); DateUtil() DateUtil(int y,int m,int d) day = new Day(y,m,d); public Day getDay() return day; public void setDay(Day day) this.day = day; boolean checkInputValidity() if(day.month.year.isLeapYear()) day.mon_maxnum[2]=29; if(day.month.year.value<1900||day.month.year.value>2050||day.month.value<1||day.month.value>12||day.value<1||day.value>day.mon_maxnum[day.month.value]) return false; else return true; boolean compareDates(DateUtil date) if(this.day.month.year.value>date.day.month.year.value) return true; else if(this.day.month.year.value==date.day.month.year.value) if(this.day.month.value>date.day.month.value) return true; else if(this.day.month.value==date.day.month.value) if(this.day.value>date.day.value) return true; else return false; else if(this.day.month.year.value<date.day.month.year.value) return false; return false; boolean equalTwoDates(DateUtil date) if(this.day.month.year.value==date.day.month.year.value&&this.day.month.value==date.day.month.value&&this.day.value==date.day.value) return true; else return false; DateUtil getNextNDays(int n) int i; for(i=0;i<n;i++) if (day.month.year.isLeapYear()) day.mon_maxnum[2] = 29; else day.mon_maxnum[2] = 28; if (day.value != day.mon_maxnum[day.month.value]) day.dayIncrement(); else if (day.month.value == 12) day.month.resetMin(); day.resetMin(); day.month.year.yearIncrement(); else day.resetMin(); day.month.monthIncrement(); return this; DateUtil getPreviousNDays(int n) int i; for(i=0;i<n;i++) if(day.month.year.isLeapYear()) day.mon_maxnum[2]=29; else day.mon_maxnum[2]=28; if(day.value!=1) day.dayReduction();//判断月份是否需要变化 else if(day.month.value==1)//判断年份是否需要变化 day.month.value=12; day.value=31; day.month.year.yearReduction(); else day.month.montReduction(); day.value = day.mon_maxnum[day.month.value]; return this; int getDaysofDates(DateUtil date) int i,n=0; int j=365,k=366; if(this.compareDates(date))//比较两个日期判断是否进行进行更换操作 if(this.day.month.year.value==date.day.month.year.value) if(day.month.year.isLeapYear()) day.mon_maxnum[2]=29; else day.mon_maxnum[2]=28; for(i=date.day.month.value+1;i<this.day.month.value;i++) n=n+day.mon_maxnum[i]; n=n+day.mon_maxnum[date.day.month.value]-date.day.value+this.day.value; else for(i=date.day.month.year.value+1;i<this.day.month.year.value;i++) Year flag = new Year(i); if(flag.isLeapYear()) n=n+k; else n=n+j; for(i=date.day.month.value+1;i<=12;i++) if(day.month.year.isLeapYear()) day.mon_maxnum[2]=29; else day.mon_maxnum[2]=28; n=n+day.mon_maxnum[i]; for(i=1;i<this.day.month.value;i++) if(day.month.year.isLeapYear()) day.mon_maxnum[2]=29; else day.mon_maxnum[2]=28; n=n+day.mon_maxnum[i]; n=n+day.mon_maxnum[date.day.month.value]-date.day.value+this.day.value; else int z,x,c;//中间变量更换日期 z=this.day.month.year.value; x=this.day.month.value; c=this.day.value; this.day.month.year.value=date.day.month.year.value; this.day.month.value=date.day.month.value; this.day.value=date.day.value; if(this.day.month.year.value==z) if(day.month.year.isLeapYear()) day.mon_maxnum[2]=29; else day.mon_maxnum[2]=28; if(this.day.value==c)//判断是否日期相等 n=0; else for(i=x+1;i<this.day.month.value;i++) n=n+day.mon_maxnum[i]; n=n+day.mon_maxnum[x]-c+this.day.value; else for(i=z+1;i<this.day.month.year.value;i++) Year flag = new Year(i); if(flag.isLeapYear()) n=n+k; else n=n+j; for(i=x+1;i<=12;i++) if(day.month.year.isLeapYear()) day.mon_maxnum[2]=29; else day.mon_maxnum[2]=28; n=n+day.mon_maxnum[i]; for(i=1;i<this.day.month.value;i++) if(day.month.year.isLeapYear()) day.mon_maxnum[2]=29; else day.mon_maxnum[2]=28; n=n+day.mon_maxnum[i]; n=n+day.mon_maxnum[x]-c+this.day.value; return n; String showDate() String showDate; showDate=day.month.year.value+"-"+day.month.value+"-"+day.value; return showDate;
题目集五7-6
这题与前面题目相差不多主要是按照题目要求的类图结构进行更改
我们对类图进行分析,我们发现这题与前面的题目相似的是:类之间的关系仍然是聚合,不一样的是:类聚合不在是一个类一个类的聚合而是别的类聚合一个主要菜单实现功能的类。
代码如下:
import java.util.Scanner; public class Main public static void main(String[] args) Scanner input = new Scanner(System.in); int year = 0; int month = 0; int day = 0; int choice = input.nextInt(); if (choice == 1) // test getNextNDays method int m = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) System.out.println("Wrong Format"); System.exit(0); m = input.nextInt(); if (m < 0) System.out.println("Wrong Format"); System.exit(0); System.out.print(date.year.value + "-" + date.month.value + "-" + date.day.value + " next " + m + " days is:"); System.out.println(date.getNextNDays(m).showDate()); else if (choice == 2) // test getPreviousNDays method int n = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) System.out.println("Wrong Format"); System.exit(0); n = input.nextInt(); if (n < 0) System.out.println("Wrong Format"); System.exit(0); System.out.print( date.year.value + "-" + date.month.value + "-" + date.day.value + " previous " + n + " days is:"); System.out.println(date.getPreviousNDays(n).showDate()); else if (choice == 3) //test getDaysofDates method year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); int anotherYear = Integer.parseInt(input.next()); int anotherMonth = Integer.parseInt(input.next()); int anotherDay = Integer.parseInt(input.next()); DateUtil fromDate = new DateUtil(year, month, day); DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); if (fromDate.checkInputValidity() && toDate.checkInputValidity()) System.out.println("The days between " + fromDate.showDate() + " and " + toDate.showDate() + " are:" + fromDate.getDaysofDates(toDate)); else System.out.println("Wrong Format"); System.exit(0); else System.out.println("Wrong Format"); System.exit(0); public static class Day Day() Day(int value) int value; public void setValue(int value) this.value = value; public int getValue() return value; void dayIncrement() value++; void dayReduction() value--; public static class Year int value; Year() Year(int value) this.value = value; public int getValue() return value; public void setValue(int value) this.value = value; boolean validate() if(value>2020||value<1820) return false; else return true; boolean isLeapYear() if((value%4==0&&value%100!=0)||value%400==0) return true; return false; void yearIncrement() value++; void yearReduction() value--; public static class Month Month() Month(int value) this.value = value; int value; public int getValue() return value; public void setValue(int value) this.value = value; boolean validate() if(value>12||value<1) return false; else return true; public void monthIncrement() value++; public void montReduction() value--; public void resetMin() value = 1; public void resetMax() value = 12; public static class DateUtil Day day = new Day(); Month month = new Month(); Year year = new Year(); int mon_maxnum[]= new int[]0,31,28,31,30,31,30,31,31,30,31,30,31;//数组储存各月份天数 DateUtil() DateUtil(int y, int m,int d) this.day.value = d; this.month.value = m; this.year.value = y; public Year getYear() return year; public void setYear(Year year) this.year = year; public Month getMonth() return month; public void setMonth(Month month) this.month = month; public Day getDay() return day; public void setDay(Day day) this.day = day; public void setDayMin() day.value = 1; public void setDayMax() if(year.isLeapYear()) mon_maxnum[2] = 29; else mon_maxnum[2] = 28; day.value = mon_maxnum[month.value]; public boolean checkInputValidity() if(year.isLeapYear()) mon_maxnum[2] = 29; else mon_maxnum[2] = 28; if(year.validate()&&month.validate()&&day.value>=1&&day.value<=mon_maxnum[month.value]) return true; else return false; DateUtil getNextNDays(int n) int i; for(i=0;i<n;i++) if (year.isLeapYear()) mon_maxnum[2] = 29; else mon_maxnum[2] = 28; if (day.value != mon_maxnum[month.value]) day.dayIncrement(); else if (month.value == 12) month.resetMin(); setDayMin(); year.yearIncrement(); else setDayMin(); month.monthIncrement(); return this; DateUtil getPreviousNDays(int n) int i; for(i=0;i<n;i++) if(year.isLeapYear()) mon_maxnum[2]=29; else mon_maxnum[2]=28; if(day.value!=1) day.dayReduction(); else if(month.value==1) month.value=12; day.value=31; year.yearReduction(); else month.montReduction(); day.value = mon_maxnum[month.value]; return this; boolean compareDates(DateUtil date) if (this.year.value > date.year.value) return true; else if (this.year.value == date.year.value) if (this.month.value > date.month.value) return true; else if (this.month.value == date.month.value) if (this.day.value > date.day.value) return true; else return false; else if (this.year.value < date.year.value) return false; return false; boolean equalTwoDates(DateUtil date) if(this.year.value==date.year.value&&this.month.value==date.month.value&&this.day.value==date.day.value) return true; else return false; int getDaysofDates(DateUtil date) int i,n=0; int j=365,k=366; if(this.compareDates(date))//比较两个日期判断是否进行进行更换操作 if(this.year.value==date.year.value) if(this.year.isLeapYear()) mon_maxnum[2]=29; else mon_maxnum[2]=28; for(i=date.month.value+1;i<this.month.value;i++) n=n+mon_maxnum[i]; n=n+mon_maxnum[date.month.value]-date.day.value+this.day.value; else for(i=date.year.value+1;i<this.year.value;i++) Year flag = new Year(i); if(flag.isLeapYear()) n=n+k; else n=n+j; for(i=date.month.value+1;i<=12;i++) if(year.isLeapYear()) mon_maxnum[2]=29; else mon_maxnum[2]=28; n=n+mon_maxnum[i]; for(i=1;i<this.month.value;i++) if(year.isLeapYear()) mon_maxnum[2]=29; else mon_maxnum[2]=28; n=n+mon_maxnum[i]; n=n+mon_maxnum[date.month.value]-date.day.value+this.day.value; else int z,x,c;//中间变量更换日期 z=this.year.value; x=this.month.value; c=this.day.value; this.year.value=date.year.value; this.month.value=date.month.value; this.day.value=date.day.value; if(this.year.value==z) if(year.isLeapYear()) mon_maxnum[2]=29; else mon_maxnum[2]=28; if(this.day.value==c)//判断是否日期相等 n=0; else for(i=x+1;i<this.month.value;i++) n=n+mon_maxnum[i]; n=n+mon_maxnum[x]-c+this.day.value; else for(i=z+1;i<this.year.value;i++) Year flag = new Year(i); if(flag.isLeapYear()) n=n+k; else n=n+j; for(i=x+1;i<=12;i++) if(year.isLeapYear()) mon_maxnum[2]=29; else mon_maxnum[2]=28; n=n+mon_maxnum[i]; for(i=1;i<this.month.value;i++) if(year.isLeapYear()) mon_maxnum[2]=29; else mon_maxnum[2]=28; n=n+mon_maxnum[i]; n=n+mon_maxnum[x]-c+this.day.value; return n; String showDate() String showDate; showDate=year.value+"-"+month.value+"-"+day.value; return showDate;
题目集六 7-1
此题与前面的题目集四7-1的大体相同,但是加入了带点菜功能,特色菜和各种异常情况处理,所以这道题是及其复杂的,但是我们首先明白一个程序的运行离不开的是输入,进行运行,输出。所以我们一步一步慢慢来就行。
首先我们对题目进行分析我们发现这个题目的输入方式为直到输入end才会结束,所以显而易见的我们这里要用一个循环输入,且要判断输入end的时候结束循环,所以我们要以end为标识符作为首要判断,根据题目的空格输入我们就应该明白这里我们要使用split方法,进行去空格产生字符数组,根据数组的大小内容进行判断进行相应方法。
代码如下:
while (true) String s1 = input.nextLine(); s = s1.split(" "); if(s1.equals("end")) break; flag = s.length; if(flag == 2) if(s[1].equals("delete")) a1 = Integer.parseInt(s[0]); if (table[a4].order.findRecordByNum(a1)!=null) if(table[a4].order.findRecordByNum(a1).portion != 0) a6 = table[a4].order.findRecordByNum(a1).getPrice(); table[a4].order.findRecordByNum(a1).portion = 0; if(table[a4].order.findRecordByNum(a1).d.flag!=0) table[a4].sum = table[a4].sum - a6; table[a4].order.findRecordByNum(a1).portion = 0; else float h = a6*0.7f; table[a4].sum = table[a4].sum - Math.round(h); else System.out.println("deduplication "+a1); else System.out.println("delete error"); else if(table[a4] == null) dishName = s[0]; if( s[1].matches(ruller)) a1 = Integer.parseInt(s[1]); menu.dishs[a5] = menu.addDish(dishName, a1); a5++; else System.out.println("wrong format"); else System.out.println("invalid dish"); else if (flag == 3) if(s[2].equals("T")) dishName = s[0]; a1 = Integer.parseInt(s[1]); menu.dishs[a5] = menu.addDish(dishName,a1); menu.dishs[a5].flag = 0; a5++; else if (flag == 4) if(s[0].equals("table")) if( s[1].matches(ruller)) a4 = Integer.parseInt(s[1]); if(a4<=55&&a4>=1) table[a4] = new Table(a4); table[a4].Doing(s[2], s[3]); if (table[a4].checkTime()) System.out.println("table" + " " + table[a4].tableNum + ":" + " "); else System.out.println(a4 + " date error"); else System.out.println(s[1]+" table num out of range"); else System.out.println("wrong format"); else a1 = Integer.parseInt(s[0]); dishName = s[1]; a2 = Integer.parseInt(s[2]); a3 = Integer.parseInt(s[3]); if (table[a4] != null) if (a2 >= 1 && a2 <= 3 && a3 > 0 && a3 <= 15) Dish otherDish = menu.searthDish(dishName); if (otherDish != null) table[a4].order.addARecord(a1, dishName, a2, a3); table[a4].order.findRecordByNum(a1).d = otherDish; a7 = table[a4].order.findRecordByNum(a1).getPrice(); if (table[a4].order.findRecordByNum(a1).d.flag == -1) float k = a7 * table[a4].discount; int t = Math.round(k); table[a4].sum += t; else if (table[a4].week <= 5 && table[a4].week >= 1) float v = a7 * 0.7f; table[a4].sum += Math.round(v); else if (table[a4].week == 6 || table[a4].week == 7) table[a4].sum += a7; System.out.println(a1 + " " + dishName + " " + table[a4].order.findRecordByNum(a1).getPrice()); else else if (a2 < 1 || a2 > 3 && a3 > 0 && a3 <= 15) System.out.println(a1 + " portion out of range " + a2); else if (a3 < 0 || a3 > 15) System.out.println(a1 + " num out of range " + a3); else else if (flag ==5) else System.out.println("wrong format");
我们对输入数据进行判断后我们应该要进行对主要方法的实现,所以我们要开始对其他类的设计,如dish,tabale等类
我们首先判断类与类之间的关系,我们可以知道各个类之间的关系为依赖,所以可以开始对各个类进行实现,代码如下
class Dish String name = " " ;//菜品名称 int unit_price = 0; //单价 int flag = -1; int portion; Dish() Dish(String name,int unit_price) this.name = name; this.unit_price = unit_price; int getPrice(int portion) int p2 = 0; if(portion == 1) p2 = this.unit_price; else if (portion == 2) float p1 = (float) (this.unit_price * 1.5); p2 = Math.round(p1); else if (portion == 3) float p1 = this.unit_price * 2; p2 = Math.round(p1); else return p2; //计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) public void setName(String name) this.name = name; public String getName() return name; public int getUnit_price() return unit_price; public void setUnit_price(int unit_price) this.unit_price = unit_price; class Menu Dish[] dishs = new Dish[10];//菜品数组,保存所有菜品信息 int count = 0; Dish searthDish(String dishName) Dish temd = null; for(int i=count-1;i>=0;i--) if(dishName.equals(dishs[i].name)) temd = dishs[i]; break; if(temd==null) System.out.println(dishName+" does not exist"); return temd; //根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price) Dish dh = new Dish(); dh.name = dishName; dh.unit_price = unit_price; count++; return dh; //添加一道菜品信息 class Record int orderNum;//序号 int Num = 1;//份额 Dish d = new Dish();//菜品\\\\ int portion = 0;//份额(1/2/3代表小/中/大份) Record() Record(int orderNum,int num,int portion) this.orderNum = orderNum; this.Num = num; this.portion = portion; int getPrice() return d.getPrice(portion)*Num; //计价,计算本条记录的价格 public Dish getD() return d; public int getNum() return Num; public int getOrderNum() return orderNum; public int getPortion() return portion; public void setD(Dish d) d = new Dish(); this.d = d; public void setNum(int num) Num = num; public void setOrderNum(int orderNum) this.orderNum = orderNum; public void setPortion(int portion) this.portion = portion; class Table int mon_maxnum[]= new int[]0,31,28,31,30,31,30,31,31,30,31,30,31;//数组储存各月份天数 Table() Table(int tableNum) this.tableNum = tableNum; Table(Order order) this.order = order; Order order = new Order(); String time; int week; int hour,minute,second,year,month,day; float discount = -1; int sum = 0; int tableNum = -1; //处理时间 public void processTime(String time1,String time2) DateTimeFormatter JEFormatter = DateTimeFormatter.ofPattern("yyyy/M/d"); LocalDate l1 = LocalDate.parse(time1,JEFormatter); week = l1.getDayOfWeek().getValue(); String[] time3 = time2.split("/"); hour = Integer.parseInt(time3[0]); minute = Integer.parseInt(time3[1]); second = Integer.parseInt(time3[2]); String[] time4 = time1.split("/"); year = Integer.parseInt(time4[0]); month = Integer.parseInt(time4[1]); day = Integer.parseInt(time4[2]); public void setDiscount() if(week<=5&&week>=1) if(hour>=17&&hour<20) discount=0.8F; else if(hour==20&&minute<30) discount=0.8F; else if(hour==20&&minute==30&&second==0) discount=0.8F; else if(hour>=11&&hour<=13||hour==10&&minute>=30) discount=0.6F; else if(hour==14&&minute<30) discount=0.6F; else if(hour==14&&minute==30&&second==0) discount=0.6F; else if(hour>=10&&hour<=20) discount= 1.0F; else if(hour==9&&minute>=30) discount= 1.0F; else if(hour==21&&minute<30||hour==21&&minute==30&&second==0) discount= 1.0F; public int getMoney() return Math.round(sum * discount); public void Doing(String time1,String time2) processTime(time1,time2); setDiscount(); public void setTableNum(int tableNum) this.tableNum = tableNum; public void setOrder(Order order) this.order = order; public Order getOrder() return order; public void setSum() sum = this.order.getTotalPrice(); void Gettottalprice() if(discount>0) System.out.println("table " + tableNum + ": " + this.order.getTotalPrice()+" "+ sum); else System.out.println("table " + tableNum + " out of opening hours"); boolean checkTime() if(year<1000||month<1||month>12||day<0||day>mon_maxnum[month]||hour<1||hour>24||minute<0||minute>60||second<0||second>60) return false; else return true; boolean checkTimeRange() if(year<2022||year>2023) return false; else return true; public int getWeek() return week; class Order private List<Record> records = new ArrayList<>(); //保存订单上每一道的记录 int totalPrice; int tableNum; Menu menu = new Menu(); int getTotalPrice() for(Record record : records) totalPrice = record.getPrice()+totalPrice; return totalPrice; //计算订单的总价 Record addARecord(int orderNum,String dishName,int portion,int num) Record record = new Record(orderNum,num,portion); record.d.setName(dishName); records.add(record); return record; //添加一条菜品信息到订单中。 void delARecordByOrderNum(int orderNum) for(Record record : records) if(record.getOrderNum() == orderNum) records.remove(record); //根据序号删除一条记录 Record findRecordByNum(int orderNum) for(Record record : records) if(record.getOrderNum() == orderNum) return record; return null; //根据序号查找一条记录 public int getTableNum() return tableNum;第一次博客:PTA题目集1-3总结
第一次博客:PTA题目集1-3总结前言:JAVA是一门非常好的语言,因其面向对象的思想,在解决问题时思路与上学期学习的C语言截然不同,但是其优势也是显然易见的,特别是在写大型程序时其面向对象的思想,可以让人思路清晰。
这次PTA中三个“菜单计价”的题目让刚刚学习JAVA的我感到无力,但是在一阵磕磕碰碰之后终于还是解决了问题,以下是对题目的一些分析与总结:这几次的题目量以及难度按老师的说法是和上一届比简单了许多,但是突然使用一种新的编程语言和编程方式进行编程还是相当困难的。
题目概述:
第一次:虽然有9题但是总的来说题目不算难并没有用到“类”的思想,其主要目的是让我们熟悉JAVA语言的基本使用,以及各种类库的基本使用。
以下是各题的知识点考察:
知识储备:1.使用Scanner输入以及System.out输出 2.不同类型的变量的定义以及输入 3.类库的简单使用。
7-1 身体质量指数(BMI)测算 7-2 长度质量计量单位换算 7-4 房产税费计算2022 7-5 游戏角色选择:考察简单的输入(注意:输入为浮点型)以及条件判断(if—else)和输出。
7-3 奇数求和:考察在循环中进行输入和判断以及求合操作。
7-6 学号识别 7-9 二进制数值提取:考察(String)字符串操作类(substring,length,charAt)的使用。
7-8 巴比伦法求平方根近似值:考察(Math)类(abs)求绝对值的使用的使用。
7-7 判断三角形类型:考察判断的嵌套(分好类可以打的很漂亮)以及浮点类型数比较(需要设定精度)。
第二次:从这次开始上难度了!!!蔡老师开始向你展示JAVA的限额,但是困难总是伴随着成长,那些打不倒你的,只会使你变的更加强大;
知识储备:1.对类与方法的基础使用 2.日期类的简单使用 3简单算法的使用 4类型转换。
这里可以窥见面向对象思想的雏形,特别是“菜单计价1,2”以及“7-3 jmu-java-日期类的基本使用”,还有那阴间的测试点折磨的我痛不欲生,还好我是 一个阳光开朗大男孩,在连续问了七八个大佬后终于还是做出来了。下面简单分析7-3,7-4 剩下两个为菜单系列后面会统一分析
7-3 jmu-java-日期类的基本使用
难度:中等。
考察对JAVA日期类的使用(Date、DateFormat、Calendar)都可以,其实真正难的是这题的类需要自己进行设计对于一个JAVA小白来说这简直就是”难于上青天“,且因为阴间的测试点,即使你的代码过了所有的测试点(例如:2022-10--1,如果使用字符串分割函数就会少一位导致后续判断失误)但是可能提交后一分也拿不到,而因为当时没有学习正则表达式,所以对输入的正确的判断变的十分困难——需要判断长度,是否为数字以及时间是否合法为此我还特意写了一个类。下面是我使用的(Calendar)以及正则表达式。
class 判断日期
Calendar c = Calendar.getInstance();//父类引用指向子类对象,右边的方法返回一个子类对象
void 日期(int year,int month,int day)
c.set(year,month-1,day);//设置时间
int a=c.get(Calendar.DAY_OF_YEAR);
int b=c.get(Calendar.DAY_OF_MONTH);
int d=c.get(Calendar.DAY_OF_WEEK);
//星期天为1
if(d==1)
d=7;
else
d-=1;
System.out.printf("%04d-%02d-%02d是当年第%d天,当月第%d天,当周第%d天.\\n",year,month,day,a,b,d);
// 2021-02-28是当年第59天,当月第28天,当周第7天.
class 比较日期大小
Calendar c1 = Calendar.getInstance();//日期1
Calendar c2 = Calendar.getInstance();//日期2
void 比较(int year1,int month1,int day1,int year2,int month2,int day2)
c1.set(year1,month1-1,day1);
c2.set(year2,month2-1,day2);
int days = ((int)(c2.getTime().getTime()/1000)-(int)(c1.getTime().getTime()/1000))/3600/24;
System.out.printf("%d-%02d-%02d与%d-%02d-%02d之间相差%d天,所在月份相差%d,所在年份相差%d.\\n",year2,month2,day2,year1,month1,day1,days,month2-month1,year2-year1);
//2020-01-02与2019-08-01之间相差154天,所在月份相差-7,所在年份相差1.
注:输入月份要-1,因为(calendar)的月份是从第0月开始的,以及其星期天为第1天,所有需要进行转换操作
正则表达式:
String timeRegex2 = "([-9][[91[0-9[2[-91][0-9][0-9161][919-9121[910913(1((([5[18101(191][201013[01]))|*+"(146911)1)(01[0912]2101010)(2()01091010~1010)((-9]2)(0[48][2468]048][13579]126])[+(181][4161481][35791]3]0)))02\\29)$";
//写的有点麻烦不知可否简化
注:使用这个两行就可以解决问题
7-4 小明走格子:
难度:中等。
这题找到规律其实计算并不困难(走到第n格的方法数等于走到前四格的方法数的总和)我使用了递归,但是难的是解决运行超时的问题,这让我想到可以使用记忆化搜索(其原理为将之前的运算结果进行储存,使函数不会进行重复计算);
//b用于储存数据
static int[] b=new int[10009];
//d用于记忆化搜索//1为以有数据
static boolean[] d=new boolean[10009];//当d[n]为true时说明a[n]已经有数据不用重复进行运算
static int dfs(int x)
if(x==0)
return 1;
else if(x==1)
return 1;
else if(x==2)
return 2;
else if(x==3)
return 4;
else if(x==4)
return 8;
else
if(d[x])
return b[x];
else
d[x]=true;
b[x]=dfs(x-1)+dfs(x-2)+dfs(x-3)+dfs(x-4);
return b[x];
但是遗憾的是即使使用了记忆化搜索还是有一个测试点不能通过(出题老师把运行时卡的太死了),无奈只能求助于网络,其原因为使用(scanner)进行输入效率很低,应当改用(BufferedReader)进行输入,下面附上相应代码;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
int n=0;
tryn = Integer.parseInt(in.readLine());
catch (Exception e)
e.printStackTrace();
注意:确实非常麻烦但是其效率是(scannre)的两倍,以后有运行时问题可以考虑使用。
第三次:这次可谓是时间紧任务重,6天7题实在是有点困难不过相对与上一次这次每题(第1题除外)的平均代码量远小于上一次,其主要考察方向为集合以及各种方法的使用(即运行时问题为主要问题),做的时候一定要切记不能使用暴力求解!!!像我这样一个上学期C语言算法没有好好学的就深受其害。所有的这次的方法都是网上即学即用,只能说:CSDN YYDS。
知识储备:1.对集合有基本认识(没有学习的话会带上痛苦面具) 2.一些算法基本知识(所有语言的算法都是互通的) 3.对封装性有基本认识(类,属性,方法的公有与私有)。
7-2 有重复的数据:使用双循环明显是不明智的,这里建议使用sort或MAP判重 因为只需要判断是否重复不需要将原输入进行处理后输出所以无论是使用那一种都十分的方便。下面是我使用的sort 其原理为将数组使用二分法进行快速排序,之后只需要判断每一个元素与其下一个元素是否相等即可(一重循环)。
import java.util.Scanner;
import java.util.Arrays;
public class Main
public static void main(String[] args)
Scanner in = new Scanner(System.in);
int n;
数据处理 b=new 数据处理();
n=in.nextInt();
int[] a=new int[n];
boolean flag=true;
for(int i=0;i<n;i++)
a[i]=in.nextInt();
Arrays.sort(a);//排序
b.排序(a);
b.查重(a);
if(flag)
System.out.println("NO");
else
System.out.println("YES");
class 数据处理
int[] 排序(int[] a)
Arrays.sort(a);
return a;
boolean 查重(int[] a)
for(int i=0;i<len-1;i++)
if(a[i]==a[i+1])
return false;
return true;
看似完美但是我忽略了一个重要的问题(内存),于是我带上了痛苦面具,在一番深思熟虑后我发现了问题所在每次无论是使用“数据处理”中的 “排序” 还是“查重”方法都要开一个与a[]等大的数组导致内存超限。于是乎我将 “数据处理”类并入main中解决了这因为画蛇添足导致的问题。
import java.util.Scanner;
import java.util.Arrays;
public class Main
public static void main(String[] args)
Scanner in = new Scanner(System.in);
int n;
// 数据处理 b=new 数据处理();
n=in.nextInt();
int[] a=new int[n];
boolean flag=true;
for(int i=0;i<n;i++)
a[i]=in.nextInt();
Arrays.sort(a);//排序
for(int i=0;i<n-1;i++)
if(a[i]==a[i+1])
flag= false;
break;
if(flag)
System.out.println("NO");
else
System.out.println("YES");
事实证明不要整花活!!!
7-3 去掉重复的数据:这题就是7-2plus,要求去除重复数据并输出,明显是不能使用sort了,但是观察数据为数字所以可以考虑使用数组标记法(多开一个标记数组,输入a[i],b[a[i]]++,这样子只需要检测b[a[i]]是否为1,即可判断是否需要进行输出 )但是容易爆内存。所以这里我选择使用LinkedHashSet为什么不能使用Set呢???因为题目要求按原来的数据进行输出而Set,HashSet内存放的数据都是无序的(与输入顺序不同)而LinkedHashSet内部的数据是有序的(与输入顺序相同)下面是基本使用方法。
//定义
Set<String> set = new LinkedHashSet<String>();
//添加元素
set.add(a);
//使用迭代器输出
Iterator<String> iter = set.iterator();
while(iter.hasNext())
System.out.print(" "+iter.next()); //输出是有序的
7-4 单词统计与排序 一个典型的自定义排序问题,但是在输入处理这块就把我难住了,同时使用"," " " "."进行字符串分割,直接a=in.nextLine();String[] arr = a.split(" |,|.");当两个分割标志同时出现时会有多余字符出现如输入样例中同时有“,和 空格”会导致数组中会有一个空格多余而导致大错误。所以我先使用空格进行分割,之后使用循环遍历所有字符去除"."和","(注:千万不能先排序,然后在输出的时候去除"."和",",这样子的话"hello."将会和"hello"被视为相同的字符串)某个大聪明(指我自己)犯了这种低级错误。
如果是C语言的话我会用sort重构compare函数进行排序然后进行去重,当然JAVA也可以怎么做,但是我想试试集合TreeSet重构排序解决问题。下面是ThreeSet的简单使用以及重载函数的写法
//定义:
Set<String> set = new TreeSet<String>(new SortDescending());//使用自定义排序
//添加元素
set.add(b);
//重载比较方法
class SortDescending implements Comparator //自定义排序
@Override//重载方法标志
public int compare(Object o1, Object o2)
String s1 = (String) o1;
String s2 = (String) o2;
if(s1.length()>s2.length())//按长度比较
return -1;
else if(s1.length()<s2.length())
return 1;
else //长度相等
return s1.compareToIgnoreCase(s2);//按字典序比较//不分大小写
7-5 面向对象编程(封装性):考察构造方法的使用,难度偏低,唯一要注意的点是:写了有参构造方法会覆盖掉原来自带的无参构造方法,所以需要再手写一个无参构造方法以保证可以使用无参构造方法构造对象
7-6 GPS测绘中度分秒转换:这个题目主要考察格式化输出,但是如果全部采用格式化输出 "秒" 将不能保持与输入位数相等,所以解题思路为“度”“分”“秒”使用普通输出方式进行输出(print),结果使用格式输出(printf)以控制6位小数。
7-7 判断两个日期的先后,计算间隔天数、周数:这题的方法在 第二次作业7-3 jmu-java-日期类的基本使用 中讲过这里就不再赘述了,但是有一点值得注意的是如果使用的是(Date、DateFormat)类进行求解,因为其时间输入格式要求所以应当将输入转换为统一格式(2022-6-6>>2022-06-06)。
菜单系列
这是蔡老师对我们全体学生的爱,麻婆豆腐 12 油淋生菜 9 想必所有同学都以及烂熟于心了吧。按老师的说法,这比上一届的三角形简单一些,而且蔡老师贴心的为我们先写好了框架,我们最重要做的是对类中方法的调度,作为一个初学JAVA的新手,这过于复杂的题目曾一度让我想要放弃,无数次非零返回,答案错误,段错误,让我带上了痛苦面具,不过在鏖战了几天几夜之后我还是勉强将其做了出来。下面我将一一介绍这三座大山的不同难度以及特点。
知识储备:1.对JAVA类初步认识 2.类的设计 3.类中方法的设计 4.对象的使用
菜单计价程序-1 这是这个系列的第一题难度当然是比不上后面俩题,但是正所谓万事开头难,这复杂的类间关系,和我那浅薄的知识量,CPU烧了!!!不过通过这题我对JAVA类的创建和调度已经算是初窥门径,所有没有压力就没有动力,人的潜能是被逼出来的。
过程非常的简单用户输入点菜,计价,输出,计算总价,要是不用面向对象的思想,使用面向过程的方法我很快就可以将其写成,但是使用面向对象我就不行了,下面我简单介绍一下我认为得各个类的作用和类间的调度与交流。
1.Dish 菜品类:对应菜谱上一道菜的信息。没有在主类中直接使用,但是菜单和点菜记录都要依赖于它,其中的getPrice(int portion)方法是于点菜记录中的getPrice()方法对应的。
2.Menu 菜谱类:对应菜谱,包含饭店提供的所有菜的信息。内有一个Dish类的对象数组用于存菜单内的菜,以及一个Dish类型的方法 searthDish(String dishName)用于配合点菜记录进行查找比对,并返回这道菜(内含有该菜的价格)用于后续计算
3.Record :点菜记录类:保存订单上的一道菜品记录,配合Menu类里的searthDish(String dishName)和Dish类里的getPrice(int portion)计算菜品的价格
4.Order:订单类:保存用户点的所有菜的信息。 内含Record数组用于储存订单信息,getTotalPrice()/方法/计算订单的总价,addARecord(String dishName,int portion)用于输入
大体流程:循环输入以“end”作为结束标记,使用Order类的addARecord(String dishName,int portion)方法存入订单中,使用循环遍历订单并使用Menu中的 searthDish(String dishName)方法进行比对做出相应的输出,最后使用Order类的getTotalPrice()计算总价。
一些技巧:1.计算要求四舍五入,但是对于本题没有可以直接对“西红柿炒蛋 15”和 “油淋生菜 9”进行特殊处理,即计算结果加1;
2.在点菜时点到菜单没有的菜时searthDish(String dishName)可以返回null,然后通过判断返回值进行相应输出,也可以在返回null前进行输出“菜不存在”。
菜单计价程序-2这比菜单1多加了菜单写入,以及删菜的功能,如果上一题,打的思路清晰,明明白白的话这题就不会很难,由于很多重复的地方所有这里仅讲解不同的部分。
2.Menu 菜谱类:对应菜谱,包含饭店提供的所有菜的信息。内有一个Dish类的对象数组用于存菜单内的菜,addDish(String dishName,int unit_price)方法用于将输入的菜品存入菜单,以及一个Dish类型的方法 searthDish(String dishName)用于配合点菜记录进行查找比对,并返回这道菜(内含有该菜的价格)用于后续计算。
4.Order:订单类:保存用户点的所有菜的信息。 内含Record数组用于储存订单信息,getTotalPrice()/方法/计算订单的总价,addARecord(String dishName,int portion)用于输入,delARecordByOrderNum(int orderNum)用于删除订单内的菜品。
大体流程:循环输入以“end”作为结束标记,将输入进行分类,创建菜单时使用Mneu类的addDish(String dishName,int portion)方法储存菜单信息,点菜时使用Order类的addARecord(String dishName,int portion)方法存入订单中,使用循环遍历订单并使用Menu中的 searthDish(String dishName)方法进行比对做出相应的输出,删菜时使用Order类中的delARecordByOrderNum(int orderNum)方法进行删除并做出相应删除,最后使用Order类的getTotalPrice()计算总价。
一些技巧:1.输入后使用字符串分割函数进行分割(String[] arr = a.split(" ");),之后使用(arr.length)判断数组内元素个数,若为4则为点菜,若为2则判断第二个元素是否 为delete若是则为删菜,否则为加菜到菜谱中。
2.计算要求四舍五入(不能像上面那样投机取巧)因只有五入所以可以直接向上取整((int)Math.ceil(1.0*unit_price*3/2);。
3.删除菜品的时候因为点菜都有编号(且为递增的)所以可以直接与订单数进行比较判断该删除序号是否存在
4.删除菜品的时候可以返回菜品价格之后在计算总价的时候减去,也可以直接将订单中该菜的份数(或价格)改为0。
5.遍历菜单时倒序遍历可以保证读到的是最新的菜信息
菜单计价程序-3在2的基础上加入了,桌,以及待点菜,还有营业时间的判定。感觉一下子就复杂起来了,而且桌类需要我们自己设计,吐槽一下:这题的题目有问题,结束时间应该是21:30,题目上写的是21:00搞的我想跳楼。其他确实没有什么太大的变化,主要就是桌类的设计。下面简单介绍一下我的设计思路。
Table:桌类需要有这一桌的所有信息,所以属性有(
int tablenum;//桌号
String time;//点菜时间
int year=0,month=0,day=0,ww=0,hh=0,mm=0,ss=0;
boolean flag=true;//判断时间是否正确
double count=0;//折扣
Order selforder=new Order();//本桌订单),而方法有对时间的处理,判断营业与折扣,计算总价。
大体流程:首先创建一个Table类的数组,循环输入以“end”作为结束标记,将输入进行分类,创建菜单时使用Mneu类的addDish(String dishName,int portion)方法储存菜单信息,加桌的时候将信息存入Table类的数组中的time属性中,点菜时使用Table对象中Order类的addARecord(String dishName,int portion)方法存入订单中(待点菜与其相同),使用循环遍历订单并使用Menu中的 searthDish(String dishName)方法进行比对做出相应的输出,删菜时使用Order类中的delARecordByOrderNum(int orderNum)方法进行删除并做出相应删除,最后使用Table对象的getTotalPrice()计算总价并做出相应输出。
一些技巧:1.判断是否在营业时间时,可以将Table类中中的count//折扣初始化为0,首先计算折扣,若折扣为0则判断为不在营业设计。
2.四舍五入sum=(int)(sum*count+0.5);用这个就可以了
下面附上我的折扣计算:
void jscount()//运用时间计算折扣
if(ww>=1&&ww<=5)
if(hh>=17&&hh<20)
count=0.8;
else if(hh==20&&mm<30)
count=0.8;
else if(hh==20&&mm==30&&ss==0)
count=0.8;
else if(hh>=11&&hh<=13||hh==10&&mm>=30)
count=0.6;
else if(hh==14&&mm<30)
count=0.6;
else if(hh==14&&mm==30&&ss==0)
count=0.6;
else
if(hh>=10&&hh<=20)
count=1.0;
else if(hh==9&&mm>=30)
count=1.0;
else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0)
count=1.0;
菜单系列踩坑心得(这世上本没有坑,踩的人多了就成了坑)
1.可以去elicpice上测试,但是搞完复制回PTA一定一定要把package删了,以及主类改为Main,会非零返回。
2.使用数组元素时一定要先nuw
3.对象第一次new了之后,无论在那都不要再new了不然会变成null
4.访问数组不能越界,会有段错误
5.只要不是void类型的方法一定要保证所有情况都有返回值,会非零返回
6.不能在定义属性的地方使用方法,如7-1中对菜单的初始化
7.一些超时可能是圈复杂度过高,或循环没有出口下面是我的第三个菜单的圈复杂度
8.7-3一定要注意方法的重复执行(对同一道菜算了两次单价),否则会运行超时,好的解决方法是,在Table类中加入sum属性用于计算总价(每次算完单价后直接加)
t[i-1].selforder.addARecord(dd1, dd2, arr[2], dd3,dd4);
g=c.searthDish(arr[2]);
if(g!=null)
t[i-1].selforder.records[k].d=g;
int x=t[i-1].selforder.records[k].getPrice();
//4 table 2 pay for table 1 12
System.out.println(dd2+" table "+i+" pay for table "+dd1+" "+x);
t[i-1].sum+=x;
k++;
总结:
通过这三次PTA大作业,我深刻感受到了,面向对象与面向过程的差别,对类有了一定的认识,题目都不算特别难,但是每一个题目都是一个知识点,特别是菜单系列刚开始的时候无从下手做完后再看看感慨万分,虽然类是老师设计的,但是其中的交流是自己打的,熬了几天大夜虽然很累但是拿满分的那一刻成就感满满。
学到了什么:
1.对类的设计有了一定的了解。
2.对集合有了一定的认知。
3.体会到优秀的框架设计的好处(优秀的架构与细节设计。优秀的含义很广泛,清晰、可读、易维护、易扩展的设计往往是鲁棒的,这样的设计往往很难出现严重的纰漏,因为很多错误已经被规避掉了,即使有错 误,发现、纠正的难度也不会太大)
4.对JAVA报错的修改更加得心应手。
5.对类的封装性有了概念
6.学习了正则表达式的基本使用
对课程的建议
1.每次作业截止之后可以出一下不计分的补题,可以让没有及时解决问题的同学继续尝试。
以上是关于PTA题目集4~6总结的主要内容,如果未能解决你的问题,请参考以下文章