Created
February 6, 2022 22:40
-
-
Save mayonesa/7d374a06ac75c19156f0813861a5c92f to your computer and use it in GitHub Desktop.
Find the longest period of time when there are no ongoing meetings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math.max | |
/* | |
James is a businessman. He is on a tight schedule this week. The week starts | |
on Monday at 00:00 and ends on Sunday at 24:00. His schedule consists of M | |
meetings he needs to take part in. Each of them will take place in a period of | |
time, beginning and ending on the same day (there are no two ongoing meetings | |
at the same time). James is very tired, thus he needs to find the longest | |
possible time slot to sleep. In other words, he wants to find the longest | |
period of time when there are no ongoing meetings. The sleeping break can | |
begin and end on different days and should begin and end in the same week. | |
You are given a string containing M lines. Each line is a substring | |
representing one meeting in the schedule, in the format "Ddd hh:mm-hh:mm". | |
"Ddd" is a three-letter abbreviation for the day of the week when the meeting | |
takes place: "Mon" (Monday), "Tue", "Wed", "Thu", "Fri", "Sat", "Sun". | |
"hh:mm-hh:mm" means the beginning time and the ending time of the meeting | |
(from 00:00 to 24:00 inclusive). | |
The given times represent exact moments of time. So, there are exactly five | |
minutes between 13:40 and 13:45. | |
For example, given a string: | |
"Sun 10:00-20:00 | |
Fri 05:00-10:00 | |
Fri 16:30-23:50 | |
Sat 10:00-24:00 | |
Sun 01:00-04:00 | |
Sat 02:00-06:00 | |
Tue 03:30-18:15 | |
Tue 19:00-20:00 | |
Wed 04:25-15:14 | |
Wed 15:14-22:40 | |
Thu 00:00-23:59 | |
Mon 05:00-13:00 | |
Mon 15:00-21:00" | |
The longest time slot when James can sleep is 505 minutes, since James can | |
sleep from Tuesday 20:00 to Wednesday 04:25, which gives 8 hours and 25 | |
minutes = 505 minutes. | |
Also, for a string: | |
"Mon 01:00-23:00 | |
Tue 01:00-23:00 | |
Wed 01:00-23:00 | |
Thu 01:00-23:00 | |
Fri 01:00-23:00 | |
Sat 01:00-23:00 | |
Sun 01:00-21:00" | |
James should sleep on Sunday from 21:00 to 24:00 (180 minutes). | |
Write a function: | |
object Solution { def solution(s: String): Int } | |
that, given a string S representing the schedule, returns the length of the | |
longest time slot when James can sleep (in minutes). | |
Assume that: | |
● M is an integer within the range [1..100]; | |
● Each line of the input string is in the format "Ddd hh:mm-hh:mm" and | |
lines are separated with newline characters; | |
● There cannot be two ongoing meetings at any time; | |
● Each meeting lasts at least 1 minute. | |
In your solution, focus on correctness. The performance of your solution will | |
not be the focus of the assessment. | |
*/ | |
object Week { | |
def largestGapInMinutes(s: String): Int = { | |
val startFakeMeeting = new Meeting("Mon 00:00-00:00") | |
val finalGap = new Meeting("Sun 24:00-24:00") | |
val sortedMeetings = startFakeMeeting +: s.linesIterator.map(new Meeting(_)).toSeq.sortBy { meeting => | |
(meeting.dow, meeting.start) | |
} :+ finalGap | |
(1 until sortedMeetings.size).foldLeft(0) { case (largestGapInMinutes, i) => | |
val previousMeeting = sortedMeetings(i - 1) | |
val meeting = sortedMeetings(i) | |
val gap = meeting.gapInMinutes(previousMeeting) | |
max(largestGapInMinutes, gap) | |
} | |
} | |
} | |
import Meeting._ | |
import java.time.DayOfWeek | |
import java.util.Date | |
import java.util.concurrent.TimeUnit | |
import TimeUnit.{MINUTES => Minutes} | |
import TimeUnit.{DAYS => Days} | |
import TimeUnit.{MILLISECONDS => Milliseconds} | |
class Meeting(slot: String) { | |
private val (startStr, endRaw) = slot.splitAt(DashI) | |
private val (dowShort, startTimeStrRaw) = startStr.splitAt(DowI) | |
private val startTimeStr = startTimeStrRaw.tail | |
private val endStr = endRaw.tail | |
val dow: DayOfWeek = DowFromShort(dowShort) | |
val start: Date = TimeFormat.parse(startTimeStr) | |
val end: Date = TimeFormat.parse(endStr) | |
def gapInMinutes(previous: Meeting): Int = { | |
def diffInMinutes(f: Meeting => Long, previousF: Meeting => Long, timeUnit: TimeUnit) = | |
Minutes.convert(f(this) - previousF(previous), timeUnit).toInt | |
val dayDiffF: Meeting => Long = _.dow.getValue | |
val dayDiffInMinutes = diffInMinutes(dayDiffF, dayDiffF, Days) | |
val timeDiffInMinutes = diffInMinutes(_.start.getTime, _.end.getTime, Milliseconds) | |
dayDiffInMinutes + timeDiffInMinutes | |
} | |
override def toString: String = slot | |
} | |
import java.text.SimpleDateFormat | |
object Meeting { | |
private val DashI = 9 | |
private val DowI = 3 | |
private val TimeFormat = new SimpleDateFormat("HH:mm") | |
private val DowFromShort = DayOfWeek.values.map { dow => | |
val allCapsShort = dow.name.take(3) | |
allCapsShort.head + allCapsShort.drop(1).toLowerCase -> dow | |
}.toMap | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.scalatest.flatspec.AnyFlatSpec | |
class WeekSpec extends AnyFlatSpec { | |
"nominal sched" should "work" in { | |
val meetings = """Sun 10:00-20:00 | |
|Fri 05:00-10:00 | |
|Fri 16:30-23:50 | |
|Sat 10:00-24:00 | |
|Sun 01:00-04:00 | |
|Sat 02:00-06:00 | |
|Tue 03:30-18:15 | |
|Tue 19:00-20:00 | |
|Wed 04:25-15:14 | |
|Wed 15:14-22:40 | |
|Thu 00:00-23:59 | |
|Mon 05:00-13:00 | |
|Mon 15:00-21:00""".stripMargin | |
assert(Week.largestGapInMinutes(meetings) === 505) | |
} | |
"last gap (it is the largest)" should "be chosen" in { | |
val meetings = """Mon 01:00-23:00 | |
|Tue 01:00-23:00 | |
|Wed 01:00-23:00 | |
|Thu 01:00-23:00 | |
|Fri 01:00-23:00 | |
|Sat 01:00-23:00 | |
|Sun 01:00-21:00""".stripMargin | |
assert(Week.largestGapInMinutes(meetings) === 180) | |
} | |
"initial gap (it is the largest)" should "be chosen" in { | |
val meetings = """Tue 01:00-23:00 | |
|Wed 01:00-23:00 | |
|Thu 01:00-23:00 | |
|Fri 01:00-23:00 | |
|Sat 01:00-23:00 | |
|Sun 01:00-21:00""".stripMargin | |
assert(Week.largestGapInMinutes(meetings) === 1500) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Java Code:
`import static java.util.stream.Collectors.groupingBy;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
class Scratch {
private static int findMaxSleepMinutes(String s) {
var weekOrder = List.of("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
var map = s.lines().collect(groupingBy(day -> day.substring(0, 3).toUpperCase()));
var sortedMeetings = sortAllMeetingsOfWeek(weekOrder, map);
var minutes = 0;
for (int i = 1; i < sortedMeetings.size(); i++) {
var currentMeeting = sortedMeetings.get(i);
var previousMeeting = sortedMeetings.get(i - 1);
minutes = Math.max(minutes, getMinutes(currentMeeting, previousMeeting));
if (i == weekOrder.size() - 1) {
minutes = Math.max(minutes, getMinutes("00:00-00:00", currentMeeting));
}
}
return minutes;
}
private static List sortAllMeetingsOfWeek(List weekOrder,
Map<String, List> map) {
var meetings = new ArrayList();
weekOrder.stream().map(String::toUpperCase).forEach(day -> {
if (map.containsKey(day)) {
var dayMeetings = map.get(day);
meetings.addAll(
dayMeetings.stream().map(meeting -> meeting.substring(4)).sorted().toList());
}
});
return meetings;
}
private static int getMinutes(String current, String previous) {
var endTimes = previous.substring(previous.indexOf("-") + 1).split(":");
var endHour = Integer.parseInt(endTimes[0]);
var localTime = LocalTime.parse(current.substring(0, current.indexOf("-"))).minusHours(endHour)
.minusMinutes(Integer.parseInt(endTimes[1]));
return localTime.getHour() * 60 + localTime.getMinute();
}
public static void main(String[] args) {
var input = List.of(
"Sun 10:00-20:00\n"
+ "Fri 05:00-10:00\n"
+ "Fri 16:30-23:50\n"
+ "Sat 10:00-24:00\n"
+ "Sun 01:00-04:00\n"
+ "Sat 02:00-06:00\n"
+ "Tue 03:30-18:15\n"
+ "Tue 19:00-20:00\n"
+ "Wed 04:25-15:14\n"
+ "Wed 15:14-22:40\n"
+ "Thu 00:00-23:59\n"
+ "Mon 05:00-13:00\n"
+ "Mon 15:00-21:00",
"Mon 01:00-23:00\n"
+ "Tue 01:00-23:00\n"
+ "Wed 01:00-23:00\n"
+ "Thu 01:00-23:00\n"
+ "Fri 01:00-23:00\n"
+ "Sat 01:00-23:00\n"
+ "Sun 01:00-21:00"
);
input.forEach(s -> System.out.println(findMaxSleepMinutes(s)));
}
}`