pta题目集4-5及期中考试
1.前言:点菜程序,光是听到名字就让人颤栗,我也光荣的基本上没写出来,以下的代码是题目集结束之后写出来的
pta题目集4:
本体大部分内容与菜单计价程序-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折, 周末全价。
注意:不同的四舍五入顺序可能会造成误差,请按以下步骤累计一桌菜的菜价:
计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格。
最后将所有记录的菜价累加得到整桌菜的价格。
import java.sql.SQLOutput; import java.time.LocalDateTime; import java.util.*; public class Main { static int cnt1 = 0; static int cnt2 = -1; static int cnt3 = 0; public static void main(String args[]) { int[] mon_maxnum = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31}; Scanner s = new Scanner(System.in); Menu menu = new Menu(); Table[] tables = new Table[10]; for (int i=0;i<10;i++) { tables[i] = new Table(); } String input = s.nextLine(); while (!input.equals("end")) { String[] a = input.split(" ");//以空格为分隔符分离输入的字符串 if (input.matches("[\\u4e00-\\u9fa5]+ \\d+(\\.\\d+)?( T)?") ) { //输入的是菜谱信息 if (!a[1].matches("^[1-9]|[1-9]\\d*$")) {//菜价 System.out.println("wrong format"); } else if (Integer.parseInt(a[1]) > 300 || Integer.parseInt(a[1]) < 0) { System.out.println(a[0] + " price out of range " + a[1]); } else{ menu.dishes[cnt1] = menu.addDish(a[0], Integer.parseInt(a[1]));//类型不匹配,使用Integer包装 cnt1++; } } else if (a.length == 3 && input.matches("[\\u4e00-\\u9fa5]+ \\d+(\\.\\d+)?( T)?")) {//特价菜 if (!a[1].matches("^[1-9]|[1-9]\\d*$")) { System.out.println("wrong format"); } else if (Integer.parseInt(a[1]) > 300 || Integer.parseInt(a[1]) < 0) { System.out.println(a[0] + " price out of range " + a[1]); } else{ menu.dishes[cnt1] = menu.addDish(a[0], Integer.parseInt(a[1]));//类型不匹配,使用Integer包装 menu.dishes[cnt1].T = 1; cnt1++; } } else if (a.length == 4 && a[0].equals("table")) {//桌与时间 String[] da = a[2].split("/");//年月日 String[] ti = a[3].split("/");//具体时间 if (!a[1].matches("^[1-9]|[1-9]\\d*$")) { System.out.println("wrong format"); } else if (Integer.parseInt(a[1]) > 55) { System.out.println(a[1] + " table num out of range"); } else if (!a[2].matches("\\d{4,}/\\d{1,2}/\\d{1,2}") || !a[3].matches("\\d{1,2}/\\d{1,2}/\\d{1,2}")) { System.out.println("wrong format"); } else if (Integer.parseInt(da[0]) < 2022 || Integer.parseInt(da[0]) > 2023 ) { System.out.println("not a valid time period"); } else if (Integer.parseInt(da[1]) < 1 || Integer.parseInt(da[1]) > 12) { System.out.println(a[1] + " date error"); } else if (Integer.parseInt(da[2]) < 1 || Integer.parseInt(da[2]) > mon_maxnum[Integer.parseInt(da[1])]) { System.out.println(a[1] + " date error"); } else if (Integer.parseInt(ti[0]) > 23 || Integer.parseInt(ti[0]) < 0) { System.out.println(a[1] + " date error"); } else if (Integer.parseInt(ti[1]) > 59 || Integer.parseInt(ti[1]) < 0) { System.out.println(a[1] + " date error"); } else if (Integer.parseInt(ti[2]) > 59 || Integer.parseInt(ti[2]) < 0) { System.out.println(a[1] + " date error"); } else { cnt2++; tables[cnt2] = new Table(); tables[cnt2].time = new Time(); tables[cnt2].tableNum = Integer.parseInt(a[1]); tables[cnt2].time.date = a[2];//年月日 tables[cnt2].time.times = a[3];//具体时间 System.out.println("table " + a[1] + ": "); } } else if (input.matches("\\d+ [\\u4e00-\\u9fa5a-zA-Z]+ \\d+ \\d+")) {//点菜 if (cnt2 > -1) { if (!tables[cnt2].order.checkOrdernum(Integer.parseInt(a[0]))) { System.out.println("record serial number sequence error"); } else if (menu.searchDish(a[1]) == null) { System.out.println(a[1] + " does not exist"); } else { Dish dish = new Dish(); dish = menu.searchDish(a[1]); if (dish.T == 1) {//特价菜份额份数判断 if (!a[3].matches("^[1-9]|[1-9]\\d*$")) { System.out.println("wrong format"); } else if (Integer.parseInt(a[2]) > 9) { System.out.println("wrong format"); } else if (Integer.parseInt(a[2]) != 1 && Integer.parseInt(a[2]) != 3) { System.out.println(a[0] + " portion out of range " + a[2]); } else if (Integer.parseInt(a[3]) > 15) { System.out.println(a[0] + " num out of range " + a[3]); } else { Record record = new Record(); record.orderNum = Integer.parseInt(a[0]); record.portion = Integer.parseInt(a[2]); record.num = Integer.parseInt(a[3]); record.d = menu.searchDish(a[1]); tables[cnt2].order.records[cnt3] = record; cnt3++; System.out.println(record.orderNum + " " + record.d.name + " " + record.getPriceA()); } } else {//非特价菜份额份数判断 if (!a[3].matches("^[1-9]|[1-9]\\d*$")) { System.out.println("wrong format"); } else if (Integer.parseInt(a[2]) > 9) { System.out.println("wrong format"); } else if (Integer.parseInt(a[2]) > 3) { System.out.println(a[0] + " portion out of range " + a[2]); } else if (Integer.parseInt(a[3]) > 15) { System.out.println(a[0] + " num out of range " + a[3]); } else { Record record = new Record(); record.orderNum = Integer.parseInt(a[0]); record.portion = Integer.parseInt(a[2]); record.num = Integer.parseInt(a[3]); record.d = menu.searchDish(a[1]); tables[cnt2].order.records[cnt3] = record; cnt3++; System.out.println(record.orderNum + " " + record.d.name + " " + record.getPriceA()); } } } } }else if (a.length == 2 && a[1].equals("delete")) { for (int i = 0;i <= cnt2;i++) { tables[i].order.delARecordByOrderNum(Integer.parseInt(a[0])); } } else{ System.out.println("wrong format"); } input = s.nextLine(); } for (int i=0;i <= Main.cnt2;i++) { tables[i].getPrice(); } } } class Dish { String name; int unit_price; int T = 0; public int getPrice(int portion) { int p = 0; if (portion == 1) { p = unit_price; } else if (portion == 2) { p = (int)(Math.round(unit_price*1.5)); } else if (portion == 3) { p = unit_price * 2; } return p; } } class Menu { Dish[] dishes; public Menu() { this.dishes = new Dish[100]; } public Dish searchDish(String dishName) { for (int i = 0; i < Main.cnt1; i++) { if (dishName.equals(dishes[i].name)) { return dishes[i]; } } return null; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 public Dish addDish(String dishName,int unit_price) { Dish dish = new Dish(); dish.name = dishName; dish.unit_price = unit_price; return dish; }//添加一道菜品信息 } class Record { Dish d; int orderNum; int flag = 1;//判断是否删除 int portion; int num; public Record (){ d = new Dish(); } public int getPrice() { return d.getPrice(portion) * num * flag; } public int getPriceA() { return d.getPrice(portion) * num; } } class Order { Record[] records; public Order() { this.records = new Record[100]; for (int i = 0; i < 100; i++) { records[i] = new Record(); } } public int getTotalPrice() {//计算订单的总价 int totalprice = 0; for (int i=0;i < Main.cnt3;i++) { totalprice += records[i].getPrice(); } return totalprice; } public Record addARecord(int orderNum,String dishName,int portion,int num) {//添加一条菜品信息到订单中 Record record = new Record(); record.orderNum = orderNum; record.d.name = dishName; record.portion = portion; record.num = num; return record; } public void delARecordByOrderNum(int orderNum) { int i; i = findRecordByNum(orderNum); if (i == -1) { System.out.println("delete error"); } else { if (records[i].flag == 1) { records[i].flag = 0; } else{ System.out.println("deduplication " + orderNum); } } } public int findRecordByNum(int orderNum) { int i; for (i=0;i < Main.cnt3;i++) { if (records[i].orderNum == orderNum) { return i; } } return -1; } Boolean checkOrdernum(int j) { for (int i=0;i< Main.cnt3;i++) { if (j <= records[i].orderNum) { return false; } } return true; } } class Time { String date; String times; int weekday; int year; int month; int day; int hour; int minutes; public void getDate() { String[] da = date.split("/"); String[] ti = times.split("/"); this.year = Integer.parseInt(da[0]); this.month = Integer.parseInt(da[1]); this.day = Integer.parseInt(da[2]); this.hour = Integer.parseInt(ti[0]); this.minutes = Integer.parseInt(ti[1]); LocalDateTime d = LocalDateTime.of(year,month,day,hour,minutes); this.weekday = d.getDayOfWeek().getValue();//getValue得到值,否则DayOfWeek类型不能直接用 } } class Table { Time time; Order order; int tableNum; int tablePrice; public Table() { time = new Time(); order = new Order(); } public void getPrice() { int sum1 = 0;//特价菜 int sum2 = 0;//非特价菜 time.getDate(); if (time.weekday >= 1 && time.weekday <= 5) {//周一到周五 for (int i=0;i <= Main.cnt3;i++) { if (order.records[i].d.T == 1) {//是特价菜 sum1 += (int)(Math.round(order.records[i].getPrice()*0.7)); } else if (order.records[i].d.T == 0) {//不是特价菜 sum2 += order.records[i].getPrice(); } } if ((time.hour >= 10 && time.minutes >= 30 && time.hour < 14) || (time.hour <= 14 && time.minutes <= 30 && time.hour > 10)) {//中午 tablePrice = (int)(Math.round(sum2 * 0.6)) + sum1; System.out.println("table " + tableNum + ": " + order.getTotalPrice() + " " + tablePrice); } else if ((time.hour >= 17 && time.hour < 20) || time.hour == 20 && time.minutes <= 30) {//晚上 tablePrice = (int)(Math.round(sum2 * 0.8)) + sum1; System.out.println("table " + tableNum + ": " + order.getTotalPrice() + " " + tablePrice); } else{ //非营业时间 System.out.println("table " + tableNum + " out of opening hours"); } } else if (time.weekday == 6 || time.weekday == 7) {//周末 if ((time.hour >= 9 && time.minutes >= 30 && time.hour < 21) || (time.hour <= 21 && time.minutes <=30 && time.hour > 9)) { tablePrice = order.getTotalPrice(); System.out.println("table " + tableNum + ": " + order.getTotalPrice() + " " + tablePrice); } else{ //非营业时间 System.out.println("table " + tableNum + " out of opening hours"); } } } }
pta题目集5:
本题在菜单计价程序-3的基础上增加了部分内容,增加的内容用加粗字体标识。
注意不是菜单计价程序-4,本题和菜单计价程序-4同属菜单计价程序-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)//根据序号查找一条记录
}
### 输入格式:
桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价
以上为菜单计价系列-3的题目要求,加粗的部分是有调整的内容。本次课题相比菜单计价系列-3新增要求如下:
1、菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+口味类型+英文空格+基础价格+"T"
例如:麻婆豆腐 川菜 9 T
菜价的计算方法:
周一至周五 7折, 周末全价。
特色菜的口味类型:川菜、晋菜、浙菜
川菜增加辣度值:辣度0-5级;对应辣度水平为:不辣、微辣、稍辣、辣、很辣、爆辣;
晋菜增加酸度值,酸度0-4级;对应酸度水平为:不酸、微酸、稍酸、酸、很酸;
浙菜增加甜度值,甜度0-3级;对应酸度水平为:不甜、微甜、稍甜、甜;
例如:麻婆豆腐 川菜 9 T
输入订单记录时如果是特色菜,添加口味度(辣/酸/甜度)值,格式为:序号+英文空格+菜名+英文空格+口味度值+英文空格+份额+英文空格+份数
例如:1 麻婆豆腐 4 1 9
单条信息在处理时,如果口味度超过正常范围,输出"spicy/acidity/sweetness num out of range : "+口味度值,spicy/acidity/sweetness(辣度/酸度/甜度)根据菜品类型择一输出,例如:
acidity num out of range : 5
输出一桌的信息时,按辣、酸、甜度的顺序依次输出本桌菜各种口味的口味度水平,如果没有某个类型的菜,对应的口味(辣/酸/甜)度不输出,只输出已点的菜的口味度。口味度水平由口味度平均值确定,口味度平均值只综合对应口味菜系的菜计算,不做所有菜的平均。比如,某桌菜点了3份川菜,辣度分别是1、3、5;还有4份晋菜,酸度分别是,1、1、2、2,辣度平均值为3、酸度平均值四舍五入为2,甜度没有,不输出。
一桌信息的输出格式:table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格+"川菜"+数量+辣度+英文空格+"晋菜"+数量+酸度+英文空格+"浙菜"+数量+甜度。
如果整桌菜没有特色菜,则只输出table的基本信息,格式如下,注意最后加一个英文空格:
table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格
例如:table 1: 60 36 川菜 2 爆辣 浙菜 1 微甜
计算口味度时要累计本桌各类菜系所有记录的口味度总和(每条记录的口味度乘以菜的份数),再除以对应菜系菜的总份数,最后四舍五入。
注:本题要考虑代点菜的情况,当前桌点的菜要加上被其他桌代点的菜综合计算口味度平均值。
2、考虑客户订多桌菜的情况,输入时桌号时,增加用户的信息:
格式:table+英文空格+桌号+英文空格+":"+英文空格+客户姓名+英文空格+手机号+日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
例如:table 1 : tom 13670008181 2023/5/1 21/30/00
约束条件:客户姓名不超过10个字符,手机号11位,前三位必须是180、181、189、133、135、136其中之一。
输出结果时,先按要求输出每一桌的信息,最后按字母顺序依次输出每位客户需要支付的金额。不考虑各桌时间段的问题,同一个客户的所有table金额都要累加。
输出用户支付金额格式:
用户姓名+英文空格+手机号+英文空格+支付金额
注意:不同的四舍五入顺序可能会造成误差,请按以下步骤累计一桌菜的菜价:
计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格。
将所有记录的菜价累加得到整桌菜的价格。
import java.util.*; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Menu menu = new Menu(); Calendar cal = Calendar.getInstance(); Map<Integer, Table> tables = new HashMap<>(); int tcd = 0; Table table = null; while (true) { try { String ipt = sc.nextLine(); if (ipt.equals("end")) break; String[] s = ipt.split(" "); if (s[0].equals("table") && s.length > 4) { if (s[3].length() > 10) { System.out.println("wrong format"); continue; } else if (11 != s[4].length()) { if (s[4].length() == 11) { } else { System.out.println("wrong format"); } } else { if (!s[4].matches("(^133|^135|^136|^180|^181|^189)\\d{8}$")) { System.out.println("wrong format"); continue; } } Table tb = new Table(s[5].split("/"), s[6].split("/")); if (checkTime(tb) == 1) { table = tb; table.name = s[3]; table.phone = s[4]; tcd = Integer.parseInt(s[1]); tables.put(tcd, table); System.out.println("table " + tcd + ": "); } else if (checkTime(tb) == 0) { tb.name = s[3]; tb.phone = s[4]; tcd = Integer.parseInt(s[1]); tables.put(tcd, tb); } else { System.out.println("wrong format"); } } else if (Pattern.matches("^\\d+\\s\\d+\\s\\S+\\s\\d+\\s\\d+\\s\\d+", ipt) && table != null) { // 1 1 醋浇羊肉 0 1 2 try { Dish dish = menu.find(s[2]); if (dish == null) { System.out.println(s[2] + " does not exist"); } else { if (dish.checkDegree(Integer.parseInt(s[3]))) { int tableNo = Integer.parseInt(s[0]); int ordern = Integer.parseInt(s[1]); int gg = Integer.parseInt(s[4]); int fs = Integer.parseInt(s[5]); Record rec = new Record(dish, fs, gg, Integer.parseInt(s[3])); table.otherMap.put(ordern, rec); tables.get(tableNo).DaiMap.put(ordern, rec); table.otherTableInfo.put(ordern, tableNo - 1); System.out.println(ordern + " table " + tcd + " pay for table " + tableNo + " " + rec.price); } } } catch (Exception e) { System.out.println("wrong format"); } } else if (ipt.contains("T")) { Dish dish; if (ipt.contains("川")) { dish = new ChuanCai(s[0], Integer.parseInt(s[2])); dish.type = 3; } else if (ipt.contains("晋")) { dish = new JinCai(s[0], Integer.parseInt(s[2])); dish.type = 2; } else if (ipt.contains("浙")) { dish = new ZheCai(s[0], Integer.parseInt(s[2])); dish.type = 1; } else { System.out.println("wrong format"); continue; } menu.add(dish); } else if (Pattern.matches("^\\d+\\s\\S+\\s\\d+\\s\\d+\\s\\d+", ipt) && table != null) { //1 麻婆豆腐 4 1 9 try { Dish dish = menu.find(s[1]); if (dish == null) { System.out.println(s[1] + " does not exist"); } else { if (dish.checkDegree(Integer.parseInt(s[2]))) { int no = Integer.parseInt(s[0]); Record record = new Record(dish, Integer.parseInt(s[4]), Integer.parseInt(s[3]), Integer.parseInt(s[2])); table.records.put(no, record); table.ownFees += record.price; System.out.println(no + " " + dish.name + " " + record.price); } } } catch (Exception e) { System.out.println("wrong format"); } } else if (s.length == 2) { if (s[1].equals("delete") && table != null) { //7 delete int i = Integer.parseInt(s[0]); if (!table.del(i)) { if (table.otherMap.remove(i) != null) { Integer t = table.otherTableInfo.get(i); tables.get(t).DaiMap.remove(i); } } // System.out.println("delete error;"); } else if (tcd == 0) { //麻婆豆腐 12 menu.add(s[0], Integer.parseInt(s[1])); } } else if (s.length == 4) if (s[0].equals("table")) { //table 1 : tom 13670008181 2023/5/1 21/30/00 } else { if (table != null) { try { //1 麻婆豆腐 2 2 Dish dish = menu.find(s[1]); if (dish == null) { System.out.println(s[1] + " does not exist"); } else if (dish.type != 0) { System.out.println("wrong format"); } else { int no = Integer.parseInt(s[0]); Record record = new Record(dish, Integer.parseInt(s[3]), Integer.parseInt(s[2])); table.records.put(no, record); table.ownFees += record.price; System.out.println(no + " " + dish.name + " " + record.price); } } catch (Exception e) { System.out.println("wrong format"); } } } else if (s.length == 5 && table != null) { //1 4 麻婆豆腐 1 1 Dish dish = menu.find(s[2]); if (dish == null) { System.out.println(s[2] + " does not exist"); } else { try { int tableNo = Integer.parseInt(s[0]); int ordern = Integer.parseInt(s[1]); int heft = Integer.parseInt(s[3]); int fs = Integer.parseInt(s[4]); Record rec = new Record(dish, fs, heft); table.otherMap.put(ordern, rec); tables.get(tableNo).DaiMap.put(ordern, rec); table.otherTableInfo.put(ordern, tableNo - 1); System.out.println(ordern + " table " + tcd + " pay for table " + tableNo + " " + rec.price); } catch (Exception e) { System.out.println("wrong format"); } } } } catch (Exception e) { System.out.println("wrong format"); } } Map<String, Integer> all = new TreeMap<>(); for (Map.Entry<Integer, Table> entryT : tables.entrySet()) { int ii = entryT.getKey(); Table t = entryT.getValue(); int year = Integer.parseInt(t.day[0]); int month = Integer.parseInt(t.day[1]) - 1; int day = Integer.parseInt(t.day[2]); int hour = Integer.parseInt(t.time[0]); cal.set(year, month, day); int week = cal.get(Calendar.DAY_OF_WEEK); float discount; if (week == 1 || week == 7) { if ((hour >= 10 && hour <= 20) || (hour == 9 && Integer.parseInt(t.time[1]) >= 30) || (hour == 21 && Integer.parseInt(t.time[1]) == 30 && Integer.parseInt(t.time[2]) == 0)) { discount = 1.0F; } else { System.out.println("table " + (ii) + " out of opening hours"); continue; } } else { if ((hour >= 17 && hour <= 19) || (hour == 20 && Integer.parseInt(t.time[1]) <= 30 && Integer.parseInt(t.time[2]) == 0)) { discount = 0.8F; } else if ((hour >= 11 && hour <= 13) || (hour == 10 && Integer.parseInt(t.time[1]) >= 30) || (hour == 14 && Integer.parseInt(t.time[1]) <= 30 && Integer.parseInt(t.time[2]) == 0) ) { discount = 0.6F; } else { System.out.println("table " + (ii) + " out of opening hours"); continue; } } if (all.get(t.name + " " + t.phone) == null) { all.put(t.name + " " + t.phone, t.allhou(discount)); } else { Integer r = all.get(t.name + " " + t.phone); r += t.allhou(discount); all.put(t.name + " " + t.phone, r); } System.out.println("table " + (ii) + ": " + t.allqian() + " " + t.allhou(discount) + t.getT()); } for (Map.Entry<String, Integer> entry : all.entrySet()) { System.out.println(entry.getKey() + " " + entry.getValue()); } } public static int checkTime(Table t) { try { Calendar cal = Calendar.getInstance(); int year = Integer.parseInt(t.day[0]); int month = Integer.parseInt(t.day[1]) - 1; int day = Integer.parseInt(t.day[2]); int hour = Integer.parseInt(t.time[0]); cal.set(year, month, day); int week = cal.get(Calendar.DAY_OF_WEEK); if (week == 1 || week == 7) { if ((hour >= 10 && hour <= 20) || (hour == 9 && Integer.parseInt(t.time[1]) >= 30) || (hour == 21 && Integer.parseInt(t.time[1]) == 30 && Integer.parseInt(t.time[2]) == 0)) { return 1; } else { return 0; } } else { if ((hour >= 17 && hour <= 19) || (hour == 20 && Integer.parseInt(t.time[1]) <= 30 && Integer.parseInt(t.time[2]) == 0)) { return 1; } else if ((hour >= 11 && hour <= 13) || (hour == 10 && Integer.parseInt(t.time[1]) >= 30) || (hour == 14 && Integer.parseInt(t.time[1]) <= 30 && Integer.parseInt(t.time[2]) == 0) ) { return 1; } else { return 0; } } }catch (Exception e){ System.out.println("wrong format"); return -1; } } } class Dish { String name; int price; int type; public Dish(String name, int price) { this.name = name; this.price = price; } boolean checkDegree(int degree) { return true; } } class ChuanCai extends Dish { public ChuanCai(String name, int price) { super(name, price); } @Override boolean checkDegree(int degree) { if (degree < 0 || degree > 5) { System.out.println("spicy num out of range :" + degree); return false; } return true; } } class JinCai extends Dish { public JinCai(String name, int price) { super(name, price); } @Override boolean checkDegree(int degree) { if (degree < 0 || degree > 4) { System.out.println("acidity num out of range :" + degree); return false; } return true; } } class ZheCai extends Dish { public ZheCai(String name, int price) { super(name, price); } @Override boolean checkDegree(int degree) { if (degree < 0 || degree > 3) { System.out.println("sweetness num out of range :" + degree); return false; } return true; } } class Menu { int count = 0; Map<String, Dish> dishes = new HashMap(); public void add(String name, int price) { dishes.put(name, new Dish(name, price)); // dishes[count] = new Dish(name, price); count++; } public void add(Dish dish) { dishes.put(dish.name, dish); count++; } public Dish find(String name) { return dishes.get(name); } } class Record { Dish dish; int unit_price; int heft; int price; int degree; public Record(Dish dish, int fs, int heft) { this.degree = -1; this.dish = dish; this.heft = heft; this.unit_price = fs; if (heft == 1) { price = dish.price * fs; } else if (heft == 2) { price = Math.round((float) dish.price * 1.5f) * fs; } else if (heft == 3) { price = dish.price * 2 * fs; } } public Record(Dish dish, int fs, int heft, int degree) { this.dish = dish; this.degree = degree; this.heft = heft; this.unit_price = fs; if (heft == 1) { price = dish.price * fs; } else if (heft == 2) { price = Math.round((float) dish.price * 1.5f) * fs; } else if (heft == 3) { price = dish.price * 2 * fs; } } } class Table { Map<Integer, Record> records = new HashMap<>(); String[] day; String[] time; String name; String phone; int ownFees = 0; Map<Integer, Record> otherMap = new HashMap<>(); Map<Integer, Integer> otherTableInfo = new HashMap<>(); Map<Integer, Record> DaiMap = new HashMap<>(); public Table(String[] day, String[] time) { this.day = day; this.time = time; } public boolean del(int no) { if (records.get(no) == null) { return false; } else { ownFees -= records.get(no).price; records.remove(no); return true; } } public int allqian() { int sum = 0; for (Record record : records.values()) { if (record == null) continue; sum += record.price; } for (Record value : otherMap.values()) { sum += value.price; } return sum; } public int allhou(float discount) { if (discount == 0.6F) { int sum = 0; for (Record record : records.values()) { if (record == null) continue; if (record.dish.type == 0) { sum += Math.round((float) record.price * discount); } else { sum += Math.round((float) record.price * 0.7); } } for (Record value : otherMap.values()) { if (value.dish.type == 0) { sum += Math.round((float) value.price * discount); } else { sum += Math.round((float) value.price * 0.7); } } return sum; } else if (discount == 0.8F) { int sum = 0; for (Record record : records.values()) { if (record == null) continue; if (record.dish.type == 0) { sum += Math.round((float) record.price * discount); } else { sum += Math.round((float) record.price * 0.7); } } for (Record value : otherMap.values()) { if (value.dish.type == 0) { sum += Math.round((float) value.price * discount); } else { sum += Math.round((float) value.price * 0.7); } } return sum; } else { return allqian(); } } public String getT() { List<Record> chuanCai = new ArrayList<>(); List<Record> jinCai = new ArrayList<>(); List<Record> zheCai = new ArrayList<>(); String r = " "; for (Record record : records.values()) { if (record == null) { continue; } switch (record.dish.type) { case 1 : zheCai.add(record); case 2 : jinCai.add(record); case 3 : chuanCai.add(record); } } for (Map.Entry<Integer, Record> entry : DaiMap.entrySet()) { switch (entry.getValue().dish.type) { case 1 : zheCai.add(entry.getValue()); case 2 : jinCai.add(entry.getValue()); case 3 : chuanCai.add(entry.getValue()); } } if (chuanCai.size() != 0) { int degree = 0; int unit_price = 0; for (Record record : chuanCai) { degree += record.degree * record.unit_price; unit_price += record.unit_price; } int pingjun = Math.round((float) degree / (float) unit_price); String[] ll = {"不辣", "微辣", "稍辣", "辣", "很辣", "爆辣"}; r = r + " 川菜 " + unit_price + " " + ll[pingjun]; } if (jinCai.size() != 0) { int degree = 0; int unit_price = 0; for (Record record : jinCai) { degree += record.degree * record.unit_price; unit_price += record.unit_price; } int pingjun = Math.round((float) degree / (float) unit_price); String[] ll = {"不酸", "微酸", "稍酸", "酸", "很酸"}; r = r + " 晋菜 " + unit_price + " " + ll[pingjun]; } if (zheCai.size() != 0) { int degree = 0; int unit_price = 0; for (Record record : zheCai) { degree += record.degree * record.unit_price; unit_price += record.unit_price; } int pingjun = Math.round((float) degree / (float) unit_price); String[] ll = {"不甜", "微甜", "稍甜", "甜"}; r = r + " 浙菜 " + unit_price + " " + ll[pingjun]; } return r.replaceAll(" {2}", " "); } }
期中考试:
将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类,类图如下所示:
试编程完成如上类图设计,主方法源码如下(可直接拷贝使用):
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int choice = input.nextInt();
switch(choice) {
case 1://Circle
double radiums = input.nextDouble();
Shape circle = new Circle(radiums);
printArea(circle);
break;
case 2://Rectangle
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
Point leftTopPoint = new Point(x1,y1);
Point lowerRightPoint = new Point(x2,y2);
Rectangle rectangle = new Rectangle(leftTopPoint,lowerRightPoint);
printArea(rectangle);
break;
}
}
其中,printArea(Shape shape)
方法为定义在Main类中的静态方法,体现程序设计的多态性。
代码如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int choice = input.nextInt(); switch (choice) { case 1: // Circle double radiums = input.nextDouble(); if (radiums <= 0) { System.out.println("Wrong Format"); return; } Shape circle = new Circle(radiums); printArea(circle); break; case 2: // Rectangle double x1 = input.nextDouble(); double y1 = input.nextDouble(); double x2 = input.nextDouble(); double y2 = input.nextDouble(); Point leftTopPoint = new Point(x1, y1); Point lowerRightPoint = new Point(x2, y2); Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint); printArea(rectangle); break; } } public static void printArea(Shape shape) { System.out.printf("%.2f", shape.getArea()); } } abstract class Shape { public abstract double getArea(); } class Circle extends Shape { private double radiums; public Circle(double radiums) { this.radiums = radiums; } @Override public double getArea() { return Math.PI * radiums * radiums; } } class Rectangle extends Shape { private Point leftTopPoint; private Point lowerRightPoint; public Rectangle(Point leftTopPoint, Point lowerRightPoint) { this.leftTopPoint = leftTopPoint; this.lowerRightPoint = lowerRightPoint; } @Override public double getArea() { double width = Math.abs(lowerRightPoint.getX() - leftTopPoint.getX()); double height = Math.abs(lowerRightPoint.getY() - leftTopPoint.getY()); return width * height; } } class Point { private double x; private double y; public Point(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } }
总结:
这几次pta的作业给了我很大的触动,首先就是可持续性改进,在点菜程序3中写下的代码,在接下来的点菜程序5点菜程序4中都只要做小小的改进甚至不需要改进就能拿来用,之后只需要随着题目的改动来写出新的类和改动主类就行,这几个题目不仅增强了我对类的属性,方法的思考,而且深化了我对面对对象程序设计的理解,同时,对于idea的使用,比如调试,插件的安装与查找等技能,也得到了很好的锻炼!我的独立思考能力也逐渐增强,对写代码的热情也越来越高!我认为还需改进的地方就是代码的健壮性不足,仍需要多多钻研。我认为实验题目也同样可以让学生写一篇博客来回顾自己的学习经历,对于pta题目的话我认为可以在每次作业之后开一个补题集给学生不断的进行改进。以上是我的全部内容。