import Data.Ratio main :: IO () main = mapM_ printIntersection ls where ls = [ (line (0, 8) (4, 0), line (2, 4) (8, 12)) , (line (0, 0) (1, 2), line (1, 1) (2, 3)) , (line (-9, -9) (1, 1), line (5, 0) (5, 3)) , (line (3, 4) (6, 7), line (3, 8) (9, -1)) ] printIntersection :: (Line, Line) -> IO () printIntersection (l, m) = putStrLn s where s | any isNaN [x, y] = "交点なし" | otherwise = show (x, y) (x, y) = intersection l m type Point = (Double, Double) type Line = (Ratio Integer, Ratio Integer, Ratio Integer) line :: Point -> Point -> Line line (x1, y1) (x2, y2) | dx /= 0 = (toRational slope, - 1, toRational $ slope * x1 - y1) | dx == 0 = (1, 0, toRational x1) | otherwise = (0, 0, toRational x1) where slope = dy / dx dx = x2 - x1 dy = y2 - y1 intersection :: Line -> Line -> Point intersection l@(a, b, p) m@(c, d, q) | not $ parallel l m = (fromRational x, fromRational y) | otherwise = (nan, nan) where x = invd * p + invb * q y | 0 `elem` [a, b] = c * x + q | 0 `elem` [c, d] = a * x + p | otherwise = invc * p + inva * q [inva, invb, invc, invd] = map (/ det l m) [a, -b, -c, d] nan :: Double nan = 0 / 0 parallel :: Line -> Line -> Bool parallel l m = det l m == (0 % 1) det :: Line -> Line -> Ratio Integer det (a, b, _) (c, d, _) = a * d - b * c