I used ranges as well. Part 1 and 2 are basically contains? and overlaps? for ranges. Did the first on my own, for part 2 Range.disjoint? is the opposite to overlaps?, so it does the job. Contains can be checked just by looking at the edges of the ranges.
Solution
defmodule Day4 do
def sum_number_of_contained_assignments(text) do
text
|> String.split("\n")
|> Enum.reject(&(&1 == ""))
|> Enum.filter(&contained_assignments?/1)
|> length()
end
def sum_number_of_overlapping_assignments(text) do
text
|> String.split("\n")
|> Enum.reject(&(&1 == ""))
|> Enum.filter(&overlapping_assignments?/1)
|> length()
end
defp contained_assignments?(assignments) do
{elf_a_range, elf_b_range} = parse_pair_ranges(assignments)
contains?(elf_a_range, elf_b_range) or contains?(elf_b_range, elf_a_range)
end
defp overlapping_assignments?(assignments) do
{elf_a_range, elf_b_range} = parse_pair_ranges(assignments)
!Range.disjoint?(elf_a_range, elf_b_range)
end
defp parse_pair_ranges(assignments) do
[elf_a_assignment, elf_b_assignment] = String.split(assignments, ",", trim: true, parts: 2)
elf_a_range = to_range(elf_a_assignment)
elf_b_range = to_range(elf_b_assignment)
{elf_a_range, elf_b_range}
end
defp to_range(assignment) do
[from, to] = String.split(assignment, "-", trim: true, parts: 2)
from_int = String.to_integer(from)
to_int = String.to_integer(to)
from_int..to_int//1
end
defp contains?(fa..ta//1, fb..tb//1) do
fa <= fb and ta >= tb
end
end






















