トップ «前の日記(2010-07-21) 最新 次の日記(2010-07-24)» 編集

日々の破片

著作一覧

2010-07-23

_ Haskellで組み合わせ

なんとなく、Haskellで組み合わせを求めるプログラムを作ろうと思い立って(再帰使いまくればできそうだし)、やってみた。
sx :: Int -> [Int] -> Int -> [[Int]]
sx 1 _ _ = []
sx _ [] _ = []
sx (n + 1) list x = map (++ [x]) $ select list n
 
select :: [Int] -> Int -> [[Int]]
select [] _ = []
select list 1 = map (:[]) list
select list n = (sx n tlist $ head list) ++ (select tlist n)
                where tlist = tail list
 
main :: IO ()
main = do
  putStrLn "list ?"
  list <- readIO =<< getLine
  putStrLn "choice ?"  
  n <- readIO =<< getLine
  putStrLn $ show $ select list n

:とか++の使い方のせいだろうけど逆順になるところが気に食わないができた(えらい長い期間のトライ&エラーの後で、樹木図みたいなのを書いて深呼吸したら数分でできたが(多分、1の場合が出てこなかったのかなぁとできてしまうと何にひっかかったのか思い出せないものだ)、正味はおそろしく長い)。

*Main> main
list ?
[1,2,3,4,5,6,7]
choice ?
3
[[3,2,1],[4,2,1],[5,2,1],[6,2,1],[7,2,1],[4,3,1],[5,3,1],[6,3,1],[7,3,1],[5,4,1],[6,4,1],[7,4,1],[6,5,1],[7,5,1],[7,6,1],[4,3,2],[5,3,2],[6,3,2],[7,3,2],[5,4,2],[6,4,2],[7,4,2],[6,5,2],[7,5,2],[7,6,2],[5,4,3],[6,4,3],[7,4,3],[6,5,3],[7,5,3],[7,6,3],[6,5,4],[7,5,4],[7,6,4],[7,6,5]]
*Main> 

追記:向井さんのアドバイスで以下のように修正

select :: [Int] -> Int -> [[Int]]
select [] _ = []
select list 1 = map (:[]) list
select (x:xs) n = (map (x:) $ select xs (n - 1)) ++ (select xs n)

なんで、(x:)はOKで、([];)とは書けないんだろう。Couldn't match expected type `Int' against inferred type `[a]'ということは、[]は要素の型が不定だからということなのかな(にしてはパラメータのパターンマッチには書けるのがわからないな)。(追記:とか書いてみたが、良く考えたらこちらは単に[a]だから要素は配列ではないからそもそも無理だった。そっちの意味のエラーだったのか。書き直したコードに問題があるのだとすぐ考えてしまうが、そうではなく書き直したことによって型の整合性が取れなくなったと考えるのが正しい考え方のようだ)

と思って、[a] -> Int -> [[a]]に変えたら、readIOが何に変換すれば良いかわからんエラーとなった。おそるべし型チェック……

_ まだ呪いがあったとは

検査例外の呪い

検査例外は見つけたらRuntimeException派生クラス(ここがミソかなぁ)でくるんじゃうからどうでもいいよ、4年たった今となってはという感じで、条件演算子はわかりにくいから使用禁止が許されるならば、検査歴外はわかりにくいから使用禁止でいいじゃん。

もともとは、tryの内側で宣言した変数をfinallyで参照できないのがよろしくないという話なので、結局は例外処理の扱いにくさに話が戻るのであった。(別方面でunwindできない例外処理は例外処理ではないというのを聞いたような覚えがあるが、状態を持ったプログラムの世界ではそれはいささか難しい)

本日のツッコミ(全3件) [ツッコミを入れる]
_ 向井 (2010-07-24 00:54)

sxいらないような気がしますが……<br><br>select :: [a] -> Int -> [[a]]<br>select _ 0 = []<br>select [] n = []<br>select l 1 = map (:[]) l<br>select (h:t) n = (map (h:) $ select t (n - 1)) ++ (select t n)

_ arton (2010-07-24 08:25)

どうもありがとうございます。(h:t)は後で気づいて、おれ何やってんだ状態でしたが、縮まりますねぇ。たぶん、++の前半と後半に分ける必要がありそうだと気付いた時に別の関数にしてそのままだったようです(今になって思えば、そのくらい正しい出力が得られたときは嬉しかったらしい)。

_ arton (2010-07-24 08:30)

後、(h:)と書けるのは素でわかっていなかったです。こちらもありがとうございます。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|

ジェズイットを見習え