Interval Scheduling Algorithm or Activity Selection Algorithm - php

I'm struggling with this question for so long.
There are n persons who want same room in a hotel. Each person wants to stay in the hotel for his own convenient time but only one person can stay at a time. Assume that room is available from 5AM to 11PM. Hotel manager takes 500 rupees from each person who is staying in that room. It does not matter how long a person stays in that room. We have to maximize the profit of the manager. Let us say that n =4 i.e. four persons want same room. Let us say that 1st person wants the room from 6AM to 8AM and 2nd person wants room from 7AM to 8AM, 3rd person wants room from 8AM to 12PM and 4th person wants room from 11AM to 1PM.
By observing above figure, we can easily see that manager can only allow maximum of two persons to stay (1st and 3rd or 1st and 4th or 2nd and 3rd or 2nd and 4th). So maximum profit he can get is 500+500 = 1000 rupees. So we have to implement an algorithm which can find maximum profit value. Assume that the persons want the room only b/w 5AM to 11PM and each person wants room in multiple of hours.
Input description:
{<1st person starting time>#<1st person ending time>,<2nd person starting time>#<2nd person ending time>,…………, # }
Output description:
Output should be maximum profit value.
For the example considered in the question, output is 2000.
Example:
Input: {6AM#8AM,11AM#1PM,7AM#3PM,7AM#10AM,10AM#12PM,2PM#4PM,1PM#4PM,8AM#9AM}
Output:
2000

This is Interval Scheduling Problem.
It can be solved by sorting the intervals by end time, and choosing greedily the earliest deadline first, remove all overlapping intervals and repeat.

Looks like a variant of the Activity Selection Problem.
Read this TopCoder Tutorial for an excellent explanation.

Below is the exact solution for your question:
<?php
// Timezone set
date_default_timezone_set("Asia/Kolkata");
// User - i/p
$input = "{6AM#8AM,11AM#1PM,7AM#3PM,7AM#10AM,10AM#12PM,2PM#4PM,1PM#4PM,8AM#9AM}";
// Processing i/p string to ARRAY
$input_array = []; // Array given as i/p to "calculateprofit"-function
$processed_array = (explode(',', substr($input, 1, -1)));
foreach ($processed_array as $key => $value)
$input_array[] = explode("#", $value);
// Function call and display o/p
$maximim_profit = calculateprofit($input_array);
echo "<strong>Input</strong> = ".$input;
echo "<br/><br/><strong>Maximum Profit</strong> = ".$maximim_profit;
// Function to calculate - Maximum Profit
function calculateprofit($input){
$room_charges = 500;
$members_covered = [$input[0]];
$last_member = 0;
$finishing_time = array();
foreach ($input as $key => $row)
$finishing_time[$key] = date("H:i", strtotime($row[1]));
array_multisort($finishing_time, SORT_ASC, $input);
for($i=1; $i<sizeof($input); $i++){
$current_coustmer = $input[$i];
if(date("H:i", strtotime($current_coustmer[0])) >= date("H:i", strtotime($input[$last_member][1])) ){
$members_covered[] = $input[$i];
$last_member = $i;
}
}
// print_r($members_covered);
return sizeof($members_covered)*$room_charges;
}
?>

Related

How to calculate the difference between minutes of a series of time intervals

I need to calculate the difference, "for example in minutes", of a series of intervals, however there is no limit, because there may be N time records, between "tipo_2_pause" and "tipo_3_return".
Excluding "tipo_1_start" and "tipo_4_end", both "tipo_2_pause" and "tipo_3_return" is an array with N records.
As an example, I need to calculate the difference between the "tipo_4_end" and the "tipo_1_start".... ok... this is easy... but I'm not able to find a way in which I can calculate always considering the respective pairs between "tipo_2_pause" and "tipo_3_return".
In the example, the first pair between "tipo_2_pause" and "tipo_3_return", I hope to get the difference... which in this case is equal to 10min....in the second pair, by chance, it could also be 10min... but it could be any time .. but if there is no pair, the result would be 0.
Objective:
Being able to calculate the difference in minutes between each item in the array "tipo_2_pause" that pairs with the array "tipo_3_return".
You're right that the key to getting pairs is to use the length of the shorter array.
Then you just apply a for-loop.
Somewhat verbose (for clarity) first pass:
$numPairs = min(count($tipo2), count($tipo3));
$duration = 0;
for($i=0; $i<$numPairs; $i++){
$start = $tipo2[$i];
$end = $tipo3[$i];
$duration += minutes_between($start, $end); // implementing minutes_between is left as an exercise.
}

PHP MySql time calculations

I want to calculate how much time the worker has left since break start.
By the click, PHP insert into history table a record with timestamp (break_start), after second click, PHP update record with timestamp (break_end).
Now i can calculate time difference using this code:
$break_start = $worker->query('SELECT break_start FROM history WHERE id = 16')->fetchArray();
$break_end = $worker->query('SELECT break_end FROM history WHERE id = 16')->fetchArray();
$diff = $worker->query("SELECT TIMEDIFF('".$break_end['break_end']."','".$break_start['break_start']."') AS total")->fetchArray();
$break_total = $worker->query("SELECT break_time FROM worker WHERE id = 7")->fetchArray();
echo $diff['total']." ";
echo $break_total['break_time']." ";
$str1 = strtotime($diff['total']);
$str2 = strtotime($break_total['break_time']);
Output is: 00:31:26 00:30:00.00 86 01:26
(This code above is just attempt to understand time in PHP and MySQL).
I want to subtract break time from "break" value which is stored in table "worker" (default value is 30).
I don`t know how to do this..

Is it bad to use a middle sql table

I have a db-table that holds holidays i.e. when Cristmas, Easter different fasts UN-days and also celebrations from the Hijri (Muslim), Hebrew (Jewish) and Chineese calendars.
All holidays are saved on the date(s) they occur in their own calendar. But not all days are celebrated on a particular date. An example is the four Advent sundays which for the fourth one is between the dates of 18:th and 24:th of december and on a sunday.
There are also other examles as in the Netherlands where some days of celebration are moved when on a Sunday.
When it comes to fasts they can hav varied length and at least in the Swedish protestant church there are also Sunday masses wich are excluded if a more important one occurs.
So my table is set up as follows:
The PHP for the actual SQL, note that it itterates over all calendars.
foreach ($kal as $kalender => $arr_date) {
$go_Y = (int)$arr_date['go']['Y'];
$go_m = (int)$arr_date['go']['m'];
$go_d = (int)$arr_date['go']['d'];
$end_Y = (int)$arr_date['end']['Y'];
$end_m = (int)$arr_date['end']['m'];
$end_d = (int)$arr_date['end']['d'];
$sql = "SELECT
id,
name,
IF (picture_link = '', type_image, picture_link) AS logo,
start_year,
start_month,
start_day,
end_year,
end_month,
end_day,
year_interval,
start_weekday,
shift,
period,
ends_with_holiday,
has_php,
is_type,
in_calendar,
begins_year,
first_year,
bank_holiday,
has_note,
source_link,
COUNT(flagday_id) AS flagdays,
flagday_for_contry, /* if for only one contry, othervise an extra SQL is needed */
flagday_type,
flagday_information,
flagday_source
FROM holiday
LEFT JOIN type ON (type.id = holiday.is_type)
LEFT JOIN flagday ON (holiday.id = flagday_for_holiday)
WHERE is_calendar = $kalender
AND (start_year IS NULL OR start_year <= $end_Y)
AND (end_year IS NULL OR end_year >= $go_Y)
AND IF($end_m < $go_m OR ($end_m = $go_m AND $end_d < $go_d), /* If over new years */
(start_month < $end_m OR start_month = $end_m AND start_day <= $end_d)
OR (end_month > $go_m OR end_month = $go_m AND end_day >= $go_d)
, /* ELSE, if not over new years */
(start_month < $end_m OR start_month = $end_m AND start_day <= $end_d)
AND (end_month > $go_m OR end_month = $go_m AND end_day >= $go_d)
)
GROUP BY id
ORDER BY start_weekday IS NULL DESC,
start_weekday DESC";
$result = mysqli_query($con, $sql) or die(mysqli_error($con));
while ($result && mysqli_num_rows($result) && $row = mysqli_fetch_array($result)) {
if($kalender == 8) { // om den cyclic jewish calendar, one more argument is needed
$out_arr = get_holiday ($ut_arr, $row, $kalender, $go_Y, $go_m, $go_d, $end_Y, $end_m, $end_d, $con, $country, array($kal[4]['go']['Y']));
} else {
$out_arr = get_holiday ($ut_arr, $row, $kalender, $go_Y, $go_m, $go_d, $end_Y, $end_m, $end_d, $con, $country);
}
}
The get_holday() function does the PHP part if 'has_php' = 1 and also adds roman numerals to the end if a holiday is more than one day. But in essence it just puts the row in an multidimensional array: The first part is the gregorian date when it occurs (there are two helperfunctions to convert dates), the second is just an irreation on that Gregorian date and the third is the different columns from the db.
$out_arr['Y-m-d'][$i][$column] = $column_value;
So now the question
This as you can see is cuite time consuming an for now it's only been for personal use so it hasn't been a real problem. If you want an examle (in Swedish) the top left part with the picture icons on my links page
I was instead thinking of outputting all this into an other db table that just holds the id and (Gregorian) date (for the next 10 years) and each year or when a new holiday is added just update the new table. Is this a good idea or does it just create the same data in multiple places and a risk that they don't match in the end?
Use foreign key constraints to make sure your database stays consistent:
Have one table with all days in it,
one for the various kinds of holiday days,
one for the various countries' calendars,
and one mapping table that says which days are what kind of day in what regional calendar.
And then pre-calculate everything. This method is flexible and allows for unlimited calendars/countries/holidays, and you can expand with more metadata about each kind of holiday and so on either by adding it into separate tables, or adjusting only the affected table. This is easier to maintain.

PHP actuarial-type probability formula

How would I convert the following formula to php to solve for "p":
(1-p)^365=.80
What I'm trying to do is calculate the daily probability of an event based on the annual probability. For example, let's say the likelihood that John Doe is going to die in a particular year is 20%. So what would be the likelihood on any given day of that year? I know the answer for that example scenario is 0.0611165 using the formula above (where .80 is the 80% annual survival probability). What I need is a formula in which I can substitute various annual probabilities and the result would be the corresponding daily probabilities.
Can anyone help?
To solve for p you need to take the 365-th root of both sides, then solve for p.
<?php
$prob = 0.80;
$p = 1 - pow($prob, 1/365);
?>
Well you'd take the 365th root of both sides which is equivalent to raising to the 1/365
<?php
$prob = 0.80;
$prob = pow($prob, 1/365);
then you'd add 1
$p = $prob + 1;
echo $p;
?>

How do I pick a selection of rows with the minimum date difference

The question was difficult to phrase. Hopefully this will make sense.
I have a table of items in my INVENTORY.
Let's call the items Apple, Orange, Pear, Potato. I want to pick a basket of FRUIT (1 x Apple,1 x Orange, 1 x Pear).
Each item in the INVENTORY has a different date for availability. So that...
Apple JANUARY
Apple FEBRUARY
Apple MARCH
Orange APRIL
Apple APRIL
Pear MAY
I don't want to pick the items in the order they appear in the inventory. Instead I want to pick them according to the minimum date range in which all items can be picked. ie Orange & Apple in APRIL and the pear in MAY.
I'm not sure if this is a problem for MYSQL or for some PHP arrays. I'm stumped. Thanks in advance.
If array of fruits isn't already sorted by date, let's sort it.
Now, the simple O(n^2) solution would be to check all possible ranges. Pseudo-code in no particular language:
for (int i = 0; i < inventory.length; ++i)
hash basket = {}
for (int j = i; j < inventory.length; ++j) {
basket.add(inventory[j]);
if (basket.size == 3) { // or whatever's the number of fruits
// found all fruits
// compare range [i, j] with the best range
// update best range, if necessary
break;
}
}
end
You may find it's good enough.
Or you could write a bit more complicated O(n) solution. It's just a sliding window [first, last]. On each step, we move either left border (excluding one fruit from the basket) or right (adding one fruit to the basket).
int first = 0;
int last = 0;
hash count = {};
count[inventory[0]] = 1;
while (true) {
if (count[inventory[first]] > 0) {
--count[inventory[first]];
++first;
} else if (last < inventory.length) {
++last;
++count[inventory[last]];
} else {
break;
}
if (date[last] - date[first] < min_range
&& count.number_of_nonzero_elements == 3) {
// found new best answer
min_range = date[last] - date[first]
}
}
Given you table inventory is structured:
fruit, availability
apple, 3 // apples in march
//user picks the availability month maybe?
$this_month = 5 ;
//or generate it for today
$this_month = date('n') ;
// sql
"select distinct fruit from inventory where availability = $this_month";
Sound quite complicated. The way that I would approach the problem is to group each fruit into its availability month group and see how many are in each group.
JANUARY (1)
FEBRUARY (1)
MARCH (1)
APRIL (2)
MAY (1)
To see that the most fruits fall within APRIL. So APRIL is therefore our preferred month.
I would then remove the items from months with duplicates (Apples in your example), which would remove MARCH as an option. This step could either be done now, or after the next step depending on your data and the results you get.
I would then look at the next most popular month and calculate how far away that month is (eg. JAN is 3 away from APRIL, MARCH is 1 etc). If you then had a tie then it shouldn't matter which you choose. In this example though you would end up choosing the 2 fruits from APRIL and 1 fruit from MAY as you requested.
This approach may not work if the most popular month doesn't actually result in the "best" selection.

Categories