Schedule meeting problem (count how many meetings an owner can schedule based on investor availabilities) - algorithm

I tried to solve the task which sounds like "Given the schedules of the days investors are available, determine how many meetings the owner can schedule". The owner is looking to meet new investors to get some funds for his company. The owner must respect the investor's schedule. Note that the owner can only have one meeting per day.
The schedule consists of 2 integer arrays, firstDay and lastDay. Each element in the array firstDay represents the first day an investor is available, and each element in lastDay represents the last day an investor is available, both inclusive.
Example:
firstDay = [1,2,3,3,3]
lastDay = [2,2,3,4,4]
There are 5 investors [i0, i1, i2, i3, i4]
The investor i0 is available from day 1 to day 2 inclusive [1,2]
The investor i1 is available in day 2 only [2,2]
The investor i2 is available in day3 only [3,3]
The investors i3 and i4 are available from day 3 to day 4 only [3,4]
The owner can only meet 4 investors out of 5: i0 in day 1, i1 in day 2, i2 in day 3 and i3 in day 4. The image below shows the scheduled meetings in green and blocked days are in gray.
A graphic shows the scheduled meetings
The task is to implement the function which takes 2 lists of integers as input parameters and returns integer result that represents the maximum number of meetings possible.
Constraints
array length - bigger or equal 1 and less or equal 100000
firstDay[i], lastDay[i] bigger or equal 1 and less or equal 100000 (i bigger than or equal 0 less than n)
firstDay[i] less or equal lastDay[i]
My implementation of this task is the following:
public static int countMeetings(List<int> firstDay, List<int> lastDay)
{
var count = 0;
count = firstDay.Concat(lastDay).Distinct().Count();
if (count > firstDay.Count)
{
count = firstDay.Count;
}
return count;
}
And this code successfully passes 8 of 12 provided tests. I'll be glad to see and discuss any working solutions to this issue. Thanks.

For the input
firstDay = [1,1,1]
lastDay = [5,5,5]
your code returns 2 however correct answer is 3

Related

Optimizing the algorithm for checking available reservations for the store

I would like to ask about some algorithms related to checking if a customer can book a table at the store?
I will describe my problem with the following example:
Restaurant:
User M has a restaurant R. R is open from 08:00 to 17:00.
Restaurant R has 3 tables (T1, T2, T3), each table will have 6 seats.
R offers F1 food, which can be eaten within 2 hours.
Booking:
R has a customer C has booked a table T1 for 5 people with F1 food | B[0]
B[0] has a start time: 9AM
M is the manager of the store, so M wants to know if the YYYY-MM-DD date has been ordered by the customer or not?
My current algorithm is:
I will create an array with the elements as the number of minutes of the day, and their default value is 0
24 * 60 = 1440
=> I have: arr[1440] = [0, 0, 0, ...]
Next I will get all the bookings for the day YYYY-MM-DD. The result will be an array B[].
Then I will loop the array B[]
for b in B[]
I then keep looping for the start_time, to the end_time of b with step of 1 min.
for time = start_time, time <= end_time. time++
With each iteration I will reassign the value of the array arr with index as the corresponding number of minutes in the day to 1
(It is quite similar to Sieve of Eratosthenes)
Then what I need to do is iterate over the array arr 1 more time, if there is at least 1 value 0 in the array it means YYYY-MM-DDdate is still bookable.
But my algorithm will not be optimal if increase the number of tables that the store has, the number of days to check is many days (for example from 2022-01-01 -> 2022-02-01), ...
Thank you very much.
P/S: Regarding the technology background, I am currently using laravel 9

Algorithm to sort users into teams (based on minimum/maximum number for each team)

I am trying to come up with an algorithm for sorting and assigning teams to a fixed number of users. The majority of algorithms that I've found assume the number of groups to divide by; I would like to create a smart system where the groups are assigned automatically (to the best of its ability) and predicted based on the total user count, and the minimum and maximum number of users per group.
Assume the following criteria for each group:
Minimum of 3 per group
Maximum of 6 per group
Smart grouping based on total number of users
Here are some of the possibilities based on the total user count and the minimum/maximum values for each group:
For 24 members:
4 groups of 5 and 1 group of 4
6 groups of 4
4 groups of 6
For 21 members:
3 groups of 6 and 1 group of 3
3 groups of 5 and 1 group of 6 (better choice)
For 10 members:
2 groups of 5 (better choice)
2 groups of 3 and 1 group of 4
Although not necessary, the "better choice" for groups would be an equal amount of users per group (e.g. 10 members would be 2 groups of 5), unless impossible (e.g. 21 members) whereby 5+5+5+6 is "more equal" in terms of members per group than 6+6+6+3.
With the criterion you've given so far - minimum group size variation - the number of cases is limited.
If the target is a multiple of 3, 4, or 5, split into equal-sized groups. (We never need groups of size 6.)
Otherwise the target is either 1 or 2 (mod 3).
For the mod 1 case use a single group of 4 with all others being 3.
For the mod 2 case use two groups of 4 with all others being 3.
Note for 21 you left out the obvious choice of 7 groups of 3.
With this algorithm:
24 - 8 groups of 3
21 - 7 groups of 3
10 - 2 groups of 3, 1 group of 4 (the 1 (mod 3) case)
14 - 2 groups of 3, 2 groups of 4 (the 2 (mod 3) case)
Maybe you are quietly thinking (but not saying) that you'd also like to minimize the number of groups. If that's true, then you need to indicate the relative importance of small number of groups and group size variation. These two factors require a tradeoff.
Here's a solution in JS for anyone that's interested https://jsfiddle.net/kp8d0w27/6/
The first loop checks whether the total number of attendees can be divided equally. If it can, do that.
The second loop will only run if the total is not equally divisible, and will loop until the remainder (modulo) is greater than the minimum set and less than the maximum.
Finally, I'm using a Lodash function called chunk to split the original array into equal parts.
const minNumber = 3
const maxNumber = 6
let divisible = false
let totalGroups = 0
let perGroup = 0
const attendees = ['chris', 'kevin', 'thomas', 'gio', 'nathan', 'michael', 'elyse', 'sarah', 'jacinthe', 'chloe', 'benoit', 'alex', 'darren', 'john']
const totalAttendees = attendees.length
// Can we divide into equal groups?
for (let divider = maxNumber; minNumber <= divider; divider--) {
totalGroups = totalAttendees / divider
if (Number.isInteger(totalGroups)) {
divisible = true
perGroup = divider
break
}
}
// Nope, so divide teams and make sure their between our min and max
if (!divisible) {
totalGroups = 0;
for (let j = maxNumber, remainder = 0; minNumber <= j; j--) {
remainder = totalAttendees % j
if (remainder >= minNumber && remainder <= maxNumber) {
perGroup = j;
break
}
}
}
console.log(JSON.stringify(_.chunk(attendees, perGroup)))
Not the cleanest (and there's some situations that I did not account for here, like if the number of attendees is less than the minimum), I'm still refactoring, but it works well and solves my original problem.

rollapply + specnumber = species richness over sampling intervals that vary in length?

I have a community matrix (samples x species of animals). I sampled the animals weekly over many years (in this example, three years). I want to figure out how sampling timing (start week and duration a.k.a. number of weeks) affects species richness. Here is an example data set:
Data <- data.frame(
Year = rep(c('1996', '1997', '1998'), each = 5),
Week = rep(c('1', '2', '3', '4', '5'), 3),
Species1 =sample(0:5, 15, replace=T),
Species2 =sample(0:5, 15, replace=T),
Species3 =sample(0:5, 15, replace=T)
)
The outcome that I want is something along the lines of:
Year StartWeek Duration(weeks) SpeciesRichness
1996 1 1 2
1996 1 2 3
1996 1 3 1
...
1998 5 1 1
I had tried doing this via a combination of rollapply and vegan's specnumber, but got a sample x species matrix instead of a vector of Species Richness. Weird.
For example, I thought that this should give me species richness for sampling windows of two weeks:
test<-rollapply(Data[3:5],width=2,specnumber,align="right")
Thank you for your help!
I figured it out by breaking up the task into two parts:
1. Summing up species abundances using rollapplyr, as implemented in a ddplyr mutate_each thingamabob
2. Calculating species richness using vegan.
I did this for each sampling duration window separately.
Here is the bare bones version (I just did this successively for each sampling duration that I wanted by changing the width argument):
weeksum2 <- function(x) {rollapply(x, width = 2, align = 'left', sum, fill=NA)}
sum2weeks<-Data%>%
arrange(Year, Week)%>%
group_by(Year)%>%
mutate_each(funs(weeksum2), -Year, -Week)
weeklyspecnumber2<-specnumber(sum2weeks[,3:ncol(sum2weeks)],
groups = interaction(sum2weeks$Week, sum2weeks$Year))
weeklyspecnumber2<-unlist(weeklyspecnumber2)
weeklyspecnumber2<-as.data.frame(weeklyspecnumber2)
weeklyspecnumber2$WeekYear<-as.factor(rownames(weeklyspecnumber2))
weeklyspecnumber2<-tidyr::separate(weeklyspecnumber2, WeekYear, into = c('Week', 'Year'), sep = '[.]')

Minimize the number of trips or Group maximum possible orders

We have one distribution center ( ware house ) and we are getting orders in real time whose time/distance from ware house and other order locations is known.
time matrix=
W O1 O2 O3
W 0 5 20 2
O1 5 0 21 7
O2 20 21 0 11
O3 2 7 11 0
order time of O1= 10:00 AM
order time of O2= 10:20 AM
order time of O3= 10:25 AM
I want to club as many as order possible such that delivery time of any order does not exceed by 2 hours of its order time. Thus the question is to reduce the number of trips(Trip is when delivery agent goes for delivery).
I am trying to come up with algorithm for this. there are two competing factors when
We can combine all the orders in the sequence as they are coming till it satisfies the constraint of delivery of the order within 2 hours of its ordering time.
We can modify above approach to find the bottleneck order(due to which we can not club more order now in approach 1). and pull it out from trip1 and make it a part of trip 2(new order) and wait for other orders to club it with trip1 or trip2 depending.
All the orders are coming in realtime. What will be the best approach to conquer this situation. Let me know if you need more clarity on this.
Very safe and easy algorithm which is guaranteed to not exceed the maximal waiting time for an order:
Let TSP() be a function which returns the estimate of time spent to visit given places. The estimate is pessimistic, i.e. the actual ride time can be shorter or equals to estimate, but not longer. For the good start you can implement TSP() very easily in a greedy way: from each place go to the nearest place. You can subtract the length of the longer edge coming out from W to have better estimate (so a car will always take the shorter edge coming out of W). If TSP() would happen to be optimal, then the whole algorithm presented here would be also optimal. The overall algorithm is as good as TSP() implementation is, it highly depends on good estimation.
Let earliestOrderTime be a time of the earliest not handled yet order.
Repeat every minute:
If there is a new order: If s is empty, set earliestOrderTime to current time. Add it to a set s. Calculate t = TSP(s + W).
If (current time + t >= earliestOrderTime + 2 hours): send a car for a TSP(s + W) trip. Make s an empty set.
Example
For your exemplary data it will work like this:
10:00. earliestOrderTime = 10:00. s = {O1}. t = TSP({01, W}) = 10 - 5 = 5.
10:00 + 0:05 < 10:00 + 2:00, so we don't send a car yet, we wait.
...
10:20. s = {O1, O2}. t = 46 - 20 = 26.
10:20 + 0:26 < 10:00 + 2:00, so we wait.
...
10:25. s = {O1, O2, O3}. t = 2 + 7 + 21 + 20 - 20 = 30.
10:25 + 0:30 < 10:00 + 2:00, so we wait.
...
11.30.
11:30 + 0:30 >= 10:00 + 2:00, so we send a car to go to O3, O1, O2 and back to W. He visits orders at 11:32, 11:39, 12:00 and come backs at 12:20. Guys where waiting 67, 99 and 100 minutes.

Algorithm for a health/activity score for completing tasks on a website

We're creating a basic site where users get to-do's delivered to them each week. I need to create an algorithm which based on there completion (or lack there of) of these to-do's, I assign them a health score of 0 - 100.
There are 0 - 4 to-do's delivered each week.
A to-do can be completed, deleted (marked as irrelevant), or left pending.
If users aren't completing their to-do's (to-do's in the pending state) then they have a low health meter.
I'd also like to weight the pending states. For example pending to-do's in the first week aren't as detrimental to the score as pending to-do's in the 4th week. I'm only thinking of using the last 4-6 weeks of data to determine the score.
Any help with the approach I should take would be much appreciated.
I'm currently using the following notation
t0 # total to-dos given in week 0
t0_c # completed to-dos from week 0
t0_d # deleted to-dos from week 0
t0_p # pending to-dos from week 0
This sounds like the perfect place for a Moving average.
Example:
health for a week = 100*((not done for that week)^1.5)/8
Then use an exponential moving average on the historical and current health scores to get the current health.
May be you could assign completion scores each week and assign weight-age for each week's completion scores. Since you are considering say only last 5 weeks of scores, you could have something like (1 for completion, 0 for pending)
week 1 [1,0,0,1] completion score = 50%
week 2 [1,0,1] completion score = 66.6%
week 3 [0] completion score = 0%
week 4 [1] completion score = 100%
week 5 [1,0,0,0] completion score = 25%
All dont have total of 4 to-dos as some may be irrelevant
Now you assign weekly weights, you know week1 is 5 weeks back and so should have more weight and eventually comes down at week 5, so something like
week1 weight = 30%
week2 weight = 25%
week3 weight = 20%
week4 weight = 15%
week5 weight = 10%
Now just multiply week's completion score to its weight and add the terms
(50*30 + 66.6*25 + 25*0 + 15*100 + 25*10)/100 = 49.15%
One downside to this approach is that,
Say Guy1 week1 has 1 to-do pending i.e
week 1 [0] => score = 0%
Say Guy2 week1 has 2 to-do pending but one complete i.e
week 1 [0,0,1] => score = 33%
Guy2 gets much higher score though he has more pending work
If number of to-dos are roughly same among the customers on an average then this wont be a big issue.

Resources