2016-04-16 11 views
0

私は最近Mastermindソルバーを構築するためにhomework assignment of some UPenn Haskell Courseを完了しました(自習用)。列挙型の操作:ヒストグラムのリスト表示、比較、およびビルド

割り当ては

data Color = Red | Green | Blue | Yellow | Orange | Purple deriving (Eq, Show) 

type Code = [Color] 

の定義から始まりと列挙型の様々な操作を必要とします。

  1. のnのすべてのコードを列挙するために(すなわち、長さのすべてのデカルトの組み合わせ:私はcomplete the assignmentに管理してきましたが、私は自分のコードが不必要に反復的または非効率的だと感じたいくつかの部分がありましたColor値のN)、私はそれだけでColorのあらゆる可能だとしてこれは、反復的に脆いようで

    allColors = [Red, Green, Blue, Yellow, Orange, Purple] 
    

    を使用しました。列挙型を単独で定義し、それらからリストを作成する方法はありますか?概念的には、allColors = listAll(Color)(質問はlistAllとなります)のようにしたいと思います。

  2. 表現の多くは(lrColor秒である)(if l == r then 1 else 0)が含まれていますので、私はboolToInt機能を書いてしまってきました。確かに2つの列挙型を比較し、その結果をより簡単に整数にキャストするいくつかの方法がありますか?つまり、私は解決策の一部は、私はこれは両方思わ

    countColor :: Color -> Code -> Int 
    countColor _ [] = 0 
    countColor c (r:rs) = (boolToInt (c == r)) + countColor c rs 
    
    countColors :: Code -> [Int] 
    countColors code = [countColor c code | c <- allColors] 
    

    を使用しなかったこれ、Codeからヒストグラムを構築する必要が0

  3. に評価するRed == Red 1に評価するため、およびRed == Blueが欲しいです非効率かつ冗長です。これを行うためのより短い+より効率的な方法がありますか?我々は、我々は

    > [minBound .. maxBound] :: [Color] 
    [Red,Green,Blue,Yellow,Orange,Purple] 
    

    2)整数にブール値に変換するために使用できる

    data Color = Red | Green | Blue | Yellow | Orange | Purple 
        deriving (Eq, Show, Enum, Bounded, Ord) 
    

    を定義する場合

答えて

3

1)、我々が使用することができ

> fromEnum True 
1 
> fromEnum False 
0 

3)ヒストグラムの場合は、並べ替えとグループ化を開始できます。

> import Data.List 
> map (\xs -> (head xs, length xs)) . group . sort $ [Red, Red, Blue, Red] 
[(Red,3),(Blue,1)] 

練習としてゼロが追加されました。

リストの代わりに配列を使用すると、O(log n)係数を削除してパフォーマンスを向上させることができますが、パフォーマンスが実際に重要であることが分かっていない限り、避けてください。

+0

多くのおかげでそれを実装します。私は本当に1 + 2が好きです。あなたの3も短いですが、対数時間ですか、いいえ?しかし、おそらくそれはHaskell(または一般的な関数型言語)の性質です。 –

+0

@Amiはい、私が書いたとおりです。 O(n log n)時間の代わりにO(n)時間が必要な場合は、配列と左折を使用する必要があります。あなたのコードのこの部分のパフォーマンスが重要であることが分かっていない限り、あまり心配する必要はありません。 – chi

+0

ああ、はい、それを逃した。再び、多くのありがとう! –

3

1と3については、chi's suggestionを参照してください。

2.再帰関数でカウンタを手動で追加しないようにすることをお勧めします。一般的に、標準的な高次関数を使うのは、Haskellの方がもっと慣用的です。たとえば、countColorは述語を満たすサブリストの長さを与えるだけです。したがって、私は、同様に

countColor c = length . filter (==c) 

として

exactMatches ls rs = length . filter id $ zipWith (==) ls rs 
+0

多くの感謝!これははるかに良く見えます。 –

関連する問題