Collecting Signatures
General Problem
Find the minimum number of points needed to cover all given segments on a line.
Input | A sequence of \(n\) segments \([a_1, b_1],\ldots[a_n, b_n]\) on a line |
Output | A set of points of minimum size such that each segment contains a point |
The Concrete Problem
You have to collect signatures from the tenants in the building. You know the times each tenant will be in the building (represented by the segments in the problem) and you want to minimize the number of visits and time spent at the building. Assume that the actual visit with the tenant will take no time.
In other words, we have a bunch of line segments that may or may not overlap. We want to minimize the number of segments
Input | \(n\), the number of segments, each following line is made of two points tha define a line segment \(a_i, b_i\) |
Output | The minimum number \(m\) of points needed, followed by the integer values for each of the points |
Constraints | \(1 \le n \le 100; 0 \le a_i \le b_i \le 10^9\) for all i |
Sample Inputs
Sample One
Input:
3 1 3 2 5 3 6
Output:
1 3
Note that the way the code is setup, the first input value isn't relevant to our solver.
Sample Two
Input:
4 4 7 1 3 2 5 5 6
Output:
2 3 6
Implementation
Imports
# from pypi
from expects import (
equal,
expect,
)
Overlapping
First, what does it mean to say that two segments overlap? Let's say we have two segments. They won't overlap if:
- the first segment's rightmost point is to the left of the other segment's leftmost point
- the second segment's rightmost point is to the left of the other segment's leftmost point
So they won't overlap if:
\[ R_0 < L_1 \lor L_0 > R_1 \]
Where \(R\) means the rightmost point for that segment and \(L\) means the leftmost point of that segment (and the first segment is \(0\) and the second one is \(1\)). To find where they do overlap we can negate the inequality.
\[ \neg (R_0 < L_1 \lor L_0 > R_1) = R_0 \le L_1 \land L_0 \le R_1 \]
Python functions are expensive, but to make it clearer I'll create a function to test for overlapping and if the final solution is too small I won't use it.
The Schedule
def schedule(schedules):
"""Finds the times to visit
Args:
schedules (list): list of times people are available
Returns:
list: times to visit
"""
return
Testing
SAMPLES = dict(
one=dict(
inputs=[(1,3), (2, 5), (3, 6)],
outputs=[3],
),
two=dict(
inputs=[(4, 7), (1, 3), (2, 5), (5, 6)],
outputs=[3, 6],
)
)
class SampleKeys:
inputs = "inputs"
expected = "outputs"
for sample, values in SAMPLES.items():
actual = schedule(values[SampleKeys.inputs])
expect(actual).to(equal(values[SampleKeys.expected]))