Hackerrank's Minimum Average Waiting Time - java

Link to challenge can be found here
Problem Statement
Tieu owns a pizza restaurant and he manages it in his own way. While
in a normal restaurant, a customer is served by following the
first-come, first-served rule, Tieu simply minimizes the average
waiting time of his customers. So he gets to decide who is served
first, regardless of how sooner or later a person comes.
Different kinds of pizzas take different amounts of time to cook.
Also, once he starts cooking a pizza, he cannot cook another pizza
until the first pizza is completely cooked. Let's say we have three
customers who come at time t=0, t=1, & t=2 respectively, and the time
needed to cook their pizzas is 3, 9, & 6 respectively. If Tieu applies
first-come, first-served rule, then the waiting time of three
customers is 3, 11, & 16 respectively. The average waiting time in
this case is (3 + 11 + 16) / 3 = 10. This is not an optimized
solution. After serving the first customer at time t=3, Tieu can
choose to serve the third customer. In that case, the waiting time
will be 3, 7, & 17 respectively. Hence the average waiting time is (3
+ 7 + 17) / 3 = 9.
Help Tieu achieve the minimum average waiting time. For the sake of
simplicity, just find the integer part of the minimum average waiting
time.
Input Format
The first line contains an integer N, which is the number of
customers. In the next N lines, the ith line contains two space
separated numbers Ti and Li. Ti is the time when ith customer order a
pizza, and Li is the time required to cook that pizza. Output Format
Display the integer part of the minimum average waiting time.
Constraints
1 ≤ N ≤ 10^5
0 ≤ Ti ≤ 10^9
1 ≤ Li ≤ 10^9
Note
The waiting time is calculated as the difference between the time a
customer orders pizza (the time at which they enter the shop) and the
time she is served.
Cook does not know about the future orders.
I've been at this for several hours.
I'm pretty sure my problems has to do with the way I increment the total Wait time.
Any help would be much appreciated.
code:
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
public class Solution {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
MinimumAverageWaitingTime mawt = new MinimumAverageWaitingTime();
while(n-- > 0) mawt.insert(s.nextLong(), s.nextLong());
System.out.print(mawt.calculateAverageWaitingTime());
}
}
class MinimumAverageWaitingTime {
private PriorityQueue<e_time_p_time> incomingOrders = new PriorityQueue<>(10, new Comparator<e_time_p_time>(){
//Order by the customerWaitTime ASC
#Override public int compare(e_time_p_time w, e_time_p_time w1) {
return (int) (w.entryTime - w1.entryTime);
}
});
private PriorityQueue<e_time_p_time> awaitingOrders = new PriorityQueue<>(10, new Comparator<e_time_p_time>(){
//Order by the difference between entrytime and pizzaCookTime ASC
#Override public int compare(e_time_p_time w, e_time_p_time w1) {
return (int) (Math.abs(w.entryTime - w.pizzaCookTime) - Math.abs(w1.entryTime - w1.pizzaCookTime));
}
});
private long total = 0l;
public void insert(long customerWaitTime, long pizzaCookTime) {
incomingOrders.add(new e_time_p_time(customerWaitTime, pizzaCookTime));
}
public long calculateAverageWaitingTime() {
int size = incomingOrders.size();
e_time_p_time currentOrder = null;
e_time_p_time laterOrders = null;
while(incomingOrders.size() > 0) {
//Start by getting the customer that has the earliest arrival time (the queue is sorted that way)
currentOrder = incomingOrders.remove();
//Calculate it's waiting time.
total += currentOrder.entryTime + currentOrder.pizzaCookTime;
do {
/*Move all the customers that entered the shop while the current pizza is in the oven
to the awaitingOrders orders queue*/
laterOrders = incomingOrders.remove();
awaitingOrders.add(laterOrders);
} while (currentOrder.pizzaCookTime >= laterOrders.entryTime && incomingOrders.size() > 0);
//Go through awaitingOrders queue and calculate waiting time for the remaining orders
//(The queue is sorted as the difference between entrytime and pizzaCookTime ASC)
while(awaitingOrders.size() > 0) {
e_time_p_time shortestOrder = awaitingOrders.remove();
long waitTimeBeforeCooking = Math.abs((shortestOrder.entryTime + shortestOrder.pizzaCookTime) - currentOrder.entryTime);
total += waitTimeBeforeCooking;
}
}
//It's supposed to be the average time, but first I need the total to be correct, and right now, it's not...
System.out.println("\nTotal waiting time: ");
return total;
}
private static class e_time_p_time {
private long entryTime;
private long pizzaCookTime;
e_time_p_time(long entryTime, long pizzaCookTime) {
this.entryTime = entryTime;
this.pizzaCookTime = pizzaCookTime;
}
}
}

In this code:
do {
/*Move all the customers that entered the shop while the current pizza is in the oven
to the awaitingOrders orders queue*/
laterOrders = incomingOrders.remove();
awaitingOrders.add(laterOrders);
} while (currentOrder.pizzaCookTime >= laterOrders.entryTime && incomingOrders.size() > 0);
A couple of things seem wrong here:
You always add at least one item to awaitingOrders - but what if no-one enters the shop while the current pizza is in the oven? (e.g. for the last pizza)
You compare the pizzaCookTime - e.g. ten minutes, with the entryTime, e.g. 4pm. This doesn't seem right - shouldn't you compare the time that the pizza is completed with the entryTime?

Related

Optimization: Finding the best Simple Moving Average takes too much time

I've created a simple Spring-Application with a MySQL-DB.
In the DB there are 20 years of stock data (5694 lines):
The Goal is to find the Best Moving Average (N) for that 20 years of stock data. Inputs are the closing prices of every trading day.
The calculated average depends on the N. So p.e. if N=3 the average of a reference day t, is given by ((t-1)+(t-2)+(t-3)/N).
Output is the Best Moving Average (N) and the Result you made with all the buying & selling transactions of the Best N.
I did not find a proper algorithm in the Internet, so I implemented the following:
For every N (249-times) the program does the following steps:
SQL-Query: calculates averages & return list
#Repository
public interface StockRepository extends CrudRepository<Stock, Integer> {
/*
* This sql query calculate the moving average of the value n
*/
#Query(value = "SELECT a.date, a.close, Round( ( SELECT SUM(b.close) / COUNT(b.close) FROM stock AS b WHERE DATEDIFF(a.date, b.date) BETWEEN 0 AND ?1 ), 2 ) AS 'avg' FROM stock AS a ORDER BY a.date", nativeQuery = true)
List<AverageDTO> calculateAverage(int n);
Simulate buyings & sellings – > calculate result
Compare result with bestResult
Next N
#RestController
public class ApiController {
#Autowired
private StockRepository stockRepository;
#CrossOrigin(origins = "*")
#GetMapping("/getBestValue")
/*
* This function tries all possible values in the interval [min,max], calculate
* the moving avg and simulate the gains for each value to choose the best one
*/
public ResultDTO getBestValue(#PathParam("min") int min, #PathParam("max") int max) {
Double best = 0.0;
int value = 0;
for (int i = min; i <= max; i++) {
Double result = simulate(stockRepository.calculateAverage(i));
if (result > best) {
value = i;
best = result;
}
}
return new ResultDTO(value, best);
}
/*
* This function get as input the close and moving average of a stock and
* simulate the buying/selling process
*/
public Double simulate(List<AverageDTO> list) {
Double result = 0.0;
Double lastPrice = list.get(0).getClose();
for (int i = 1; i < list.size(); i++) {
if (list.get(i - 1).getClose() < list.get(i - 1).getAvg()
&& list.get(i).getClose() > list.get(i).getAvg()) {
// buy
lastPrice = list.get(i).getClose();
} else if (list.get(i - 1).getClose() > list.get(i - 1).getAvg()
&& list.get(i).getClose() < list.get(i).getAvg()) {
// sell
result += (list.get(i).getClose() - lastPrice);
lastPrice = list.get(i).getClose();
}
}
return result;
}
}
When I put Min=2 and Max=250 it takes 45 minutes to finish.
Since, I'm a beginner in Java & Spring I do not know how I can optimize it.
I'm happy for every input.
This problem is equivalent with finding the best moving N sum. Simply then divide by N. Having such a slice, then the next slice subtracts the first value and adds a new value to the end. This could lead to an algorithm for finding local growths with a[i + N] - a[i] >= 0.
However in this case a simple sequential ordered query with
double[] slice = new double[N];
double sum = 0.0;
suffices. (A skipping algorithm on a database is probably too complicated.)
Simply walk through the table keeping the slice as window, keeping N values and keys, and maintaining the maximum upto now.
Use the primitive type double instead of the object wrapper Double.
If the database transport is a serious factor, a stored procedure would do. Keeping a massive table as really many entities just for a running maximum is unfortunate.
It would be better to have a condensed table or better field with the sum of N values.

Java adding objects according to ratios and population sizes

My project is a simple agent based simulation that models the spread of disease. The simulation consists of agents and map, the classes that belong to agents are: Civil, Medic and Animal. Currently I'm trying to fill the map according to the size of populations: noMedics, noCivils, noAnimals and amount of healthy, ill, and immune agents that should add up to total population of both humans and animals.
The way that health status of an agent is determined is simple - random.nextInt(3), 0 being healthy, 1 ill and 2 immune. The way that I would usually fill the map with one of the agent class is as follows:
for (int i = 0; i < noAnimals; i++) {
IAgent animal = new Animal(map, rnd.nextInt(3), 2, 3);
agentList.add(animal);
}
However the issue arises whenever I would try to implement the remaining parameters of simulation that is: noHealthy, noImmune, noIll. I can't seem to find a loop or condition that would fullfill my need which is to "fairly" fill the map with all agents of in the given createAgents() method. Create agents takes 6 parameters: noHealthy, noImmune, noIll, noAnimals, noCivil, noMedics.
I've tried few things already but the one that compiles and runs correctly so far is as follows: I'm creating a loop that runs from currNoImmune until noImmune from parameters and whenever a condition sumForImmune < halfNoAnimals && currNoImmune <= noImmune is fulfilled it adds an animal to the simulation and increments sumForImmune and currNoImmune once. The reverse check is done for civlians sumForImmune >= halfNoAnimals && currNoImmune <= noImmune incrementing the same variables and adding a civil to the simulation. Here is the code for method I've described:
while (sumForImmune <= noImmune) {
if (sumForImmune < halfNoAnimals && currNoImmune <= noImmune) {
agentList.add(new Animal(map, 2, 0, 2));
sumForImmune++;
currNoImmune++;
}
if (sumForImmune >= halfNoAnimals && currNoImmune <= noImmune) {
agentList.add(new Civil(map, 2, 0, 2));
sumForImmune++;
currNoImmune++;
}
}
Then there are two loops that run until noIll and noHealthy and that's how agents are created so far. It works however not quite how I hoped it would. Numbers that are passed as arugments to createAgents() aren't being reflected on the map for all possible inputs. I realize that this task is beyond my capabilities since I've spend a good amount of time trying to figure it out, despite that I would still love to understand how it's done and how it can be achieved.
What I mean by fairly is as close to 50:50 as possible - whenever user inputs an uneven number of 3 immune, 1 animal and 2 civil agents there should be 2 immune civilians and 1 immune animal. Same logic shoud be extended to the missing parameters that is healthy and ill agents.
Edit:
What I mean by that mess written above is that I need an algorithm to place agents according to the ratios determined by noHealthy:noIll:noImmune for both population of Civilians (noCivils) and population of Animals (noAnimals). Taking into account that Medics are already immune so noImmune should shrink by the number of Medics present in the simulation.
Edit2:
I've played around with the maths a bit and this is what I managed to get but there is still issue with 1:1:1 ratios as they don't give expected results for given population sizes. One more thing is this doesn't account for medics yet, just so it doesn't mess the ratios and makes the logic a bit easier.
void createAgents(int noAnimals, int noCivil, noIll, noImmune, noHealthy) {
double sumTheRatio = noHealthy + noIll + noImmune;
double animalsPart = noAnimals / sumTheRatio;
double numHealthyAnimals = noHealthy * animalsPart;
double numIllAnimals = noIll * animalsPart;
double numImmuneAnimals = noImmune * animalsPart;
double civilPart = noCivil / sumTheRatio;
double numHealthyCivil = noHealthy * civilPart;
double numIllCivil = noIll * civilPart;
double numImmuneCivil = noImmune * civilPart;
//The only issue is when ratios of agent health states are 1:1:1
//- for example for ratios like 18:18:18 and 26 civilians 28 animals will
// give 27 agents for both animals and civilians (+/- 1 from expected numbers)
//- another example 7:7:7 and 1 civil and 20 animals will give 0 agents
// for civilians and 21 agents for animals (+/- 1 from expected numbers)
//- another example 14:14:14 and 38 civilians and 4 animals will give 39
// agents for civilians and 3 agents for animals (+/- 1 from expected numbers)
System.out.println("Rounded ratio number for animals:"
+ "\n healthy - " + Math.round(numHealthyAnimals)
+ " ill - " + Math.round(numIllAnimals)
+ " immune - " + Math.round(numImmuneAnimals));
System.out.println("Rounded ratio number for civilians:"
+ "\n healthy - " + Math.round(numHealthyCivil)
+ " ill - " + Math.round(numIllCivil)
+ " immune - " + Math.round(numImmuneCivil));
}
Then simply iterating to: Math.round(numHealthyCivil), Math.round(numIllCivil), Math.round(numImmuneCivil) and adding respective agent with each iteration.
Is there a way to adjust this algorithm or perhaps there is a need for different function responsible for agents creation whenever ratios are 1:1:1?
You say that Medics should have an Immune health status. The remaining problem is therefore to assign Civilians and Animals a health status of Healthy, Ill, or Immune such that:
noCivils + noAnimals + noMedics = noHealthy + noIll + noImmune
One way of doing this would be to create a health status array noCivils + noAnimals long and populate it with noHealthy, noIll, and noImmune-noMedics elements of the corresponding type (0, 1, 2). You then randomly shuffle this array and use the values to assign a health status to Civilians and Animals in turn.
Here's some Java code to illustrate:
static void createAgents(int noHealthy, int noImmune, int noIll,
int noAnimals, int noCivil, int noMedics)
{
for (int i=0; i<noMedics; i++) {
// create and add Medic, with health status Immune
}
int remImmune = noImmune - noMedics;
assert noCivil + noAnimals == noHealthy + noIll + remImmune;
int caAgents = noCivil + noAnimals;
Integer[] agentStatus = new Integer[caAgents];
Arrays.fill(agentStatus, 0, noHealthy, 0);
Arrays.fill(agentStatus, noHealthy, noHealthy+noIll, 1);
Arrays.fill(agentStatus, noHealthy+noIll, noHealthy+noIll+remImmune, 2);
Collections.shuffle(Arrays.asList(agentStatus));
int j = 0;
for (int i=0; i<noAnimals; i++, j++) {
// create and add Animal, with health status status[j]
}
for (int i=0; i<noCivil; i++, j++) {
// create and add Civilian, with health status status[j]
}
}

I write a program but it misses something and I don't know how to take the rent from loop

A real estate office handles 50 apartment units. When the rent is $600 per
month, all the units are occupied. However, for each $40 increase in rent,
one unit becomes vacant. Each occupied unit requires an average of $27 per
month for maintenance. How many units should be rented to maximize the
profit?
Write a program that prompts the user to enter:
The number of apartment Units
The rent to occupy all the Units
The increase in rent that results in a vacant unit
Amount to maintain a rented unit
The program then outputs the number of units to be rented to maximize
the profit
but I want to show to the user the rent and I don't know how
import java.util.*;
public class yeungah {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
double rent, maintenance, maintenanceCost, increase;
double result=0, profit, maxProfit = 0;
int h=0, number;
System.out.println(" enter the number of apartment units: ");
number=input.nextInt();
System.out.println( " enter the rent value for all the occupied units: ");
rent=input.nextInt();
System.out.println("The increase in rent that results in a vacant unit: ");
increase=input.nextInt() ;
System.out.println( "enter the maintain value for each occupied unit: ") ;
maintenanceCost=input.nextInt() ;
for (int i = number; i > 0; i--, rent += increase)
{
result = i * rent ;
maintenance = i * maintenanceCost ;
profit = result – maintenance ;
if (profit > maxProfit)
{
maxProfit = profit ;
h =i ;
}
}
System.out.println( "Number of units to be rented in order to maximize profit is: "+maxProfit) ;
System.out.println("It occurs when Number of occupied Units is:"+h) ;
}
}
can anyone help?
Sadly I cant make comments yet but I'm curious.
When does the for loop end? I cant see that it ever reached i>0 since i is always decreasing and I cant see that i is changed in the for loop.
I would use a while loop that breaks when profit isn't larger then maxprofit.
In the end it should be enough to take number-h to answer the assignment question
Take everything I write with a grain of salt since I'm also a rookie. :)
To show the rent after each increase do System.out.println(rent) at the end of the for loop.
To show the rent at the end you would do the same thin after the loop.
A problem I'm seeing here is that you don't seem drop out of the loop once the max profit is found. I would recommend a boolean flag. Set it to false have it as a condition along with 1 > 0.
Then within the loop add an else to your if statement setting it to true.
This will cause the loop to drop out once the max profit is found.

Find Survivor when n people are sitting in a circle

Hi I am across this problem and trying to solve this
Take a second to imagine that you are in a room with 100 chairs arranged in a circle. These chairs are numbered sequentially from One to One Hundred.
At some point in time, the person in chair #1 will be told to leave the room. The person in chair #2 will be skipped, and the person in chair #3 will be told to leave. Next to go is person in chair #6. In other words, 1 person will be skipped initially, and then 2, 3, 4.. and so on. This pattern of skipping will keep going around the circle until there is only one person remaining.. the survivor. Note that the chair is removed when the person leaves the room.Write a program to figure out which chair the survivor is sitting in.
I made good progress but stuck with a issue, after the count reaches 100 and not sure how to iterate from here, can any one help me, this is my code
import java.util.ArrayList;
public class FindSurvivor {
public static void main(String[] args) {
System.out.println(getSurvivorNumber(10));
}
private static int getSurvivorNumber(int numChairs) {
// Handle bad input
if (numChairs < 1) {
return -1;
}
// Populate chair array list
ArrayList<Integer> chairs = new ArrayList<Integer>();
for (int i = 0; i < numChairs; i++) {
chairs.add(i + 1);
}
int chairIndex = 0;
int lr =0;
while (chairs.size() > 1) {
chairs.remove(lr);
chairIndex+=1;
System.out.println(lr+" lr, size "+chairs.size()+" index "+chairIndex);
if(lr==chairs.size()||lr==chairs.size()-1)
lr=0;
lr = lr+chairIndex;
printChair(chairs);
System.out.println();
}
return chairs.get(0);
}
public static void printChair(ArrayList<Integer> chairs){
for(int i : chairs){
System.out.print(i);
}
}
}
The answer is 31. Here are three different implementations
var lastSurvivor = function(skip, count, chairs) {
//base case checks to see if there is a lone survivor
if (chairs.length === 1)
return chairs[0];
//remove chairs when they are left/become dead
chairs.splice(skip, 1);
//increment the skip count so we know which chair
//to leave next.
skip = (skip + 1 + count) % chairs.length;
count++;
//recursive call
return lastSurvivor(skip, count, chairs);
};
/** TESTS *******************************************************************
----------------------------------------------------------------------------*/
var result = lastSurvivor(0, 0, chairs);
console.log('The lone survivor is located in chair #', result);
// The lone survivor is located in chair # 31
/** ALTERNATE IMPLEMENTATIONS ***********************************************
-----------------------------------------------------------------------------
/* Implemenation 2
-----------------*/
var lastSurvivor2 = function(chairs, skip) {
skip++;
if (chairs === 1)
return 1;
else
return ((lastSurvivor2(chairs - 1, skip) + skip - 1) % chairs) + 1;
};
/** Tests 2 *******************************************************************/
var result = lastSurvivor2(100, 0);
console.log('The lone survivor is located in chair #', result);
// The lone survivor is located in chair # 31
/* Implemenation 3
------------------*/
var chairs2 = [];
for (var i = 1; i <= 100; i++)
chairs2.push(i);
var lastSurvivor3 = function(chairs, skip) {
var count = 0;
while (chairs.length > 1) {
chairs.splice(skip, 1);
skip = (skip + 1 + count) % chairs.length;
count++;
}
return chairs[0];
};
/** Tests 3 *******************************************************************/
var result = lastSurvivor3(chairs2, 0);
console.log('The lone survivor is located in chair #', result);
// The lone survivor is located in chair # 31
I'm not sure what your removal pattern is but I'd probably implement this as a circular linked list where the 100th seat holder will connect back to the 1st seat holder. If you use an array, you will have to worry about re-organizing the seats after every removal.
There is elegant analytical solution:
Let's change numbering of people: #2 -> #1, #3 -> #2, ..., #1 -> #100 (in the end we just need to substract 1 to "fix" the result). Now first person remains instead or leaving. Suppose that there is only 64 people in circle. It's easy to see that after first elimination pass 32 people in circle will remain and numbering will start again from #1. So in the end only #1 will remain.
We have 100 people. After 36 people will leave the circle we will end up with 64 people - and we know how to solve this. For each person that leaves the room one person remains, so circle with 64 people will start from 1 + 2*36 = #73 (new #1). Because of changing indexes on first step final answer will be #72.
In general case res = 2*(N - closest_smaller_pow_2) = 2*N - closest_larger_pow_2. The code is trivial:
public static long remaining(long total) {
long pow2 = 1;
while (pow2 < total) {
pow2 *= 2;
}
return 2*total - pow2;
}
Also this algorithm has O(log(N)) complexity instead of O(N), so it's possible to calculate function for huge inputs (it can be easily adapted to use BigInteger instead of long).
First, let's assume the chairs are numbered from 0. We'll switch the numbering back at the end -- but usually things are simpler when items are enumerated from 0 rather than 1.
Now, if you've got n people and you start eliminating at chair x (x is 0 or 1) then in a single pass through you're going to eliminate half the people. Then you've got a problem of roughly half the size (possibly plus one), and if you solve that, you can construct the solution to the original problem by multiplying that sub-result by 2 and maybe adding one.
To code this, it's simply a matter of getting the 4 cases (n odd or even vs x 0 or 1) right. Here's a version that gets the 4 cases right by using bitwise trickery.
public static long j2(long n, long x) {
if (n == 1) return 0;
return j2(n/2 + (n&x), (n&1)^x) + 1-x;
}
A solution with chairs numbered from 1 and without the extra argument can now be written:
public static long remaining(long n) {
return 1 + j2(n, 0);
}
This runs in O(log n) time and uses O(log n) memory.
If your step is incremental you can you use the following code:
int cur = 0;
int step = 1;
while (chairs.size() > 1) {
chairs.remove(cur);
cur += ++step;
cur %= chairs.size();
}
return chairs.get(0);
If your step is fixed to 1 then based on explanation provided by #Jarlax you can solve the problem with one-line of code in O(log n) time:
//for long values
public static long remaining(long numChairs) {
return (numChairs << 1) - (long)Math.pow(2,Long.SIZE - Long.numberOfLeadingZeros(numChairs));
}
//for BigInteger values
public static BigInteger remaining(BigInteger numChairs) {
return numChairs.shiftLeft(1).subtract(new BigInteger("2").pow(numChairs.bitLength()));
}
However, if you stick with ArrayLists no extra variables are required to your code. Always remove the first element and remove-then-add the next at the end of the list. This is however O(n).
while (chairs.size() > 1) {
chairs.remove(0);
chairs.add(chairs.remove(0));
}
return chairs.get(0);

Represent and compare time slots

I need to store time slots for restaurant table reservation and then see if there is any collision...
For example - Total tables - 4
1) 9 - 11 , 3 tables
2) 9 - 10 , 1 tables (Need to do search if any table left
with constraint to above booking)
How do i store the time slots and tables and compare with others...
what data structure should i use...
If i use HashMap what can be the key and value ,
I have designed all other classes and methods but cant able to find a way to solve time slot collision problem
collision example -
total - 4 tables
1) 9-10 , 3 tables
2) 9-11 , 1 table
3) 9-12 , 2 tables (collision , table not available)
You could simplify the problem, by slicing the available time in blocks of 15 minutes (or whatever other block size is suitable for you). For restaurant reservations I bet that 15 minute blocks are ok.
Then you could have a simple int[] which stores the number of booked tables for each time slot.
Example:
Your restaurant opens from 9 a.m. to 9 p.m., so 12 hours with 4 time slots each. So you need an int[] with 48 slots. Now, when you get a reservation for 3 tables 9 to 11 o'clock, then you increase the first 8 slots (means 9 to 11 o'clock) by 3. The second booking would increase the first 4 slots by 1. If a reservation would increase one of your slots over the available table limit, you know that you need to reject it.
final int MAX_TABLES = 4;
final int OPENING= 9;
final int CLOSING= 21;
final int SLOTS= 4;
int[] booking = new int[(CLOSING - OPENING) * SLOTS];
public void main() {
// no tables booked
Arrays.fill(booking,0);
doBooking(3, 0, 8);
doBooking(1, 4, 8);
doBooking(1, 4, 12);
}
public void doBooking(int tables, int startSlot, int endSlot) {
for (int slot= startSlot, slot < endSlot, slot++) {
if (booking[slot] + tables > MAX_TABLES) {
throw new Exception("no free table at slot "+slot);
}
}
for (int slot= startSlot, slot < endSlot, slot++) {
booking[slot] += tables;
}
}
This should give you the idea. There is still stuff to do, e.g. proper exception handling, conversion from time to slots, etc. Note also, that this may be improper java code, as I didn't test it nor did I write it in a GUI.
More examples :)
I had the same problem.
I create time slots with interface Slot and using it in the application
As example:
Schedule schedule = new Schedule(myduration, unit);
schedule.add(date1, slot1);
schedule.add(date2, slot2);
schedule.get(date1, slot1);
schedule.indexOf(date1, slot1);
schedule.remove(date1, slot1);
schedule.set(date1, index, slot1);
More details in github https://github.com/illineya/schedule
For time ranges(make it timestamp or 15 min intervals) use Guava Range - it has nice tools to work with ranges (collisions).
Start with open interval from now to future - all tables are available.
New reservation -> check whether there is a free table for the whole interval.
If there is break original interval to three -> before + this + after
Repeat...
You can create a TimeSlot objects and compare each start and endtimes.
public class TimeSlot {
private int startTime;
private int endTime;
public TimeSlot(int start, int end){
this.startTime = start;
this.endTime = end;
}
}

Categories