Real World Haskell
実戦で学ぶ関数型言語プログラミング
(オライリージャパン)
Bryan O'Sullivan (著) John Goerzen (著)
Don Stewart (著)
山下 伸夫 (翻訳) 伊東 勝利 (翻訳)
株式会社タイムインターメディア (翻訳)
開発環境
- OS X Mavericks - Apple(OS)
- BBEdit - Bare Bones Software, Inc., Emacs (Text Editor)
- Haskell (純粋関数型プログラミング言語)
- GHC (The Glasgow Haskell Compiler) (処理系)
- The Haskell Platform (インストール方法、モジュール等)
Real World Haskell―実戦で学ぶ関数型言語プログラミング(Bryan O'Sullivan (著)、 John Goerzen (著)、 Don Stewart (著)、山下 伸夫 (翻訳)、伊東 勝利 (翻訳)、株式会社タイムインターメディア (翻訳)、オライリージャパン)の3章(型を定義し、関数を単純化する)、3.13(ガードの条件節の評価)、練習問題 12.を解いてみる。
その他参考書籍
- すごいHaskellたのしく学ぼう!(オーム社) Miran Lipovača(著)、田中 英行、村主 崇行(翻訳)
- プログラミングHaskell (オーム社) Graham Hutton(著) 山本 和彦(翻訳)
練習問題 12.
コード(BBEdit)
Sample.hs
{-# OPTIONS -Wall -Werror #-}
module GrahamScan where
import qualified Data.List as List
type Point = (Double, Double)
data Direction = LeftTurn | Collinear | RightTurn
deriving (Show, Eq)
grahamScan :: [Point] -> [Point]
grahamScan ps = let p = findLowestPoint ps
ps' = sortPoints p ps
in grahamScanRecursive p ps'
grahamScanRecursive :: Point -> [Point] -> [Point]
grahamScanRecursive p (a:b:[])
| d == LeftTurn = [a, b]
| d == Collinear = [b]
where d = getDirection a b p
grahamScanRecursive p (a:b:c:ps)
| a == b = grahamScanRecursive p (a:c:ps)
| a == c = grahamScanRecursive p (a:ps)
| b == c = grahamScanRecursive p (a:b:ps)
| d == LeftTurn = a:grahamScanRecursive p (b:c:ps)
| otherwise = grahamScanRecursive p (a:c:ps)
where d = getDirection a b c
grahamScanRecursive _ _ = undefined
findLowestPoint :: [Point] -> Point
findLowestPoint = foldr1 lowerPoint
lowerPoint :: Point -> Point -> Point
lowerPoint (a, b) (c, d)
| b < d = (a, b)
| b > d = (c, d)
| a < c = (a, b)
| otherwise = (c, d)
sortPoints :: Point -> [Point] -> [Point]
sortPoints p = List.sortBy (comparePoint p)
comparePoint :: Point -> Point -> Point -> Ordering
comparePoint p a b
| a == b = EQ
| t > 0 = LT
| t < 0 = GT
| fst a < fst b = LT
| otherwise = GT
where t = cow p a b
getDirections :: [Point] -> [Direction]
getDirections (a:b:c:xs) = getDirection a b c:getDirections (b:c:xs)
getDirections _ = []
getDirection :: Point -> Point -> Point -> Direction
getDirection a b c
| t > 0 = LeftTurn
| t < 0 = RightTurn
| otherwise = Collinear
where t = cow a b c
cow :: Point -> Point -> Point -> Double
cow (x1, y1) (x2, y2) (x3, y3) = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)
kernel :: Point
kernel = (0.0, 0.0)
test :: [Point]
test = [
kernel, (1.0, 0.0), kernel, (1.0, 1.0), kernel, (0.0, 1.0), kernel,
(-1.0, 1.0), kernel, (-1.0, 0), kernel, (-1.0, -1.0), kernel, (0.0, -1.0),
kernel, (1.0, -1.0)]
入出力結果(Terminal, インタプリタghci)
$ ghci GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> :load GrahamScan.hs [1 of 1] Compiling GrahamScan ( GrahamScan.hs, interpreted ) Ok, modules loaded: GrahamScan. *GrahamScan> let a = grahamScan test *GrahamScan> a [(-1.0,-1.0),(1.0,-1.0),(1.0,0.0),(1.0,1.0),(0.0,1.0),(-1.0,1.0)] *GrahamScan> getDirections a [LeftTurn,Collinear,LeftTurn,Collinear] *GrahamScan> :quit Leaving GHCi. $
0 コメント:
コメントを投稿