Represent and compare time slots - java

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;
}
}

Related

Grouping of 5 items sorted by criteria

I want to make a java application, which is addressed for an esports competition. Specifically this application will be for a teamspeak server.
I want users on a channel to be sorted into groups of 5 (they will be identified by a uniqid and a number representing the skill level).
Thus, when 5 users are between skill levels 1 - 3 to be placed in one group, the next ones in another group (each of 5), and until that list / map will no longer be able to be made groups of 5.
Can you help me with an idea? I know how to get the uniqid from the teamspeak server, as well as the skill level, but I don't know how to randomly group them and meet that skill level condition.
I tried a hashmap but it failed.
HashMap<Integer, Integer> teams = new HashMap<>();
for(Client c : api.getClients()){
if(c.getChannelId() == 2170){
if(api.getChannelByNameExact("[LOBBY] Cauta echipa",true).getTotalClients() >= 5) {
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVER1")))) {
teams.put(c.getId(), 1);
}
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVER2")))) {
teams.put(c.getId(), 2);
}
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVER3")))) {
teams.put(c.getId(), 3);
}
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVER4")))) {
teams.put(c.getId(), 4);
}
if (c.isInServerGroup(Integer.parseInt(Configuration.info().getProperty("SILVERE")))) {
teams.put(c.getId(), 5);
}
while(teams.size() >= 5){
teams.forEach((key, value) -> {
System.out.println("Key : " + key + " Value : " +value);
if(value > 1 && value < 5){
teams.
}
});
}
teams.clear();
}
}
}
Exemple:
If on a teamspeak channel there are 20 people with skill level in 1 lvl -18 lvl, the robot will build teams of 5 members with similar skill level (with a margin of + - 1 level).
For example, if I have skill level 5, and on the channel there are at least 4 people with skill level between 3-5, the 5 people (including myself) will be added to a list or array or whatever.
After we made the team of 5 people, the program will continue to run and form teams of 5 people with similar skill level, until it will no longer be possible (there will be no 5 people in the main room).
On my mind you should divide on two groups(ArrayLists) hightlevel and lowlevel, for this create function and check skills level(skills>3)=>hight else=>low;
After create HashMap team; where keys - ids; and value - numbers of group;
With operator for and function MathRandom complete first group; value++; Continue while you have available people.
Change value +1(it will be next group) complete HashMap with next Array, using MathRandom();
This is working, if ids - Integer and unique. of course you have to delete from Array element after putting in the map
Also you can try to manage with databases MongoDB:
1.Create two datas: high and low level
2. With Pagebale create page items on page 5; number of page will be your group number. Use method unsorted

Random Number with Java in Android Studio

i'm try to make a random or unique code to payment method, for example the user must pay for Rp. 10.000 and then the user checkout and the system give the total payment with unique code in last three number.
For example user should pay for Rp. 10.000 and then the system showing Rp. 10.123
for other example, user pay for 1.000.000 and then system showing the total is 1.000.562 just unique or random in last three number
how i can make like this in java for android ?
UPDATE
i've been try this code
int someNumber = 10.000;
int lastThree = someNumber % 1000;
but when the last 3 number is '0' it return 0, when i'm change the last 3 number like 10.234 it return into 234, now how i can get the last three number when the value is like 10.000
That's because your 'lastThree' is an integer and there is no way to have an integer like 000. if you need last three number, you can use something like this:
int someNumber = 10.000;
String temp = Integer.toString(someNumber);
String lastThree = temp.substring(temp.length() - 3);
Now if you pass 10000, lastThree will be '000'.

Hackerrank's Minimum Average Waiting Time

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?

Aggregating objects by timestamp per day for a timespan of week

I have problem with aggregating data based on their timestamp per day for a timespan of one week. There is a SQLite database, which has a table which I save the number of walking steps in (timestamp column is UTC and created_At is local time, but I don't use the created_at column anyway).
What I want to do is get the total data which happened in 7 days ago until the midnight of a day before. So I have this jodatime expression to find start and end for timestamps
long start = new DateTime().withMillisOfDay(0).minusDays(7).getMillis();
long end = new DateTime().withTimeAtStartOfDay().getMillis();
//start milli:1405029600000 DateTime: 2014-07-11 00:00:00
//end milli:1405634400000 DateTime: 2014-07-18 00:00:00
Then I execute this sql command:
SELECT * FROM pa_data WHERE timestamp BETWEEN 1405029600000 AND 1405634400000
And I am pretty sure that it returns the correct rows ( I have compared the android database result with SQLite Database Browser on my pc, both return same number of rows). For this, I tried to use this nested iteration:
the Object I am trying to create is:
public class PhysicalActivityPerDay {
private List<PhysicalActivity> mList;
public PhysicalActivityPerDay(List<PhysicalActivity> list) {
mList = new ArrayList<PhysicalActivity>(list);
}
//methods....
}
Now the problem is, I want to have a data object that can hold the rows for each day.
List<PhysicalActivity> all = getPhysicalActivitiesBetween(start, end);
List<PhysicalActivityPerDay> perDays = new ArrayList<PhysicalActivityPerDay>();
List<PhysicalActivity> tempList;
PhysicalActivityPerDay tempPerDay;
for (int i = 0; i < 7; i++) {
long begin = start;
long stop = (begin + 86400000); //add 24 hours
tempList = new ArrayList<PhysicalActivity>();
for (int j = 0; j < all.size(); j++) {
PhysicalActivity p = all.get(j);
DateTime when = new DateTime(p.getTimestamp());
if (when.isAfter(start) && when.isBefore(stop)) {
tempList.add(p);
all.remove(j); //remove the matching object from the list
}
}
tempPerDay = new PhysicalActivityPerDay(tempList);
perDays.add(tempPerDay);
start += 86400000; //add 24 hours or 1 day for next iteration
}
return perDays;
But the result is totally unexpected. There are many rows which don't match the if statements above. I did a debug and here is what happens:
Log.w(TAG, "There are totally " + all.size() + " physical activities for day for 7 days");
//There are totally 6559 physical activities for day for 7 days
But, when I check the all list (total rows returned by DB) although I am removing matched objects from it, if I query its size after the nested iteration, it surprisingly still contains many objects in it, telling me that the iteration was not successful!
//Remaining: 3278 records after iterations from 6559
What I am doing wrong? please help me findout!
Not sure if that's the only problem :
You are looping over the all List, and removing items.
When you call all.remove(j), the item that used to be at position j+1 moves to poisition j. Which means your for loop would skip that item.
One way to solve this is to increment j only if you don't remove an item from the list.
for (int j = 0; j < all.size();) {
PhysicalActivity p = all.get(j);
DateTime when = new DateTime(p.getTimestamp());
if (when.isAfter(start) && when.isBefore(stop)) {
tempList.add(p);
all.remove(j); //remove the matching object from the list
} else {
j++;
}
}
Actually, I'm not entirely sure if the loop would work after this fix. It depends whether all.size() is evaluated in each iteration. If it isn't, it would expect the list to have the initial number of elements, even though you are removing items. In that case you can expect to get an exception the first time you try to access an index beyond the last index of the array.
If you get an exception, you can replace the loop with a while loop :
Iterator<PhysicalActivity> iter = all.iterator();
while (iter.hasNext ()) {
PhysicalActivity p = iter.next();
...
if (...) {
iter.remove();
}
}
Refer to the definition of List.remove() :
public E remove(int index)
Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).
How about letting SQL perform your aggregation for you
SELECT strftime('%W-%Y',dt) as weekYear, count(1) as occurencePerWeek
FROM SOMETABLE c GROUP BY weekYear;
http://sqlfiddle.com/#!5/e63c3/1

Java: Unique 10 digit ID

I need to generate a unique 10 digit ID in Java. These are the restrictions for this ID:
Only Numeric
Maximum 10 digits
Possible to create up to 10 different IDs per second
Has to be unique (even if the application re-starts)
Not possible to save a number in the Database
As fast as possible NOT to add much lattency to the system
The best solution I found so far is the following:
private static int inc = 0;
private static long getId(){
long id = Long.parseLong(String.valueOf(System.currentTimeMillis())
.substring(1,10)
.concat(String.valueOf(inc)));
inc = (inc+1)%10;
return id;
}
This solution has the following problems:
If for any reason there is a need to create more than 10 IDs per seccond, this solution won't work.
In about 32 years this ID could be repeated (This is probably acceptable)
Any other solution to create this ID?
Any other problem I haven't thought of with mine?
Thanks for your help,
This is a small enhancement to yours but should be resilient.
Essentially, we use the current time in milliseconds unless it hasn't ticked since the last id, in which case we just return last + 1.
private static final long LIMIT = 10000000000L;
private static long last = 0;
public static long getID() {
// 10 digits.
long id = System.currentTimeMillis() % LIMIT;
if ( id <= last ) {
id = (last + 1) % LIMIT;
}
return last = id;
}
As it is it should manage up to 1000 per second with a comparatively short cycle rate. To extend the cycle rate (but shorten the resolution) you could use (System.currentTimeMillis() / 10) % 10000000000L or (System.currentTimeMillis() / 100) % 10000000000L.
This may be a crazy idea but its an idea :).
First generate UUID and get a string representation of it with
java.util.UUID.randomUUID().toString()
Second convert generated string to byte array (byte[])
Then convert it to long buffer: java.nio.ByteBuffer.wrap( byte
digest[] ).asLongBuffer().get()
Truncate to 10 digits
Not sure about uniqueness of that approach tho, I know that you can rely on uniqueness of UUIDs but haven't checked how unique are they converted and truncated to 10 digits long number.
Example was taken from JavaRanch, maybe there is more.
Edit: As you are limited to 10 digits maybe simple random generator would be enough for you, have a look into that quesion/answers on SO: Java: random long number in 0 <= x < n range
private static AtomicReference<Long> currentTime = new AtomicReference<>(System.currentTimeMillis());
public static Long nextId() {
return currentTime.accumulateAndGet(System.currentTimeMillis(), (prev, next) -> next > prev ? next : prev + 1) % 10000000000L;
}
What means that it has to be unique? Even across more currently running instances? It break your implementation.
If it must be unique across universe, the best solution is to use UUID as it's mathematically proven identifier generator as it generates unique value per universe. Less accurate number brings you collisions.
When there is only one concurrent instance, you can take current time in millis and solve 10ms problem using incrementation. If you sacrifice proper number of last positions in the number you can get many number within one milliseconds. I would than define the precision - I mean how much unique numbers do you need per seconds. You will solve the issue without any persistence using this approach.

Categories