Ladder Range
July 25, 2017
Once a year, or thereabouts, I pick up Jon Bentley’s book Programming Pearls and read a random chapter; even though I’ve read it before, re-reading always makes the material seem fresh. Today’s exercise is Exercise 7 from Chapter 4 about binary search:
A colleague faced the following problem in a program to draw lines on a bit-mapped display. An array of n pairs of reals (ai, bi) defined the n lines y = mi x +
bi. The lines were ordered in the x-interval [0, 1] in the sense that yi < yi+1 for all values of i between 0 and n − 2 and all values of x in [0, 1].[ Here Bentley has a picture of a ladder with rungs at various angles to the horizontal. We won’t reproduce it here; get the book if you want to see it. ]
Less formally, the lines don’t touch in the vertical slab. Given a point (x, y), where 0 ≤ x ≤ 1, he wanted to determine the two lines that bracket the point. How could he solve the problem quickly?
Your task is to write a program to solve Bentley’s exercise. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
Binary search is where I tend to make the relevant assumptions explicit as comments, as below (in Julia). Otherwise I keep getting something off by one or some condition accidentally reversed.
I had two typos in my test code on the first run. I had also written the test invocations to expect zero-based indexes, so the correct one-based indexes were reported as off-by one on that first run :)
My function returns only the lower-rung index. The corresponding upper-rung index is the next integer.
In Python using the bisect module for the search. As bisect needs a list, the class LazyRungs is used, that behaves like a list and only calculates the y-value when needed.