29 June, 2006

[Haskell] Exercise 3.18, 3.19

Exercise 3.18は省略。(いやまぁ奇麗に書き直すべきものがあるような気もするが...)
Exercise 3.19は下記のようになった。

funny x = x+x
peculiar y = y

Hugs.Base> :load 319.hs
ERROR "319.hs":2 - Syntax error in input (unexpected `=')
Main> :q

funny x = x+x
peculiar y = y

Hugs.Base> :load 319
Main> :q

前者では、
funny x = x+x peculiar y = y
という、=の2つある式になっているということか。

[Haskell] Exercise 3.15, 3.16, 3.17

guardとwhereのレイアウトに注意。whereがguardに従属すると判る様にインデントを深くすること。

numberNDroot :: Float -> Float -> Float -> Int
numberNDroot a b c
| d > 0 = 2
| d == 0 = 1
| d < 0 = 0
where
d = b * b - 4.0 * a * c

Main> numberNDroot 1.0 2.0 0.0
2
Main> numberNDroot 1.0 2.0 1.0
1
Main> numberNDroot 1.0 1.0 1.0
0
Main>

これを使って書く。guardでマッチすると抜けるので、高次の係数の非零から調べれば良い。

numberRoots :: Float -> Float -> Float -> Int
numberRoots a b c
| a /= 0.0 = numberNDroots a b c -- non-degenerate eq.
| b /= 0.0 = 1 -- eq. bx+c=0
| c /= 0.0 = 0 -- eq. c=0 -> no x satisfy the eq.
| otherwise = 3 -- a=b=c=0 -> all x satisfy the eq.

Main> numberRoots 1.0 2.0 0.0
2
Main> numberRoots 1.0 2.0 1.0
1
Main> numberRoots 1.0 2.0 0.0
2
Main> numberRoots 0.0 2.0 1.0
1
Main> numberRoots 0.0 0.0 1.0
0
Main> numberRoots 0.0 0.0 0.0
3
Main>

上記を使って解の個数に応じて解を求める。
ちょっと工夫したところは、bの符号に応じて片方だけ求めて、解と係数の関係 αβ = - c/a を使うところ。加減算での桁落ちを防ぐため。

smallerRoot :: Float -> Float -> Float -> Float
smallerRoot a b c
| numberRoots a b c == 0 = 0.0
| numberRoots a b c == 3 = 0.0
| a == 0.0 = -(c/b)
| b >= 0 = (-b - sqrt d) / 2.0 / a
| otherwise = c / a / (largerRoot a b c)
where d = b * b - 4.0 * a * c

largerRoot :: Float -> Float -> Float -> Float
largerRoot a b c
| numberRoots a b c == 0 = 0.0
| numberRoots a b c == 3 = 0.0
| a == 0.0 = -(c/b)
| b <= 0 = (-b + sqrt d) / 2.0 / a
| otherwise = c / a / (smallerRoot a b c)
where d = b * b - 4.0 * a * c

Main> largerRoot 0.0 0.0 0.0
0.0
Main> largerRoot 0.0 0.0 1.0
0.0
Main> largerRoot 0.0 1.0 1.0
-1.0
Main> largerRoot 1.0 1.0 1.0
0.0
Main> largerRoot 1.0 0.0 (-1.0)
1.0
Main> smallerRoot 0.0 0.0 0.0
0.0
Main> smallerRoot 0.0 0.0 1.0
0.0
Main> smallerRoot 0.0 1.0 1.0
-1.0
Main> smallerRoot 1.0 1.0 1.0
0.0
Main> smallerRoot 1.0 0.0 (-1.0)
-1.0
Main> largerRoot 1.0 (-1.0) 0.0000000000000001
1.0
Main> smallerRoot 1.0 (-1.0) 0.0000000000000001
1.0e-16
Main>

[Haskell] Guards, if-then-else, and Case Expression

Haskell 学習メモ: Boolean Guard, Case Expression, Conditional Expressionより。


sign1 :: Int -> Int
sign1 x | x > 0 = 1
| x == 0 = 0
| otherwise = -1

-- 真となるガードがない場合、次の等式へ。
sign2 :: Int -> Int
sign2 x | x > 0 = 1
| x == 0 = 0
sign2 _ = -1

sign3 :: Int -> Int
sign3 x = case (x > 0) of
True -> 1
False -> case (x == 0) of
True -> 0
False -> -1

sign4 :: Int -> Int
sign4 x = if (x > 0) then 1
else if (x == 0) then 0
else -1


次の演習問題用にGuardをネストして書きたい場合はどうすれば良いのだろうと思って探していたら見つけた。
当たり前だが、caseとかifで書けばいいのか。

あと、3. 関数を定義するHaskell のお勉強でも同様の書き方を学べる。
こちらでは、

shot_putting1 v0 angle = vx * t
where r = angle * pi / 180.0
vx = v0 * cos r
vy = v0 * sin r
t = 2 * vy / 9.8

と、補助関数(これが普通の言語なら補助のlocal変数と思うところだが)という書き方も見つけた。便利。
このサイトの他の記事も、最小二乗法とか探索の書き方とか、勉強になる。

[Haskell] Exercise 3.14

教科書には fromInt :: Int -> Float があると書いてあるのだが無いので仕方なく定義する。
平均以上の個数だが、全部等しければ0個で、3個というのはあり得ないので、0個でも2個でも無ければ1個。

fromInt :: Int -> Float
fromInt x = fromInteger (toInteger x)

averageThree :: Int -> Int -> Int -> Float
averageThree x y z = fromInt (x + y + z) / 3.0

howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage x y z
| (x==y) && (y==z) = 0
| (fromInt x > averageThree x y z) && (fromInt y > averageThree x y z) = 2
| (fromInt y > averageThree x y z) && (fromInt z > averageThree x y z) = 2
| (fromInt z > averageThree x y z) && (fromInt x > averageThree x y z) = 2
| otherwise = 1

Main> averageThree 1 2 3
2.0
Main> averageThree 3 3 4
3.333333
Main> howManyAboveAverage 3 3 4
1
Main> howManyAboveAverage 3 4 4
2
Main> howManyAboveAverage 3 3 3
0
Main> howManyAboveAverage 1 2 3
1

リストはまだ教科書には出てこないが、これを使うと簡潔に書ける。

howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage x y z = length $ filter (\w -> fromInt w > averageThree x y z) [x,y,z]

Main> howManyAboveAverage 3 3 4
1
Main> howManyAboveAverage 3 4 4
2
Main> howManyAboveAverage 3 3 3
0
Main> howManyAboveAverage 1 2 3
1
Main>

28 June, 2006

[Haskell] Exercise 3.12, 3.13

hugsもghciも、Charをimportしないと、ordが無いと言うのでimportする。
但し、toUpperもCharには当然入っているようだが。

import Char
toupper :: Char -> Char
toupper c
| ('a' <= c) && (c <= 'z') = chr ( ord c + ord 'A' - ord 'a')
| otherwise = c

Main> toupper 'h'
'H'
Main> toupper 'F'
'F'
Main> toupper '%'
'%'
Main>

同様に Exercise 3.13。

import Char
charToNum :: Char -> Int
charToNum c
| ('0' <= c) && (c <= '9') = ord c - ord '0'
| otherwise = 0

Main> charToNum '8'
8
Main> charToNum 'j'
0
Main>

[Haskell] Exercise 3.10, 3.11


import Prelude hiding (max,min)
max :: Int -> Int -> Int
max x y
| x >= y = x
| otherwise = y
maxThree :: Int -> Int -> Int -> Int
maxThree x y z
| x >= y && x >= z = x
| y >= z = y
| otherwise = z
min:: Int -> Int -> Int
min x y
| x <= y = x
| otherwise = y
minThree :: Int -> Int -> Int -> Int
minThree x y z
| x <= y && x <= z = x
| y <= z = y
| otherwise = z

Main> :type max
max :: Int -> Int -> Int
Main> max (3-2) (3*8)
24
Main> maxThree (4+5) (2*6) (100 `div` 7)
14
Main>

max (3-2) (3*8)
x >= y = x をテスト
(3-2) >= (3*8)
1 >= 24
False
otherwise y にマッチ
24

maxThree (4+5) (2*6) (100 `div` 7)
x >=y && x>=z = xをテスト
(4+5) >= (2*6) && (4+5) >= (100 `div` 7)
9 >= 12 && 9 >= 14
False && False
y >= z = yをテスト
(2*6) >= (100 `div` 7)
12 >= 14
False
otherwise = zにマッチ
14

27 June, 2006

[Haskell] Exercise 3.6 - 3.9

●Excercise 3.6

mystery :: Int -> Int -> Int -> Bool
mystery m n p = not ((m == n) && (n==p))

Main> mystery 1 1 1
False
Main> mystery 1 1 2
True
Main> mystery 1 2 1
True
Main> mystery 2 1 1
True
Main> mystery 1 2 3
True
Main>

m, n, p が等しい場合だけFalseで他はTrue。

● Exercise 3.7

threeDifferent :: Int -> Int -> Int -> Bool
threeDifferent m n p = (m /= n) && (n /= p) && (p /= m)

Main> threeDifferent 1 2 3
True
Main> threeDifferent 1 2 1
False
Main> threeDifferent 1 1 2
False
Main> threeDifferent 2 1 1
False
Main> threeDifferent 1 1 1
False
Main> threeDifferent 3 4 3
False

threeDifferent 3 4 3
= (3 /= 4) && (4 /= 3) && (3 /= 3)
= True && (4 /= 3) && (3 /= 3)
= (4 /= 3) && (3 /= 3)
= True && (3 /= 3)
= (3 /= 3)
= False

●Exercise 3.8
threeEqualsを真似て。

fourEqual :: Int -> Int -> Int -> Int -> Bool
fourEqual m n p q = (m==n) && (n==p) && (p==q)

threeEqualsを用いて。

threeEquals :: Int -> Int -> Int -> Bool
threeEquals m n p = (m==n) && (n==p)

fourEquals :: Int -> Int -> Int -> Int -> Bool
fourEquals m n p q = (threeEquals m n p) && (p==q)


●Exercise 3.9
評価する箇所をイタリックで書くと、
threeEquals (2+3) 5 (11 `div` 2)
= ((2+3) == 5) && (5 == (11 `div` 2)) && ((11 `div` 2) == (2+3))
= (5 == 5) && (5 == (11 `div` 2)) && ((11 `div` 2) == 5)
= True && (5 == (11 `div` 2)) && ((11 `div` 2) == 5)
= (5 == (11 `div` 2)) && ((11 `div` 2) == 5)
= (5 == 5) && (5 == 5)
= True && (5==5)
= (5==5)
= True
のような感じか。他は省略。

Main> threeEquals (2+3) 5 (11 `div` 2)
True
Main> mystery (2+3) 5 (11 `div` 2)
False
Main> threeDifferent (2+3) 5 (11 `div` 2)
False
Main> fourEqual (2+3) 5 (11 `div` 2) (21 `mod` 11)
False

[Event] Lightweight Language Ring Ticket

Lightweight Language Ring

 今週からチケット発売という事で、とりあえずチケットを買いました。
 この手のイベントへは初参加なのだが、楽しめるといいなぁ。

25 June, 2006

[Haskell] Exercise 3.4, 3.5

ex34.hsを作成。~(A && B) = ~A || ~B なので

nAnd :: Bool -> Bool -> Bool
nAnd x y = not (x && y)

nAnd2 :: Bool -> Bool -> Bool
nAnd2 x y = (not x) || (not y)

*Main> nAnd True True
False
*Main> nAnd True False
True
*Main> nAnd False True
True
*Main> nAnd False False
True
*Main> nAnd2 True True
False
*Main> nAnd2 True False
True
*Main> nAnd2 False True
True
*Main> nAnd2 False False
True
*Main>

次に計算過程を手で書く。実は (||) がどういう実装になっているか次第だが、疑似コードで
x || y = if (x) then {return True} else {return y}
だと仮定すると、遅延評価であることを考えると、

nAnd True True = not (True && True) = not True = False
nAnd True False = not (True && False) = not False = True

nAnd2 True True = (not True) || (not True) = False || (not True) = not True = False
nAnd True False = (not True) || (not False) = False || (not False) = not False = True

となるのではなかろうか。

[Haskell] Exercise 3.3

ex33.hsを作成。

exOr :: Bool -> Bool -> Bool
exOr True True = False
exOr True False = True
exOr False True = True
exOr False False = False

*Main> exOr True True
False
*Main> exOr True False
True
*Main> exOr False True
True
*Main> exOr False False
False
*Main>

[Haskell] Exercise 3.1, 3.2

ex31.hs に下記の様に定義

exOr :: Bool -> Bool -> Bool
exOr x y = (x && not y) || (not x && y)

*Main> exOr True True
False
*Main> exOr True False
True
*Main> exOr False True
True
*Main> exOr False False
False
*Main>

Exercise 3.2は上記コードの図を書くのだが自明と思うので省略する。

[Haskell] Hugs on MacOSX

 Hugs を MacOSX にインストールする方法。

 DarwinPortsをインストールしてから、Hugsをインストールすることに。詳しくは DarwinPorts 1.0 : Mac OS X Software Install Memoを参照。

[Haskell] Exercise 2.5

良い絵を考えるのも面倒なので教科書の例をそのまま作ってみる。例によってUsePictures.hsに追記。

-- Ex2.5
ex25 :: Picture -> Picture
ex25 p = checkerH (above p ((flipH . invertColour) p))

*UsePictures> printPicture (ex25 horse)
.......##...#######..###
.....##..#..#####..##.##
...##.....#.###..#####.#
..#.......#.##.#######.#
..#...#...#.##.###.###.#
..#...###.#.##.###...#.#
.#....#..##.#.####.##..#
..#...#.....##.###.#####
...#...#....###.###.####
....#..#....####.##.####
.....#.#....#####.#.####
......##....######..####
######..####......##....
#####.#.####.....#.#....
####.##.####....#..#....
###.###.####...#...#....
##.###.#####..#...#.....
#.####.##..#.#....#..##.
##.###...#.#..#...###.#.
##.###.###.#..#...#...#.
##.#######.#..#.......#.
###..#####.#...##.....#.
#####..##.##.....##..#..
#######..###.......##...
*UsePictures>

[Haskell] Exercise 2.4

1つ目:Exercise 2.3で作ったchecker22でOK。

*UsePictures> printPicture (checker22 horse)
.......##...#######..###
.....##..#..#####..##.##
...##.....#.###..#####.#
..#.......#.##.#######.#
..#...#...#.##.###.###.#
..#...###.#.##.###...#.#
.#....#..##.#.####.##..#
..#...#.....##.###.#####
...#...#....###.###.####
....#..#....####.##.####
.....#.#....#####.#.####
......##....######..####
#######..###.......##...
#####..##.##.....##..#..
###..#####.#...##.....#.
##.#######.#..#.......#.
##.###.###.#..#...#...#.
##.###...#.#..#...###.#.
#.####.##..#.#....#..##.
##.###.#####..#...#.....
###.###.####...#...#....
####.##.####....#..#....
#####.#.####.....#.#....
######..####......##....
*UsePictures>

2つ目と3つ目:horseから目的の絵を作る関数ex242, ex243をUsePictures.hsに追記。

-- Ex2.4
ex242, ex243 :: Picture -> Picture
ex242 p = checkerH (above p ((flipV . invertColour) p))
ex243 p = checkerH (above p ((rotate . invertColour) p))

結果。

*UsePictures> printPicture (ex242 horse)
.......##...#######..###
.....##..#..#####..##.##
...##.....#.###..#####.#
..#.......#.##.#######.#
..#...#...#.##.###.###.#
..#...###.#.##.###...#.#
.#....#..##.#.####.##..#
..#...#.....##.###.#####
...#...#....###.###.####
....#..#....####.##.####
.....#.#....#####.#.####
......##....######..####
###..#######...##.......
##.##..#####..#..##.....
#.#####..###.#.....##...
#.#######.##.#.......#..
#.###.###.##.#...#...#..
#.#...###.##.#.###...#..
#..##.####.#.##..#....#.
#####.###.##.....#...#..
####.###.###....#...#...
####.##.####....#..#....
####.#.#####....#.#.....
####..######....##......
*UsePictures> printPicture (ex243 horse)
.......##...#######..###
.....##..#..#####..##.##
...##.....#.###..#####.#
..#.......#.##.#######.#
..#...#...#.##.###.###.#
..#...###.#.##.###...#.#
.#....#..##.#.####.##..#
..#...#.....##.###.#####
...#...#....###.###.####
....#..#....####.##.####
.....#.#....#####.#.####
......##....######..####
####..######....##......
####.#.#####....#.#.....
####.##.####....#..#....
####.###.###....#...#...
#####.###.##.....#...#..
#..##.####.#.##..#....#.
#.#...###.##.#.###...#..
#.###.###.##.#...#...#..
#.#######.##.#.......#..
#.#####..###.#.....##...
##.##..#####..#..##.....
###..#######...##.......
*UsePictures>

[Haskell] Exercise 2.3

2通りの方法で作る。

まず、whiteとblackを明示的に並べる。

*UsePictures> printPicture (sideBySide (white ++ black) (black ++ white))
............############
............############
............############
............############
............############
............############
............############
............############
............############
............############
............############
............############
############............
############............
############............
############............
############............
############............
############............
############............
############............
############............
############............
############............
*UsePictures>

次にwhiteから2x2のchecker boardを作る関数を作る。(関数の合成を使ってみた)
また、同じPictureを2x2に並べる関数を作って、上記の2x2 checker boardに2回適用すれば8x8になる。
UsePictures.hsへ追記。

-- Ex2.3
checkerV, checkerH, checker22 :: Picture -> Picture
checkerV p = above p (invertColour p)
checkerH p = sideBySide p (invertColour p)
checker22 = checkerH . checkerV

copyV, copyH, copy22 :: Picture -> Picture
copyV p = above p p
copyH p = sideBySide p p
copy22 = copyV . copyH

試してみる。

*UsePictures> printPicture (checker22 white)
............############
............############
............############
............############
............############
............############
............############
............############
............############
............############
............############
............############
############............
############............
############............
############............
############............
############............
############............
############............
############............
############............
############............
############............
*UsePictures> printPicture ((copy22 . copy22 . checker22) white)
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
............############............############............############............############
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
############............############............############............############............
*UsePictures>

[Haskell] Exercise 2.2

Haskell: The Craft of Fuctional Programming の演習問題。

black を2通りの方法(1つはwhiteを使わないでsuperimposeを使う)で求める。
A and (~A) = 1 であることを使う。

Prelude> :load UsePictures
Compiling Pictures ( ./Pictures.hs, interpreted )
Compiling UsePictures ( UsePictures.hs, interpreted )
Ok, modules loaded: UsePictures, Pictures.
*UsePictures> printPicture (invertColour white)
############
############
############
############
############
############
############
############
############
############
############
############
*UsePictures> printPicture (superimpose horse (invertColour horse))
############
############
############
############
############
############
############
############
############
############
############
############
*UsePictures>

UsePictures.hsに下記を追加する。

-- Ex2.2
black :: Picture
black = invertColour white

24 June, 2006

[Haskell] Exercise 2.1

Haskell: The Craft of Functional Programmingのサイトから、教科書用のコードのダウンロードページへ行き、Pictures.hs をダウンロードした。

% ghci
___ ___ _
/ _ \ /\ /\/ __(_)
/ /_\// /_/ / / | | GHC Interactive, version 6.4, for Haskell 98.
/ /_\\/ __ / /___| | http://www.haskell.org/ghc/
\____/\/ /_/\____/|_| Type :? for help.

Loading package base-1.0 ... linking ... done.
Prelude> :load Pictures
Compiling Pictures ( Pictures.hs, interpreted )
Ok, modules loaded: Pictures.
*Pictures> printPicture horse
.......##...
.....##..#..
...##.....#.
..#.......#.
..#...#...#.
..#...###.#.
.#....#..##.
..#...#.....
...#...#....
....#..#....
.....#.#....
......##....
*Pictures>

これをimportするようなUsePictures.hsを書く。

% cat UsePictures.hs
--
-- UsePictures.hs
--
module UsePictures where
import Pictures

-- see p.8 and p.9
blackHorse :: Picture
blackHorse = invertColour horse

rotateHorse :: Picture
rotateHorse = flipH (flipV horse)

% ghci
___ ___ _
/ _ \ /\ /\/ __(_)
/ /_\// /_/ / / | | GHC Interactive, version 6.4, for Haskell 98.
/ /_\\/ __ / /___| | http://www.haskell.org/ghc/
\____/\/ /_/\____/|_| Type :? for help.

Loading package base-1.0 ... linking ... done.
Prelude> :load UsePictures
Compiling Pictures ( ./Pictures.hs, interpreted )
Compiling UsePictures ( UsePictures.hs, interpreted )
Ok, modules loaded: UsePictures, Pictures.
*UsePictures> printPicture blackHorse
#######..###
#####..##.##
###..#####.#
##.#######.#
##.###.###.#
##.###...#.#
#.####.##..#
##.###.#####
###.###.####
####.##.####
#####.#.####
######..####
*UsePictures> printPicture rotateHorse
....##......
....#.#.....
....#..#....
....#...#...
.....#...#..
.##..#....#.
.#.###...#..
.#...#...#..
.#.......#..
.#.....##...
..#..##.....
...##.......
*UsePictures>

[Scheme] DrScheme on MacOSX

DrScheme より、MacOSX用のパッケージをダウンロードして導入するだけ。

 使い方とかはソフトウェア技法DrSchemeクイックリファレンスとかが判りやすい。

22 June, 2006

[Haskell] GHC for MacOSX

 GHC Download version 6.4 @ haskell.org より GHC-6.4.pkg.zip をダウンロード。
 あとは普通にMacのインストールでOK。

[Test] テスト

 投稿のテストを兼ねて。

 今年の流行ものということもあって、関数型プログラミング言語の勉強メモを作る事に。
 Lispは、流行ものなのでSICPを読もうかと。
 Haskellは、「入門Haskell」「ふつうのHaskellプログラミング」を参考書にしつつ、Haskell : The Craft of Functional Programming, 2nd editionの演習問題を解くつもり。