Skip to content

Instantly share code, notes, and snippets.

@mayonesa
Created February 6, 2022 22:40
Show Gist options
  • Save mayonesa/7d374a06ac75c19156f0813861a5c92f to your computer and use it in GitHub Desktop.
Save mayonesa/7d374a06ac75c19156f0813861a5c92f to your computer and use it in GitHub Desktop.
Find the longest period of time when there are no ongoing meetings
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
}
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)
}
}
@manu828
Copy link

manu828 commented Nov 16, 2024

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

}`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment