--/--/--

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2008/10/29

Project Euler: Problem 22

Problem 22

アルファベット文字列から数値への変換を容易にするため、アルファベットの Enum なデータ型を用意した。Enum#toInt とがそのまま使えるので、変換処理が簡潔になる。また、文字からシンボルへの変換は、ord と fromInt を組み合わせることで、これまた簡潔になる。こんな感じで、問題の本題については、かなり簡潔に書けたと思う。(2つ目のハイフンより上まで)

面倒だったのはファイルからのリスト構築。" とゴミで入った \n を消去し、"," で split する。こういう関数ってないのかな。いや絶対あるだろう。

実行結果

$ runhaskell 22.hs
871198282

プログラム

 1 import Data.Char (ord)
 2 import Data.List (sort)
 3 import IO (readFile)
 4
 5 data Alpha = A | B | C | D | E
 6            | F | G | H | I | J
 7            | K | L | M | N | O
 8            | P | Q | R | S | T
 9            | U | V | W | X | Y
10            | Z deriving (Enum,Eq,Show)
11
12 toInt :: Alpha -> Int
13 toInt = (+1. fromEnum
14
15 fromChar :: Char -> Alpha
16 fromChar = toEnum . subtract (ord 'A'. ord
17 ----------------------------------------
18
19 score :: Int -> String -> Int
20 score n s = n * (sum $ map (toInt . fromChar) s)
21
22 scores :: [String] -> Int
23 scores = sum . map (uncurry score) . zip [1..]
24
25 sortNames :: [String] -> [String]
26 sortNames = sort
27 ----------------------------------------
28
29 member :: (Eq a) => a -> [a] -> Bool
30 member _ [] = False
31 member x (y:ys) = x == y || member x ys
32
33 deleteAll :: (Eq a) => [a] -> [a] -> [a]
34 deleteAll _ [] = []
35 deleteAll xs (y:ys) | member y xs = deleteAll xs ys
36                     | otherwise   = y : deleteAll xs ys
37
38 splitWith :: (Eq a) => a -> [a] -> [[a]]
39 splitWith _ [] = []
40 splitWith x ys = split' x ys []
41   where split' _ [] r = [reverse r]
42         split' x (y:ys) r
43            | x == y    = (reverse r) : splitWith x ys
44            | otherwise = split' x ys (y:r)
45
46 makeInput :: IO String
47 makeInput = readFile "names.txt"
48 ----------------------------------------
49
50 fn = makeInput >>=
51      return . scores . sortNames . splitWith ',' . deleteAll "\"\n"
52
53 main = fn >>= print
スポンサーサイト

comment

post




上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。