1. 程式人生 > >java面試設計題:羽毛球館管理員;

java面試設計題:羽毛球館管理員;

連結:https://www.nowcoder.com/questionTerminal/4c3d325a70fd4fb4909e2fe1c42fba71?toCommentId=1352361
來源:牛客網

小明是一個羽毛球場館的管理員,管理著四個羽毛球場地(A,B,C,D場地),負責場地的維護和預訂工作。為了簡化自己的工作,場地只接受整點預訂,預訂以小時為單位。

羽毛球場的收費標準如下:

  • 週一到週五:
    • 9:00 ~ 12:00 30元/時
    • 12:00 ~ 18:00 50元/時
    • 18:00 ~ 20:00 80元/時
    • 20:00 ~ 22:00 60元/時
  • 週六及週日
    • 9:00 ~ 12:00 40元/時
    • 12:00 ~ 18:00 50元/時
    • 18:00 ~ 22:00 60元/時

羽毛球場館在預訂之後,可以接受取消預訂,不過取消預訂需要交違約金,違約金的計算規則如下:

  • 週一到週五的預訂取消收取全部費用的50%作為違約金
  • 週六週日的預訂取消收取全部費用的25%作為違約金
由於手頭還有其他工作,小明希望能夠藉助計算機程式來自動化處理預訂及取消預訂的事務,並且希望程式能夠打印出場館的收入彙總情況。

程式輸入

預訂:使用者預訂以字串的形式輸入,一行字串代表一個預定

  • 格式為{使用者ID} {預訂日期 yyyy-MM-dd} {預訂時間段 HH:mm~HH:mm} {場地},如U123 2016-06-02 20:00~22:00 A,代表使用者U123預定2016年06月02日晚上20:00到22:00的場地A的時間段
  • 時間段的起止時間必然為整小時,否則報錯
  • 如預訂與已有預訂衝突,也會報錯

取消預定:使用者取消預定,輸入也以一行字串的形式表現

  • 格式為{使用者ID} {預訂日期 yyyy-MM-dd} {預訂時間段 HH:mm~HH:mm} {場地} {取消標記},如U123 2016-06-02 20:00~22:00 A C,代表使用者U123取消其在2016年06月02日晚上20:00到22:00在場地A的預訂,其中取消標記C代表Cancel
  • 取消標記只能是C,若為其他字元則報錯
  • 時間段的起止時間必然為整小時,否則報錯
  • 只能完整取消之前的預訂,不能取消部分時間段
  • 取消預訂的請求,必須與之前的預訂請求嚴格匹配,需要匹配的項有使用者ID,預訂日期,預訂時間段,場地

列印場館收入彙總: 將所有的預訂和取消預訂帶來的收入彙總資訊打印出來

  • 格式為,輸入一個空行,代表列印收入彙總

程式輸出

收入彙總:以文字的形式輸出當前系統所有預訂以及取消預訂所帶來的收入情況,以不同的場地分組,一個可能的輸出如下所示:

12345678910111213141516171819收入彙總---場地:A2016-06-02 09:00~10:00 違約金 152016-06-02 10:00~12:00 602016-06-03 20:00~22:00 120小計:195場地:B2016-06-04 09:00~10:00 40小計:40場地:C小計:0場地:D小計:0---總計: 235

注意:

  • 如果同一場地同一時間段有多條預定記錄,則顯示多條
  • 收入記錄以時間順序升序排列

測試用例1

注意:>開頭表示命令列輸出,以下測試用例都遵循此例

1234567891011121314151617181920212223242526272829303132abcdefghijklmnopqrst1234567890> Error: the booking is invalid!U001 2016-06-02 22:00~22:00 A> Error: the booking is invalid!U002 2017-08-01 19:00~22:00 A> Success: the booking is accepted!U003 2017-08-02 13:00~17:00 B> Success: the booking is accepted!U004 2017-08-03 15:00~16:00 C> Success: the booking is accepted!U005 2017-08-05 09:00~11:00 D> Success: the booking is accepted!> 收入彙總> ---> 場地:A> 2017-08-01 19:00~22:00 200> 小計:200>> 場地:B> 2017-08-02 13:00~17:00 200> 小計:200>> 場地:C> 2017-08-03 15:00~16:00 50> 小計:50>> 場地:D> 2017-08-05 09:00~11:00 80> 小計:80> ---> 總計:530

測試用例2

12345678910111213141516171819202122232425262728293031U002 2017-08-01 19:00~22:00 A> Success: the booking is accepted!U003 2017-08-01 18:00~20:00 A> Error: the booking conflicts with existing bookings!U002 2017-08-01 19:00~22:00 A C> Success: the booking is accepted!U002 2017-08-01 19:00~22:00 A C> Error: the booking being cancelled does not exist!U003 2017-08-01 18:00~20:00 A> Success: the booking is accepted!U003 2017-08-02 13:00~17:00 B> Success: the booking is accepted!> 收入彙總> ---> 場地:A> 2017-08-01 18:00~20:00 160> 2017-08-01 19:00~22:00 違約金 100> 小計:260>> 場地:B> 2017-08-02 13:00~17:00 200> 小計:200>> 場地:C> 小計:0>> 場地:D> 小計:0> ---> 總計:460
總結:1.這個程式重點在於時間日期的處理,還有字串的正則匹配;

2.判斷時間的衝突情況,和價格計算都要涉及到(組合的嚴謹準確)的準確,如何排除廢的資料?在草稿紙下把業務判斷清楚就行;

3.理解到Scanner的Delimeter,Scanner預設是以空格為Delimeter,設定其為\n換行:sc.useDelimiter("\n");

4.正則表示式Pattern,基本操作:

Pattern p = Pattern.compile(bookPattern);
			Matcher m = p.matcher(line);
			m.find();
			//save to str
			for(int j=0;j<m.groupCount()+1;j++) {
				str[j] = m.group(j);
			}
5.對業務邏輯和java業務基礎和演算法細節有要求,比如在儲存資料的時候選擇的Ararylist,陣列,如何add,rem的操作;
程式碼如下:

訂單實體:

package entity;

public class Customer {
	String userID;
	int year;
	int month;
	int day;
	int startClock;
	int endClock;
	String place;
	
//	public Customer() {
//		// TODO Auto-generated constructor stub
//		
//	}

	public Customer(String userID, int year,int month, int day, int startClock, int endClock, String place) {
		super();
		this.year = year;
		this.userID = userID;
		this.month = month;
		this.day = day;
		this.startClock = startClock;
		this.endClock = endClock;
		this.place = place;
	}
	public boolean isIdEqual(Customer c){
		if(this.userID.equals(c.userID))
			return true;
		return false;
	}
	public boolean isDateEqual(Customer c) {
		if(this.year==c.year&&this.day==c.day&&this.month==c.month)
			return true;
		return false;
	}
	public boolean isplaceEqual(Customer c) {
		if(this.place.equals(c.place))
			return true;
		return false;
	}
	public boolean isEqual(Customer c) {
		if(this.userID.equals(c.userID) &&this.year==c.year&&this.month==c.month
				&&this.day ==c.day&&this.startClock==c.startClock&&this.endClock==c.endClock
				)
				return true;
		return false;
	}
	public boolean isTimeConflict(Customer c) {
		if(isDateEqual(c) &&(
			

					(this.startClock < c.startClock && this.endClock < c.endClock && this.endClock > c.startClock)
					||(this.startClock > c.startClock && this.startClock < c.endClock && this.endClock > c.startClock && this.endClock < c.endClock)
					||(this.startClock > c.startClock && this.startClock < c.endClock && this.endClock > c.endClock)
					||(c.startClock < this.startClock && c.endClock < this.endClock && c.endClock > this.startClock)
					||(c.startClock > this.startClock && c.startClock < this.endClock && c.endClock > this.startClock && c.endClock < this.endClock)
					||(c.startClock > this.startClock && c.startClock < this.endClock && c.endClock > this.endClock)
					
				)
					&& isplaceEqual(c)
				)
				return true;
		return false;
				
				
	}
	
}

主程式:

package entity;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class mainmeans {
static String str[] = new String[21];
	/**
	 * str[1] =user id 
	 * start year
	 * start month
	 * start day
	 * start clock
	 * end clock
	 * accept
	 * cancel
	 */
	
	static int minStartClock = 9;
	static int maxStartClock = 22;
	static List<Customer> booklist = new LinkedList<>();
	static List<Customer> cancellist = new ArrayList<>();
	
	
	public mainmeans() {
		// TODO Auto-generated constructor stub
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		sc.useDelimiter("\n");
		String line = "";
		while(line.length() != 1&& line !=" ") {
			line = sc.nextLine();
			if(line.length()!=1&&line!=" ")
				mainProcess(line);
		}
		
		printResult();
		
//		連結:https://www.nowcoder.com/questionTerminal/4c3d325a70fd4fb4909e2fe1c42fba71?toCommentId=1352361
//			來源:牛客網
//
//			// String [] line = new String[6];
//			 
//			// line[0] = "U002 2017-08-01 19:00~22:00 A";
//			 
//			// line[1] = "U003 2017-08-01 18:00~20:00 A";
//			 
//			// line[2] = "U002 2017-08-01 19:00~22:00 A C";
//			 
//			// line[3] = "U002 2017-08-01 19:00~22:00 A C";
//			 
//			// line[4] = "U003 2017-08-01 18:00~20:00 A";
//			 "(U) (\\d{3}) (\\s) (\\d{4) (-) (\\d{2}) (-) (\\d{2}) (\\s) (\\d{2})(:)(00)(~)(\\d{2}(:)(00) (\\s) ([A-D])) "
//			// line[5] = "U003 2017-08-02 13:00~17:00 B";
//			 
//			// for (String l:line) {
//			 
//			// mainProcess(l);;
//			 
//			// }
//			 
//			// printResult();
	}

	

	private static void mainProcess(String line) {
		// TODO Auto-generated method stub
		String userID;
		int year;
		int month;
		int day;
		int startClock;
		int endClock;
		String place;
		
		String bookPattern = "(U)(\\d{3})(\\s)(\\d{4})(-)(\\d{2})(-)(\\d{2})(\\s)(\\d{2})(:)(00)(~)(\\d{2})(:)(00)(\\s)([A-D])";
		String cancelPattern = "(U)(\\d{3})(\\s)(\\d{4})(-)(\\d{2})(-)(\\d{2})(\\s)(\\d{2})(:)(00)(~)(\\d{2})(:)(00)(\\s)([A-D])(\\s)([C])";
		boolean isBook = Pattern.matches(bookPattern, line);
		boolean isCancel = Pattern.matches(cancelPattern, line);
		 
		if(isBook) {
			Pattern p = Pattern.compile(bookPattern);
			Matcher m = p.matcher(line);
			m.find();
			//save to str
			for(int j=0;j<m.groupCount()+1;j++) {
				str[j] = m.group(j);
				
			}
			userID = str[2];
			year = Integer.valueOf(str[4]);
			month = Integer.valueOf(str[6]);
			day = Integer.valueOf(str[8]);
			startClock = Integer.valueOf(str[10]);
			endClock = Integer.valueOf(str[14]);
			place = str[18];
			
			if(Integer.valueOf(startClock)==Integer.valueOf(endClock)
				||Integer.valueOf(startClock )< minStartClock
				||Integer.valueOf(endClock) >maxStartClock
				
					)
				printInvalidError();
			else {
				Customer cus = new Customer(userID, year, month, day, startClock, endClock, place);
				book(cus);
			}
		}else if(isCancel) {
			Pattern p = Pattern.compile(cancelPattern);
			Matcher m = p.matcher(line);
			m.find();
			
			for(int j=0;j<m.groupCount()+1;j++) {
				str[j] = m.group(j);
			}
			userID = str[2];
			year = Integer.valueOf(str[4]);
			month = Integer.valueOf(str[6]);
			day = Integer.valueOf(str[8]);
			startClock = Integer.valueOf(str[10]);
			endClock = Integer.valueOf(str[14]);
			place = str[18];
			
			Customer cus = new Customer(userID, year, month, day, startClock, endClock, place);
			cancelBook(cus);		
		}else 
			printInvalidError();
		
	}

	private static void cancelBook(Customer cus) {
		// TODO Auto-generated method stub
		boolean rem = false;
		for(Customer c :booklist) {
			if(cus.equals(c)) {
				booklist.remove(c);
				printBookSuccess();
				rem = true;
			}
		}
		if(!rem)
			printCancelError();
	}
	public static void printResult() {
		String [] placeIncome = new String[4];
		int [] placePrice = new int[4];
		int bookIncome;
		int CancelIncome;
		for(int j='A',k=0;j<='D';j++,k++) {
			placeIncome[k] = "場地"+String.valueOf((char)(j)) +":\n";
		}
		System.out.println("\n"+"收入彙總\n"+"---");
		for(Customer c :booklist) {
			bookIncome = calPrice(c);
			for(int j='A',k=0;j<='D';j++,k++) {
				if(String.valueOf((char)(j)).equals(c.place) ) {
					placePrice[k]+=bookIncome;
					placeIncome[k]+=(c.year+"-"+(c.month<10?("0"+c.month):c.month)
													+(c.startClock<10?("0"+c.startClock):c.startClock+":"+"00~")
													+(c.endClock<10?("0"+c.endClock):c.endClock+":00"+" "+bookIncome+"元"+"\n")
													);
				}
			} 
		}
		
		for(Customer c:cancellist) {
			CancelIncome = calCancel(c);
			for(int j='A',k=0;j<='D';j++,k++) {
				if(String.valueOf((char)(j)).equals(c.place)) {
					placeIncome[k]+=(c.year+"-"+(c.month<10?("0"+c.month):c.month)
											+(c.startClock<10?("0"+c.startClock ):c.startClock)+":00~"
											+(c.endClock<10?("0"+c.endClock):c.endClock)+":00"
											+" 違約金 "+CancelIncome+"元\n")
											;
				}
			}
			
		}
		int i=0;
		int sumPrice=0;
		for(String p:placeIncome) {
			sumPrice+=placePrice[i];
			System.out.print(p);
			System.out.println("小計:"+placePrice[i++]+"元");
			System.out.println();
		}
		System.out.println("---\n"+"總計:"+sumPrice+"元");
	}
	private static int calCancel(Customer c) {
		// TODO Auto-generated method stub
		return (int)(calPrice(c));
	}

	private static int calPrice(Customer c) {
		// TODO Auto-generated method stub
		int [] workdayPrice = {30,50,80,60};
		int [] weekdayPrice = {40,50,60};
		int week = getWeek(c);
		int price=0;
		
		if(week<=5) {
			if(c.startClock>=9&&c.startClock<=12) {
				if(c.endClock>=9&&c.endClock<=12) {
					price=(c.endClock-c.startClock)*workdayPrice[0];
					
				}else if(c.endClock>12&&c.endClock<=18) {
					price = (12 - c.startClock) * workdayPrice[0] + (c.endClock - 12) * workdayPrice[1];
				}else if(c.endClock>18&&c.endClock<=20) {
						price = (12 - c.startClock) * workdayPrice[0] + (18 - 12) * workdayPrice[1]+ (c.endClock - 18) * workdayPrice[2];
						
				}else if(c.endClock>20&&c.endClock<=22) {
					price = (12 - c.startClock) * workdayPrice[0] + (18 - 12) * workdayPrice[1]+ (20 - 18) * workdayPrice[2] + (c.endClock - 20) * workdayPrice[3];
				}
			}else if(c.startClock>12&&c.startClock<=18) {
					if (c.endClock >=12 && c.endClock <= 18)
					price = (c.endClock - c.startClock) * workdayPrice[1];
					else if (c.endClock >18 && c.endClock <= 20)
					price = (18 - c.startClock) * workdayPrice[1]
					+ (c.endClock - 18) * workdayPrice[2];
					else if (c.endClock > 20 && c.endClock <= 22)
					price = (18 - c.startClock) * workdayPrice[1] + (20 - 18) * workdayPrice[2]
					+ (c.endClock - 20) * workdayPrice[3];
			}

				else if (c.startClock > 18 && c.startClock <= 20) {

				if (c.endClock >=18 && c.endClock <= 20)
				price = (c.endClock - c.startClock) * workdayPrice[2];
				else if (c.endClock > 20 && c.endClock <= 22) {
				price = (20 - c.startClock) * workdayPrice[2] + (c.endClock - 20) * workdayPrice[3];
				}
				}
					else if (c.startClock > 20 && c.startClock <= 22) {
					price = (c.endClock - c.startClock) * workdayPrice[3];
					}
		}else {
				if (c.startClock >= 9 && c.endClock <=12) {
				if(c.endClock > 9 && c.endClock <= 12) {
				price = (c.endClock - c.startClock) * weekdayPrice[0];
				} else if (c.endClock > 12 && c.endClock <=18) {
				price = (12 - c.startClock) * weekdayPrice[0] + (c.endClock - 12) * weekdayPrice[1];
				} else if (c.endClock > 18 && c.endClock <= 22) {
				price = (12 - c.startClock) * weekdayPrice[0] + (18 - 12) * weekdayPrice[1]
				+ (c.endClock - 18) * weekdayPrice[2];
				}
				} else if (c.startClock > 12 && c.startClock <= 18) {
				if (c.endClock > 12 && c.endClock <= 18)
				price = (c.endClock - c.startClock) * weekdayPrice[1];
				else if (c.endClock > 18 && c.endClock <= 22)
				price = (18 - c.startClock) * weekdayPrice[1] + (c.endClock - 18) * weekdayPrice[2];
				} else if (c.startClock > 18 && c.startClock <= 22) {
				price = (c.endClock - c.startClock) * weekdayPrice[2];
				}
		}
		return price;
	}

	private static int getWeek(Customer c) {
		// TODO Auto-generated method stub
		String [] weeks = {"星期一","星期二","星期三","星期四","星期五","星期六", "星期日"};
		String strDate=c.year+"-"+c.month+"-"+c.day;
		SimpleDateFormat f =new SimpleDateFormat("yyyy-MM-dd");
		Date date = null;
		try {
			date = f.parse(strDate);
		} catch (ParseException e) {
			System.out.println("輸入的日期格式不合理");
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		SimpleDateFormat sdf = new SimpleDateFormat("EEEE");
		String week = sdf.format(date);
		for(int i=0;i<weeks.length;i++) {
			if(week.equals(weeks[i]))
				return ++i;
		}
		return 0;
	}

	private static void printCancelError() {
		// TODO Auto-generated method stub
		System.out.println("Error: the booking being cancelled does not exist!");
	}

	private static void book(Customer cus) {
		// TODO Auto-generated method stub
		for(Customer c:booklist) {
			if(c.isTimeConflict(cus)) {
				printConfictError();
				return;
			}
		}
		booklist.add(cus);
		printBookSuccess();
		
	}

	private static void printBookSuccess() {
		// TODO Auto-generated method stub
		System.out.println("Success: the booking is accepted!");
	}

	private static void printConfictError() {
		// TODO Auto-generated method stub
		System.out.println("Error: the booking conflicts with existing bookings!");
	}

	private static void printInvalidError() {
		// TODO Auto-generated method stub
		System.out.println("Error: the booking is invalid!");
	}

}