import Data.Ratio main :: IO () main = mapM_ printIntersection ls where ls = [ (((0, 8), (4, 0)), ((2, 4), (8, 12))) , (((0, 0), (4, 6)), ((0, 0), (7, 15))) , (((0, 0), (1, 2)), ((1, 1), (2, 3))) , (((-9, -9), (9, 9)), ((5, 0), (5, 7))) , (((3, 4), (6, 7)), ((3, 8), (9, -1))) , (((-1, 0), (4, 18)), ((-2, -5), (1, 3))) ] printIntersection :: ((Point, Point), (Point, Point)) -> IO () printIntersection (l, m) = putStrLn s where s = if not (onSegment l && onSegment m) || any isNaN [x, y] then "交点なし" else show (x, y) (x, y) = intersection (uncurry line l) (uncurry line m) onSegment ((x1, y1), (x2, y2)) = checkX && checkY where checkX = cmp (if x1 <= x2 then (<=) else (>=)) [x1, x, x2] checkY = cmp (if y1 <= y2 then (<=) else (>=)) [y1, y, y2] cmp f = and . (flip (zipWith f) =<< tail) 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, 0) 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 == a = c * x + q | 0 == c = 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