Help simplify a map function

Unless you’re certain you won’t need subsecond accuracy and the ranges are small enough, I would not use ranges.

I’ve already solved your challenge twice, so I’m going to be vague and wave my hands at this point. The next level is probably to pull in a library like timex and then you can keep the same basic shape of this solution, but change the if condition to something like if Enum.any?(..., &Timex.Interval.overlaps?(...))

1 Like

For future reference, I’ve adapted Greg’s solution with time being converted to seconds using Time.to_seconds_after_midnight/1, i.e. it works with precision to seconds:

classes = [
  %{id: 1, time: Time.new!(15,00,00), duration: 60}, # 
  %{id: 2, time: Time.new!(16,00,00), duration: 180}, # overlap: true
  %{id: 3, time: Time.new!(17,00,00), duration: 60}, # overlap: true
  %{id: 4, time: Time.new!(18,00,00), duration: 60}, # overlap: true
  %{id: 5, time: Time.new!(19,00,00), duration: 60}, # 
  %{id: 6, time: Time.new!(20,00,00), duration: 120}, # overlap: true
  %{id: 7, time: Time.new!(21,00,00), duration: 60}, # overlap: true
]

ranges = 
  Map.new(classes, fn %{time: t, duration: d, id: id} -> 
    {tsec, _} = Time.to_seconds_after_midnight(t)
    {id, tsec..(tsec + (d * 60) - 1)} 
  end)

Enum.map(classes, fn c ->
   if Enum.all?(classes -- [c], &Range.disjoint?(ranges[c.id], ranges[&1.id])) do
     c
   else
     Map.put(c, :overlap, true)
   end
 end)
|> IO.inspect

I’m not certain but you might be able to utilize: