patternMinor
Return list with numbers of color occurrences in another list
Viewed 0 times
occurrencesreturnwithnumberscoloranotherlist
Problem
I'm solving "mastermind game" problem from CIS haskell course. Here is the link to assignment pdf if someone is interested.
List of possible colors is defined like this:
And I had to write a function that will take a list with color guesses and return the occurrence count for each available color in the form of a list.
It works fine but I'd like to know if there is better/more expressive way to write it (using most basic available functions).
I'm not sure what's good practice in Haskell; that is my main problem. I have tried to write in point free notation at first but it looked overly complicated.
My worry is that code is not clear enough. I like to have code that is as obvious as possible.
Here are test cases in case it helps:
List of possible colors is defined like this:
data Peg = Red | Green | Blue | Yellow | Orange | Purple
deriving (Show, Eq, Ord)
type Code = [Peg]
colors :: [Peg]
colors = [Red, Green, Blue, Yellow, Orange, Purple]And I had to write a function that will take a list with color guesses and return the occurrence count for each available color in the form of a list.
countColors :: Code -> [Int]
countColors a = map (\(x,y) -> length $ filter (x==) y) combo
where combo = zip colors (take 6 $ repeat a)It works fine but I'd like to know if there is better/more expressive way to write it (using most basic available functions).
I'm not sure what's good practice in Haskell; that is my main problem. I have tried to write in point free notation at first but it looked overly complicated.
My worry is that code is not clear enough. I like to have code that is as obvious as possible.
Here are test cases in case it helps:
countColors [Red, Blue, Yellow, Purple] == [1, 0, 1, 1, 0, 1]
countColors [Green, Blue, Green, Orange] == [0, 2, 1, 0, 1, 0]Solution
I think you're tripping yourself up by position-encoding the colors. Position-encoding is usually a code smell in Haskell, what you probably want is an association. Consider the difference between
(You could be even more specific at the type level with something like
So then how do you write a function with type
[Int] and [(Peg, Int)], and just how much more expressive of intent the latter is.(You could be even more specific at the type level with something like
type Count = Int countColors :: Code -> Map Peg Count but that's probably excessive for a small game.)So then how do you write a function with type
Code -> [(Peg, Int)]? As you noticed the [Peg] may be in any order, so to compensate you can filter for each individual color, or you could leverage the Ord Peg instance and sort the original list to group identical colors together. After the colors are in order, what's left is to simply run-length encode the list.countColors :: Code -> [(Peg, Int)]
countColors = map (\shade -> (head shade, length shade)) . group . sortCode Snippets
countColors :: Code -> [(Peg, Int)]
countColors = map (\shade -> (head shade, length shade)) . group . sortContext
StackExchange Code Review Q#88720, answer score: 4
Revisions (0)
No revisions yet.