60 lines
1.6 KiB
Elixir
60 lines
1.6 KiB
Elixir
defmodule RangeUtil do
|
|
@spec from_start(integer(), integer()) :: Range.t()
|
|
def from_start(start, len) do
|
|
if len == 0 do
|
|
..
|
|
else
|
|
start..(start + len - 1)
|
|
end
|
|
end
|
|
|
|
def transpose(value, source, dest) do
|
|
offset = value - (source |> Enum.at(0))
|
|
(dest |> Enum.at(0)) + offset
|
|
end
|
|
|
|
@spec contains?(Range.t(), Range.t()) :: boolean
|
|
def contains?(r1, r2) do
|
|
r2.first >= r1.first and r2.last <= r1.last
|
|
end
|
|
|
|
@spec difference(Range.t(), Range.t()) :: [Range.t()]
|
|
def difference(r1, r2) do
|
|
cond do
|
|
Range.disjoint?(r1, r2) ->
|
|
[r1]
|
|
|
|
RangeUtil.contains?(r2, r1) ->
|
|
[]
|
|
|
|
RangeUtil.contains?(r1, r2) ->
|
|
s1_len = r2.first - r1.first
|
|
s2_len = r1.last - r2.last
|
|
|
|
[
|
|
RangeUtil.from_start(r1.first, s1_len),
|
|
RangeUtil.from_start(r2.last + 1, s2_len)
|
|
]
|
|
|> Enum.reject(fn r -> r == .. end)
|
|
|
|
r2.first <= r1.first and r2.last <= r1.last ->
|
|
s1_len = r1.last - r2.last
|
|
[RangeUtil.from_start(r2.last + 1, s1_len)]
|
|
|
|
r2.first >= r1.first and r2.last >= r1.last ->
|
|
s1_len = r2.first - r1.first
|
|
[RangeUtil.from_start(r1.first, s1_len)]
|
|
end
|
|
end
|
|
|
|
@spec intersection(Range.t(), Range.t()) :: Range.t()
|
|
def intersection(r1, r2) do
|
|
cond do
|
|
Range.disjoint?(r1, r2) -> ..
|
|
RangeUtil.contains?(r2, r1) -> r1
|
|
RangeUtil.contains?(r1, r2) -> r2
|
|
r2.first <= r1.first and r2.last <= r1.last -> Range.new(r1.first, r2.last)
|
|
r2.first >= r1.first and r2.last >= r1.last -> Range.new(r2.first, r1.last)
|
|
end
|
|
end
|
|
end
|