(The misnumbering in my printed copy continues, and these wrongly appear as questions 10-13.)
#9. Trivially,
data Direction = LeftTurn | RightTurn | Straight
deriving (Show)I'd use Left and Right, except that there already are constructors of these names defined in Prelude, and the book hasn't yet discussed how to deal with such conflicts.
#10. If the question seems unclear, think of it this way: you're driving from point p1 to point p2; it's a straight line. Now, you have to reach point p3. Do you drive straight on, make a left turn, or make a right turn?
At first it seems this requires lots of trigonometrics to solve, but in fact, there's a simple formula that yields the required result, based on the sign (negative, positive, or zero) of the two vectors defined by the two path segments (p1 to p2 and p2 to p3):
data Point = Point { x :: Double, y :: Double }
deriving (Show)
turn :: Point -> Point -> Point -> Direction
turn p1 p2 p3 | prod > 0 = LeftTurn
| prod < 0 = RightTurn
| otherwise = Straight
where prod = ((x(p2) - x(p1)) * (y(p3) - y(p1))) -
((y(p2) - y(p1)) * (x(p3) - x(p1)))#11. The trick is to define a pattern that extracts the three leading elements of the list. And remember, when progressing to the next step, that you keep two out of these three (rather than considereding all three as "processed").
directions :: [Point] -> [Direction] directions ps | length ps < 3 = [] directions (p1:p2:p3:ps) = turn p1 p2 p3 : directions (p2:p3:ps)
#12. This is where I draw the line (no pun intended) -- this is too much math before breakfast for me. I might come back to this question later.
4 comments: