Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- data Eval = Eval Int Int
- evaluate :: Enum a => [a] -> [a] -> Eval
- matching :: (C set, Enum a) => EnumSet a -> [a] -> Eval -> set a
- matchingSimple :: Enum a => EnumSet a -> [a] -> Int -> [[EnumSet a]]
- randomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> set a -> State g (Maybe [a])
- mixedRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> set a -> State g (Maybe [a])
- scanningRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> EnumSet a -> [([a], Eval)] -> set a -> State g (Maybe [a])
- separatingRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> EnumSet a -> set a -> State g (Maybe [a])
- partitionSizes :: Enum a => EnumSet a -> [a] -> [(Eval, Integer)]
- mainSimple :: T Char -> Int -> IO ()
- mainRandom :: T Char -> Int -> IO ()
- main :: IO ()
- propBestSeparatingCode :: (C set, Enum a) => Int -> set a -> T [] [a] -> Bool
Documentation
evaluate :: Enum a => [a] -> [a] -> Eval Source #
Given the code and a guess, compute the evaluation.
matching :: (C set, Enum a) => EnumSet a -> [a] -> Eval -> set a Source #
Given a code and an according evaluation, compute the set of possible codes.
The Game.Mastermind game consists of collecting pairs of codes and their evaluations. The searched code is in the intersection of all corresponding code sets.
matchingSimple :: Enum a => EnumSet a -> [a] -> Int -> [[EnumSet a]] Source #
A variant of the game: It is only possible to specify number of symbols at right places.
The results of matching
and matchingSimple
cannot be compared.
mixedRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> set a -> State g (Maybe [a]) Source #
In the beginning we simply choose a random code from the set of possible codes. In the end, when the set becomes small, then we compare different alternatives.
scanningRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> EnumSet a -> [([a], Eval)] -> set a -> State g (Maybe [a]) Source #
This strategy starts with scanning the alphabet. That is, we test sets of different symbols we did not try so far. The idea is to sort out unused symbols early. This is especially useful when the alphabet is large, i.e. its size is some multiples of the code width.
We stop scanning when we are sure to have seen all characters of the secret code. E.g.:
vicx alsn o mfgt o hjqw edpz oo bkru - we already know, that these cannot be in the secret code
We use the Choice
data type
for tracking the number of symbols that we can minimally use
from the ones we have already tried.
The order of applying mergeChoice
matters,
but I see no easy way to find a good order
or to make it robust against re-ordering.
If the user tells us that all symbols in a code are used,
then the scanning phase ends immediately.
This happens automatically according to our way of processing Choice
s.
separatingRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> EnumSet a -> set a -> State g (Maybe [a]) Source #
In the beginning we choose codes that separate reasonably well, based on heuristics. At the end, when the set becomes small, we do a brute-force search for an optimally separating code.