ぷち・ぷろぐらむ
JAVA5.0でGO!! | プログラミングに自信があるやつこい!!
10分でコーディング | プログラミングに自信があるやつこい!!
via なんかしらんけど配る - * *scrap*
こういうのを Haskell で書くのはヒキョウだと思いつつ、書いてみたい誘惑に勝てませんでした。
布教活動の一環として公開します。
deal'(リストを n 個ずつに区切る)はProgramming:玉手箱:リストに、unfoldr を使ったきれいな書き方が載ってました。
もっと簡単に書けるよ、というのがあったら教えてください。
import Data.List deal :: Int -> String -> [String] deal n xs | null xs' = replicate n "" | otherwise = transpose xs' where xs' = deal' n xs deal' n xs | length xs < n = [] | otherwise = as : deal' n bs where (as,bs) = splitAt n xs whoCanSee :: [String] -> [String] -> [String] -> [String] whoCanSee users allowed report = map (users!!) $ findIndices (canSee report) allowed where canSee rs as = all (`elem` words as) rs
コメントいただいたので修正。length がリストの一部に対して何度も適用されてしまうので、再帰の外に出しました。これでリスト全体に対しては一度しか適用されないはず。
あと deal' は splits に名前を変更。
deal n xs | null xs' = replicate n [] | otherwise = transpose xs' where xs' = takeWhile ((==n).length) $ splits n xs splits n [] = [] splits n xs = as : splits n bs where (as,bs) = splitAt n xs
それから、関数 deal の中での場合分けが冗長に感じたので、以下のようにまとめてみたのですが、これは逆に分かりにくいですね。難読化してるだけだ。(Maybe 版に合わせて微修正)
dealL n = map concat . transpose . takeWhile ((==n).length) . splits n . (replicate n [] ++) . map (:[])
[1..100]>>=pen さんに「それ Maybe でもできるよ」って教えてもらいました。あぁ、この方が目的に適った使い方で分かりやすいかも。上の List 版と比べてもらうと、同じところ違うところがはっきりすると思います。init は悔しいので使わない。
dealM n = map catMaybes . transpose . takeWhile ((==n).length) . splits n . (replicate n Nothing ++) . map Just
と思ったら、one liner に進化してるし。