Skip to content

Instantly share code, notes, and snippets.

@mayonesa
Last active February 4, 2022 17:26
Show Gist options
  • Save mayonesa/c9dff6d4980a5884ad870b43cc14a843 to your computer and use it in GitHub Desktop.
Save mayonesa/c9dff6d4980a5884ad870b43cc14a843 to your computer and use it in GitHub Desktop.
Given individual schedules and the endpoints of time, it will return all the free times.
import scala.collection.parallel.immutable.ParRange
import scala.collection.GenSeq
object Solution extends App {
private val NoTimes = Seq.empty[(Int, Int)]
private val NoStart = Option.empty[Int]
private val StdListStart = "["
private val StdListEnd = "]"
private val Sample = (-5, 60, Seq(Seq((0, 5), (15, 30), (45, 60)), Seq((5, 15), (30, 40))))
private val stdin = "" // """\[(\d+), (\d+)\]""".r
private val (start, end, schedules) = Sample
private def markBusy(acc: Vector[Boolean], time: (Int, Int)) = {
val (s, e) = time
val patchSize = e - s
val busyPatch = Vector.fill(patchSize)(false)
val i = s - start
acc patch (i, busyPatch, patchSize)
}
private def freePerSched(acc: Vector[Boolean], sched: Seq[(Int, Int)]) = sched.foldLeft(acc)(markBusy)
// adds falsehoods on both ends to properly downstream-process potential boolean transitions
private def bookend(xs: GenSeq[(Int, Boolean)]) = (start - 1, false) +: xs :+ (end, false)
private def toFreeInterval(accAndLastStartOpt: (Seq[(Int, Int)], Option[Int]),
timeAndFree: (Int, Boolean)) = {
val (acc, lastStartOpt) = accAndLastStartOpt
val (time, free) = timeAndFree
lastStartOpt match {
case Some(lastStart) =>
if (free) (acc, lastStartOpt)
else (acc :+ (lastStart, time), NoStart)
case _ =>
if (free) (acc, Option(time))
else (acc, NoStart)
}
}
private val nTimes = end - start
private val freeMask = Vector.fill(nTimes)(true)
private val freeIndicator = schedules.foldLeft(freeMask)(freePerSched)
private val timesInParallel = ParRange(0, nTimes, 1, false)
private val freeTimeAggs = timesInParallel map { i =>
val startTime = i + start
(startTime, freeIndicator(i))
}
private val intervalReadyFreeTimes = bookend(freeTimeAggs)
private val freeIntervals = (intervalReadyFreeTimes.foldLeft((NoTimes, NoStart))(toFreeInterval))._1
println(StdListStart + (freeIntervals mkString " ") + StdListEnd)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment