fix: use average instead of max as evaluation function as it gives a slightly more efficient algorithm
This commit is contained in:
parent
8f07d1a83c
commit
136ba9d1d5
1 changed files with 13 additions and 11 deletions
20
Proj2.hs
20
Proj2.hs
|
|
@ -40,7 +40,7 @@
|
||||||
--
|
--
|
||||||
-- To pick the best next guess, we filter the game state to contain only
|
-- To pick the best next guess, we filter the game state to contain only
|
||||||
-- targets that are consistent with the received feedback from the previous
|
-- targets that are consistent with the received feedback from the previous
|
||||||
-- guess. We then calculate, for each candidate, the maximum number of guesses
|
-- guess. We then calculate, for each candidate, the average number of guesses
|
||||||
-- that would remain if we chose it as the next guess. We can then choose the
|
-- that would remain if we chose it as the next guess. We can then choose the
|
||||||
-- candidate that has the smallest of this number as the next guess.
|
-- candidate that has the smallest of this number as the next guess.
|
||||||
|
|
||||||
|
|
@ -54,8 +54,9 @@ module Proj2
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Data.Function (on)
|
||||||
import Data.List
|
import Data.List
|
||||||
import Data.Map qualified as M
|
import Data.Map qualified as Map
|
||||||
import Data.Ord (comparing)
|
import Data.Ord (comparing)
|
||||||
import Data.Set qualified as S
|
import Data.Set qualified as S
|
||||||
|
|
||||||
|
|
@ -178,8 +179,8 @@ initialGuess = (bestFirstGuess, allChords)
|
||||||
-- strategy:
|
-- strategy:
|
||||||
-- 1. reduce the size of the search space by removing all guesses inconsistent
|
-- 1. reduce the size of the search space by removing all guesses inconsistent
|
||||||
-- with the answer received for the previous guess.
|
-- with the answer received for the previous guess.
|
||||||
-- 2. for each candidate, calculate the worst case number of remaining target
|
-- 2. for each candidate, calculate the average number of remaining targets
|
||||||
-- 3. choose the candidate with the smallest of this number
|
-- 3. choose the candidate with the smallest average
|
||||||
--
|
--
|
||||||
nextGuess :: ([Pitch], GameState) -> (Int, Int, Int) -> ([Pitch], GameState)
|
nextGuess :: ([Pitch], GameState) -> (Int, Int, Int) -> ([Pitch], GameState)
|
||||||
nextGuess (prevGuess, state) prevFeedback = (chosen, newState)
|
nextGuess (prevGuess, state) prevFeedback = (chosen, newState)
|
||||||
|
|
@ -190,11 +191,12 @@ nextGuess (prevGuess, state) prevFeedback = (chosen, newState)
|
||||||
scored = map (\x -> (x, score x candidates)) candidates
|
scored = map (\x -> (x, score x candidates)) candidates
|
||||||
candidates = filter (\x -> prevFeedback == feedback prevGuess x) state
|
candidates = filter (\x -> prevFeedback == feedback prevGuess x) state
|
||||||
|
|
||||||
-- maximum number of possible targets per candidate
|
-- average number of possible targets per candidate
|
||||||
score candidate candidates =
|
score candidate candidates = ((/) `on` fromIntegral) (sum l) (length l)
|
||||||
maximum $
|
where
|
||||||
M.elems $
|
l =
|
||||||
M.fromListWith
|
Map.elems $
|
||||||
|
Map.fromListWith
|
||||||
(+)
|
(+)
|
||||||
[(feedback candidate target, 1) | target <- candidates]
|
[(feedback candidate target, 1) | target <- candidates]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue