12 July, 2006

[Haskell] LL Ring : Round 2

LL Ringの、キミならどう書く 2.0 - ROUND 2 -をHaskellで解いてみた ... 特に工夫した訳ではないので単に解いただけに過ぎないのではあるが。

下記のような感じでhugsの上で動作確認しつつ小さな関数をくみ上げて実装。

f :: Int -> Int
f n
| n == 1 = 1
| even n = f (n `div` 2)
| otherwise = f (3 * n + 1)

f2 :: (Int,Int) -> (Int,Int)
f2 (n,k)
| n == 1 = (n,k)
| even n = f2 (n `div` 2, k + 1)
| otherwise = f2 (3 * n + 1, k + 1)

g :: Int -> Int
g n = snd ( f2 (n, 1))

g2 :: Int -> (Int,Int)
g2 n = (n, g n)

gs :: Int -> [(Int,Int)]
gs n = map g2 [1 .. n]

h2 :: [(Int,Int)] -> (Int,Int) -> (Int,Int)
h2 [] m = m
h2 (x:xs) m = case (snd x > snd m) of
True -> h2 xs x
False -> h2 xs m

h :: Int -> Int
h n = fst (h2 (gs n) (0,0))

main = do args <- getArgs
mapM_ (putStrLn . show . h . read) args


これをhugsの上でテスト。

Main> g2 3
(3,8)
Main> gs 10
[(1,1),(2,2),(3,8),(4,3),(5,6),(6,9),(7,17),(8,4),(9,20),(10,7)]
Main> h2 $$ (0,0)
(9,20)
Main> h 10
9
Main>


ghcでコンパイルして、iBook G4 で実行して時間測定。

% /usr/bin/time ./collatz 100
97
0.07 real 0.00 user 0.01 sys
% /usr/bin/time ./collatz 1000
871
0.18 real 0.10 user 0.01 sys
% /usr/bin/time ./collatz 10000
6171
1.28 real 1.13 user 0.04 sys
% /usr/bin/time ./collatz 100000
77031
14.64 real 13.78 user 0.28 sys


---
7/12追記
はてなのHaskellグループでみつけた回答→collatz予想 @ haskellのある暮らし
うーむ、奇麗なコードだ。あと、明示的にHashとかを使ってメモ化すると早い、ということの様だ。
遅延評価で再計算しないはずだと考えると、明示的にメモ化するメリットはどこにあるのだろうか。検索性能?

09 July, 2006

[Haskell] Exercise 5.8 - 5.11

LIst comprehension notation の練習
○ Exercise 5.8

doubleAll :: [Int] -> [Int]
doubleAll xs = [2*x | x <- xs]

Main> doubleAll [1,2,3]
[2,4,6]
Main> doubleAll []
[]


○ Exercise 5.9

import Char

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

isLetters :: Char -> Bool
isLetters c
| ('a' <= c) && (c <= 'z') = True
| ('A' <= c) && (c <= 'Z') = True
| otherwise = False

capitalize :: String -> String
capitalize s = [toupper c | c <- s]

capitalizeLetters :: String -> String
capitalizeLetters s = [toupper c | c <- s, isLetters c]

Main> capitalize "aabbCdE"
"AABBCDE"
Main> capitalize "aabbC--dE"
"AABBC--DE"
Main> capitalizeLetters "aabbC--dE"
"AABBCDE"
Main>

○ Exercise 5.10

divisors :: Int -> [Int]
divisors n = [x | x <- [1 .. n], n `mod` x == 0]

isPrime :: Int -> Bool
isPrime n = (length (divisors n)) == 2

Main> divisors 12
[1,2,3,4,6,12]
Main> divisors 7
[1,7]
Main> isPrime 12
False
Main> isPrime 7
True
Main>

○ Exercise 5.11

matches :: Int -> [Int] -> [Int]
matches x ys = [y | y<- ys, y == x]

elem :: Int -> [Int] -> Bool
elem x ys = (length (matches x ys)) /= 0

Main> matches 1 [1,2,1,3,1,4]
[1,1,1]
Main> elem 1 [1,2,1,3,1,4]
True
Main> matches 1 [2,3,4]
[]
Main> elem 1 [2,3,4]
False
Main>

07 July, 2006

[Haskell] Comparing Haskell and OOP language

 Smalltalkとかのオブジェクト指向な言語だと、適切なコレクションのクラスをうまく使うことが重要、という気がする。例えば先の問題Bとかで重複を避けて数えるなら、BagではなくSetを使うのが簡単な方法だろう。
 対するにHaskellとかの場合は、とりあえずリストにして、mapとかのリストに作用させる高階関数をうまく使う事が重要っぽい。その一方で、リストは単なるBagみたいなものでそれ自体には特筆すべき機能がないように思うのだが。

 あと、幾つもの関数を . や $ で繋ぐのは、なんかUnixのパイプみたいな感じだ。簡単な事をする関数を繋いで、という感じ。
 その見方で言うと、リストとかが標準入出力みたいな感じだろうか。リストから値を取って、加工してリストに入れる、みたいな。

[Haskell] ICPC 2006 Domestic, Problem B

小さな関数を書いて繋ぎ合わせて答えを出す事にする。これもmainが書けてないのだがまぁ問題自体は解けたという事で。

まず、リストから重複を除いて整列させる関数。整列は実は重要では無いが、重複は除きたい。

-- sort & uniq
--
sortuniq :: Ord a => [a] -> [a]
sortuniq [] = []
sortuniq [x] = [x]
sortuniq (p:xs) = sortuniq smaller ++ [p] ++ sortuniq larger
where
smaller = [x | x <- xs, x < p]
larger = [x | x <- xs, x > p]

Main> sortuniq [1,2,1,3,1,4]
[1,2,3,4]
Main> sortuniq [5,5,1,2,1,3,1,4]
[1,2,3,4,5]

次いで、電車を2つに分けたリストを作る。

-- spritStr
--
splitStr :: String -> [(String, String)]
splitStr s = map splitAtOnS [1 .. (length s - 1)]
where
splitAtOnS n = splitAt n s
-- splitAt :: Int -> [a] -> ([a],[a])

Main> splitStr "abcd"
[("a","bcd"),("ab","cd"),("abc","d")]

次いで、各ペアについて順序を反転するか否かで4通りづつ作る。重複があればここで除く。

-- reversePair
--
reversePair :: (String,String) -> [(String,String)]
reversePair (sa, sb) = sortuniq [(sa,sb), (sa,rsb), (rsa,sb), (rsa,rsb)]
where
rsa = reverse sa
rsb = reverse sb

Main> map reversePair $$
[[("a","bcd"),("a","dcb")],[("ab","cd"),("ab","dc"),("ba","cd"),("ba","dc")],[("abc","d"),("cba","d")]]
Main> concat $$
[("a","bcd"),("a","dcb"),("ab","cd"),("ab","dc"),("ba","cd"),("ba","dc"),("abc","d"),("cba","d")]

次いで、それらを連結する。

-- connectPair
--
connectPair :: (String,String) -> [String]
connectPair (sa,sb) = [sa ++ sb, sb ++ sa]


Main> map connectPair $$
[["abcd","bcda"],["adcb","dcba"],["abcd","cdab"],["abdc","dcab"],["bacd","cdba"],["badc","dcba"],["abcd","dabc"],["cbad","dcba"]]
Main> concat $$
["abcd","bcda","adcb","dcba","abcd","cdab","abdc","dcab","bacd","cdba","badc","dcba","abcd","dabc","cbad","dcba"]

次いで重複を除く。

trainPattern :: String -> [String]
trainPattern s = sortuniq $ concat $ map connectPair $ concat $ map reversePair (splitStr s)


Main> sortuniq $$
["abcd","abdc","adcb","bacd","badc","bcda","cbad","cdab","cdba","dabc","dcab","dcba"]
Main>

最後にリストの数を数える。

-- answer
--
answer :: String -> Int
answer s = length $ trainPattern s

Main> answer "aa"
1
Main> answer "abba"
6
Main> answer "abcd"
12
Main> answer "abcde"
18
Main>

05 July, 2006

[Haskell] ICPC 2006 Domestic, Problem A

2006-07-04 @ HaHaHa!International Collegiate Programming Contest : Domestic Contest 2006の存在を知る。

HaHaHa! の答えを見ないで簡単そうな問題を解いてみる事にする。とりあえず問題Aが簡単そう。
...うぅぅむ、入出力のところが判らない。「ふつける」か「入門Haskell」 を読まないと駄目かなぁ。
エラトステネスの篩の部分はとりあえず教科書からコピペ。(まぁ慣用句みたいなものだし...)

primes :: [Int]
primes = 2:(sieve [3, 5 ..])
where sieve (p:xs) = p: (sieve [ x | x <- xs, x `mod` p /= 0])

arithSeriesPrimes :: (Int, Int) -> [Int]
arithSeriesPrimes (a,d) = [ x | x <- primes, x >= a, (x-a) `mod` d == 0]

answer :: (Int, Int, Int) -> Int
answer (a, d, n) = last $ take n $ arithSeriesPrimes (a,d)

Prelude> :load acm2006a.hs
Compiling Main ( acm2006a.hs, interpreted )
Ok, modules loaded: Main.
*Main> answer (179,10,203) --- これは時間がかかった
6709
*Main> answer (179,10,203) --- これはすぐに答えが出た
6709
*Main> answer (271,37,39) --- これも割と早い?
12037
*Main> answer (367,186,151) --- これも時間がかかった
92809
*Main> answer (27,104,185) --- これは早い。
93523

primesは毎回最初から計算している訳ではなく、計算した所までは答えが記憶されているようだ。
うぅぅむ、入出力のところをちゃんと書ける様にしなくては。

一方で、この程度の問題ならJavaでもそんなに時間がかからずに書けるかも、とも思った。もっとパズル的な問題を解ける様にならねば。

04 July, 2006

[Haskell] HUnit

2006-07-03 HUnit@ のびのびなHaskell日記

 HUnit の使い方について書かれている。
 HUnit は慣れ親しんだ JUnit と同様の使い方なんで簡単に使えそうな気がする。

[Haskell] Exercise 5.5 - 5.7

○ Exercise 5.5
0.1は2進小数では無限小数になるので0.1*10=1にならない、というのが期待されていたのだと思うが、教科書の問題に関してはOKでした。

Main> [0, 0.1 .. 1]
[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]

○ Exercise 5.6
[2, 3] は、2と3のリスト。
[[2, 3]]は、[2,3]を含むリスト。

Main> length [2,3]
2
Main> length [[2,3]]
1
Main> :type [[2,3]]
[[2,3]] :: Num a => [[a]]
Main>

○ Exercise 5.7
最後のは^Cを押すまで無限ループ。

Main> [2 .. 2]
[2]
Main> [2, 7 .. 4]
[2]
Main> [2, 2 .. 2]
[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2^C{Interrupted!}

Main>

[Haskell] Exercise 5.1 - 5.4

○ Exercise 5.1
tuple の使い方を学ぶ

maxOccurs :: Int -> Int -> (Int,Int)
maxOccurs x y
| x == y = (x, 2)
| x > y = (x, 1)
| x < y = (y, 1)

Main> maxOccurs 3 5
(5,1)
Main> maxOccurs 5 3
(5,1)
Main> maxOccurs 5 5
(5,2)

maxThreeOccurs :: Int -> Int -> Int -> (Int,Int)
maxThreeOccurs x y z
| m == z = (m, n+1)
| m > z = (m, n)
| m < z = (z, 1)
where m = fst $ maxOccurs x y
n = snd $ maxOccurs x y

Main> maxThreeOccurs 3 4 5
(5,1)
Main> maxThreeOccurs 3 5 4
(5,1)
Main> maxThreeOccurs 4 3 5
(5,1)
Main> maxThreeOccurs 4 5 3
(5,1)
Main> maxThreeOccurs 5 3 4
(5,1)
Main> maxThreeOccurs 5 4 3
(5,1)
Main> maxThreeOccurs 3 4 4
(4,2)
Main> maxThreeOccurs 4 3 4
(4,2)
Main> maxThreeOccurs 4 4 3
(4,2)
Main> maxThreeOccurs 4 4 4
(4,3)
Main>

○ Exercise 5.2
listをsortすれば終わりのような問題ではあるが、tupleを扱う練習なので素直に。

maxThree, middleThree, minThree :: (Int, Int, Int) -> Int
maxThree (x, y, z)
| x >= y && x >= z = x
| y >= x && y >= z = y
| otherwise = z

minThree (x, y, z)
| x <= y && x <= z = x
| y <= x && y <= z = y
| otherwise = z

middleThree (x, y, z) = x + y + z - maxThree (x,y,z) - minThree (x,y,z)

orderTriple :: (Int, Int, Int) -> (Int, Int, Int)
orderTriple (x,y,z) = (minThree (x,y,z), middleThree (x,y,z), maxThree (x,y,z))


Main> orderTriple (1,2,3)
(1,2,3)
Main> orderTriple (1,3,2)
(1,2,3)
Main> orderTriple (2,1,3)
(1,2,3)
Main> orderTriple (2,3,1)
(1,2,3)
Main> orderTriple (3,1,2)
(1,2,3)
Main> orderTriple (3,2,1)
(1,2,3)
Main> orderTriple (1,1,2)
(1,1,2)
Main> orderTriple (1,2,1)
(1,1,2)
Main> orderTriple (2,1,1)
(1,1,2)
Main> orderTriple (1,1,1)
(1,1,1)
Main>

○ Exercise 5.3, 5.4
直線 ax+by+c=0 がx軸と交わる点は、x=-c/a if a /= 0。
a /= 0 --> (-c/a, True)を、a == 0 --> (0.0, false) を返す関数を作る事にする。

-- find x for ax+by+c=0 where y=0
-- x = -c/a
findX :: (Float, Float, Float) -> (Float, Bool)
findX (a, b, c)
| a /= 0.0 = ((-c) / a, True)
| a == 0.0 = (0.0, False)

Main> findX (1.0, 1.0, 1.0)
(-1.0,True)
Main> findX (1.0, 0.0, 1.0)
(-1.0,True)
Main> findX (0.0, 0.0, 1.0)
(0.0,False)
Main> findX (0.0, 1.0, 1.0)
(0.0,False)
Main> findX (1.0, 2.0, 3.0)
(-3.0,True)
Main>

01 July, 2006

[Haskell] Exercise 4.15 - 4.20

テストケースの自動生成を行うquickCheckについては、いつか。(現状ではテスト仕様を私がHaskellでうまく書けないので。)
○ Exercise 4.15
allEquals :: Int -> Int -> Int -> Bool
のテストなので、
allEquals 1 1 1, allEquals 1 1 2, allEquals 1 2 1, allEquals 2 1 1, allEquals 1 2 3
とかをテストする。

○ Exercise 4.16
allEqualsの実装solutionについて検討する。m+n=2p となるようなケース(最後のケース)でsolutionは誤る。

solution :: Int -> Int -> Int -> Bool
solution m n p = ((m+n+p)==3*p)

Main> solution 1 1 1
True
Main> solution 1 1 2
False
Main> solution 1 2 1
False
Main> solution 2 1 1
False
Main> solution 1 2 3
False
Main> solution 1 5 3
True

○ Exercise 4.17
allDifferent :: Int -> Int -> Int -> Bool
テストケースとしては、
allDifferent 1 1 1, allDifferent 1 1 2, allDifferent 1 2 1, allDifferent 2 1 1, allDifferent 1 2 3
とか。
○ Exercise 4.18
allDifferentの実装attemptについて。attempt 1 2 1で誤り。

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

Main> attempt 1 1 1
False
Main> attempt 1 1 2
False
Main> attempt 1 2 1
True
Main> attempt 2 1 1
False
Main> attempt 1 2 3
True
Main>

○ Exercise 4.19
関数自体はExercise3.14で作成している。
ケースとしては、
* 3つとも同じ値
* 平均以上が1つの場合。引数の入れ替えに対して対称。
* 平均以上が2つの場合。引数の入れ替えに対して対称。
を試す。

Main> howManyAboveAverage 1 1 1
0
Main> howManyAboveAverage 1 2 10
1
Main> howManyAboveAverage 1 10 2
1
Main> howManyAboveAverage 2 1 10
1
Main> howManyAboveAverage 2 10 1
1
Main> howManyAboveAverage 10 1 2
1
Main> howManyAboveAverage 10 2 1
1
Main> howManyAboveAverage 1 10 11
2
Main> howManyAboveAverage 1 11 10
2
Main> howManyAboveAverage 10 1 11
2
Main> howManyAboveAverage 10 11 1
2
Main> howManyAboveAverage 11 1 10
2
Main> howManyAboveAverage 11 10 1
2
Main>

○ Exercise 4.20
Exercise 4.14を参照の事。

[Haskell] Exercise 4.13, 4.14

○ Exercise 4.13
ユークリッドの互除法

import Prelude hiding (gcd)
gcd :: Int -> Int -> Int
gcd m n
| m < n = gcd n m
| m `mod` n == 0 = n
| otherwise = gcd n (m `mod` n)

Main> gcd 7 5
1
Main> gcd 12 18
6
Main>

○ Exercise 4.14

power2 :: Int -> Int
power2 n
| n == 0 = 1
| n == 1 = 2
| n `mod` 2 == 0 = square (power2 (n `div` 2))
| otherwise = 2 * square (power2 ((n-1) `div` 2))
where square x = x * x

Main> power2 0
1
Main> power2 1
2
Main> power2 2
4
Main> power2 3
8
Main> power2 4
16
Main> power2 5
32
Main>

[Haskell] Exercise 4.7 - 4.12

○ Exercise 4.7

mulFun :: (Int -> Int) -> Int -> Int
mulFun f n
| n == 0 = f 0
| n > 0 = f n * mulFun f (n-1)
| otherwise = error "mulFun only defined on natural numbers"

Main> mulFun (\x -> x + 1) (-1)

Program error: mulFun only defined on natural numbers

Main> mulFun (\x -> x + 1) 0
1
Main> mulFun (\x -> x + 1) 1
2
Main> mulFun (\x -> x + 1) 2
6
Main>

○ Exercise 4.8
ループカウンタを引数にする方法しか思いつかなかった。

sqrt :: Int -> Int
sqrt x
| x < 0 = error "sqrt defined only on natural number"
| otherwise = sqrt2 0 x

sqrt2 :: Int -> Int -> Int
sqrt2 n x
| n*n <= x && x < (n+1)*(n+1) = n
| otherwise = sqrt2 (n+1) x

Main> sqrt 0
0
Main> sqrt 1
1
Main> sqrt 15
3
Main> sqrt 16
4
Main> sqrt 17
4
Main> sqrt (-1)

Program error: sqrt defined only on natural number

Main>

○ Exercise 4.9

maxFun :: (Int -> Int) -> Int -> Int
maxFun f n
| n == 0 = f 0
| n > 0 = max (f n) (maxFun f (n-1))
| otherwise = error "maxFun defined only on natural number"

f :: Int -> Int
f 0 = 0
f 1 = 44
f 2 = 17
f _ = 0

Main> maxFun f 0
0
Main> maxFun f 1
44
Main> maxFun f 2
44
Main> maxFun f 3
44
Main>

○ Exercise 4.10

searchZero :: (Int -> Int) -> Int -> Bool
searchZero f n
| n < 0 = error "defined only on natural number"
| n == 0 = (f 0 == 0)
| otherwise = (f n == 0) || searchZero f (n-1)

Main> searchZero (\x -> x - 3) (-1)

Program error: defined only on natural number

Main> searchZero (\x -> x - 3) 0
False
Main> searchZero (\x -> x - 3) 1
False
Main> searchZero (\x -> x - 3) 3
True
Main> searchZero (\x -> x - 3) 4
True
Main>

同じようなことをリストを使えば簡単になる。

searchZero2 :: (Int -> Int) -> Int -> Bool
searchZero2 f n = any (\x -> f x == 0) [0 .. n]

Main> searchZero2 (\x -> x - 3) 2
False
Main> searchZero2 (\x -> x - 3) 3
True
Main> searchZero2 (\x -> x - 3) 4
True
Main>

○ Exercise 4.11
region 0 = 1
region 1 = region 1 + 1
region 2 = region 2 + 2 = region 0 + 1 + 2
よって
region n = region 0 + n(n+1)/2 = n(n+1)/2 + 1
と再帰を使わず明に書き下せる。
○ Exercise 4.12 [Harder]
教科書には、平面をn個の直線で分割すると幾つの領域に別れるか、という例が載っている。
この問題は、同様に考察して、空間をn個の平面で分割すると幾つの領域に別れるか、を考える。
region3 0 = 1, region3 1 = 2, region3 2 = 4, region3 3 = 8
ここまでは自明。

今、空間を3つの平面 p1, p2, p3で切ったとする。このp1, p2, p3 と全て交わる平面として p4を考える。p4の切り口はどうなっているかというと、3本の直線で平面を領域分けした状態になっているはず。この領域が切断で領域数が倍に増える。
よって、region3 4 = region3 3 + region 3の様に計算すれば良い。
計算してみると、region3 0 = 1と、教科書の region を使えば、region3 1, region3 2, region3 3も正しく解ける事が判る。
(同様に考えていけば、n次元空間の分割もnに関する数学的帰納法で解ける。)

なお、数学として公式まで求めている回答は、球は何個に分けられる?の千葉さんの回答を参照の事。(同じ様に考えている人がいるので、これで回答としてはいいのだと思う。)

region2 :: Int -> Int
region2 n
| n == 0 = 1
| n > 0 = region2 (n-1) + n
| otherwise = error "n<0"

region3 :: Int -> Int
region3 n
| n == 0 = 1
| n > 0 = region3 (n-1) + region2 (n-1)
| otherwise = 0

Main> region3 0
1
Main> region3 1
2
Main> region3 2
4
Main> region3 3
8
Main> region3 4
15
Main> region3 5
26
Main>

[Haskell] Exercise 4.5, 4.6

ようやく再帰の話とかが出てきました。

rangeProduct :: Int -> Int -> Int
rangeProduct m n
| m > n = 0
| m == n = n
| otherwise = m * rangeProduct (m+1) n

Main> rangeProduct 4 3
0
Main> rangeProduct 4 4
4
Main> rangeProduct 4 5
20
Main> rangeProduct 4 6
120
Main> rangeProduct (-3) (-1)
-6
Main> rangeProduct (-3) 3
0
Main>

fac を rangeProduct を使って定義する。負の引数に対してエラー表示と、0に対して 0! = 1 を返す様にする必要。

fac :: Int -> Int
fac n
| n < 0 = error "fac only defined on natural number"
| n == 0 = 1
| otherwise = rangeProduct 1 n

Main> fac (-1)

Program error: fac only defined on natural number

Main> fac 0
1
Main> fac 1
1
Main> fac 5
120
Main>

[Haskell] Exercise 4.1 - 4.4

○ Exercise 4.1
maxFourを3通りの方法で書く。maxは自分の書いた物を使う様に指定。

import Prelude hiding (max)
max :: Int -> Int -> Int
max x y
| x >= y = x
| otherwise = y

maxThree :: Int -> Int -> Int -> Int
maxThree x y z = max (max x y) z

maxFour1 :: Int -> Int -> Int -> Int -> Int
maxFour1 x y z w = max (max (max x y) z) w

maxFour2 :: Int -> Int -> Int -> Int -> Int
maxFour2 x y z w = max (max x y) (max z w)

maxFour3 :: Int -> Int -> Int -> Int -> Int
maxFour3 x y z w = max (maxThree x y z) w

○ Exercise 4.2
betweenは昇順でも降順でもTrueになる様に作る。

between :: Int -> Int -> Int -> Bool
between x y z = (weakAscendingOrder x y z)
|| (weakAscendingOrder z y x)

weakAscendingOrder :: Int -> Int -> Int -> Bool
weakAscendingOrder x y z = (x<=y) && (y<=z)

Main> between 1 2 3
True
Main> between 3 2 1
True
Main> between 3 2 2
True
Main> between 3 1 2
False
Main> between 1 3 2
False
Main> between 1 3 3
True
Main>

○ Exercise 4.3
指示通り Exercise 3.7, 3.8 で作った関数を再利用する。

-- from Ex3.8
threeEquals :: Int -> Int -> Int -> Bool
threeEquals m n p = (m==n) && (n==p)

-- from Ex3.7
threeDifferent :: Int -> Int -> Int -> Bool
threeDifferent m n p = (m /= n) && (n /= p) && (p /= m)

howManyEquals :: Int -> Int -> Int -> Int
howManyEquals x y z
| threeEquals x y z = 3
| threeDifferent x y z = 0
| otherwise = 2

Main> howManyEquals 34 25 36
0
Main> howManyEquals 34 25 34
2
Main> howManyEquals 34 34 34
3
Main>

○ Exercise 4.4
とりあえずの回答。

howManyOfFourEqual :: Int -> Int -> Int -> Int -> Int
howManyOfFourEqual x y z w
| (x == y) && (y == z) && (z == w) = 4
| threeEquals x y z = 3
| threeEquals y z w = 3
| threeEquals z x y = 3
| threeEquals w x y = 3
| x == y = 2
| x == z = 2
| x == w = 2
| y == z = 2
| y == w = 2
| z == w = 2
| otherwise = 0

Main> howManyOfFourEqual 1 2 3 4
0
Main> howManyOfFourEqual 1 2 3 3
2
Main> howManyOfFourEqual 1 3 3 3
3
Main> howManyOfFourEqual 3 3 3 3
4
Main> howManyOfFourEqual 1 3 3 1
2
Main>

別解:比較の6個の組み合わせの等号の数を数える。(Haskellっぽくない?)

isEq :: Int -> Int -> Int
isEq x y
| x == y = 1
| otherwise = 0

howManyOf4Equal :: Int -> Int -> Int -> Int -> Int
howManyOf4Equal x y z w =
case (count x y z w) of
6 -> 4 -- all combination ==
3 -> 3 -- x == y == z == x
2 -> 2 -- example x == y /= z == w
1 -> 2 -- example x == y only
0 -> 0
where count x y z w = (isEq x y) + (isEq x z) + (isEq x w)
+ (isEq y z) + (isEq y w) + (isEq z w)

Main> howManyOf4Equal 1 2 3 4
0
Main> howManyOf4Equal 1 2 3 3
2
Main> howManyOf4Equal 1 3 3 3
3
Main> howManyOf4Equal 3 3 3 3
4
Main> howManyOf4Equal 1 3 3 1
2
Main>

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の演習問題を解くつもり。