From 136ba9d1d513c714d27300fbbb9b08ac3440ed08 Mon Sep 17 00:00:00 2001 From: wi11-holdsworth <83637728+wi11-holdsworth@users.noreply.github.com> Date: Tue, 7 Oct 2025 19:32:42 +1100 Subject: [PATCH] fix: use average instead of max as evaluation function as it gives a slightly more efficient algorithm --- Proj2.hs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Proj2.hs b/Proj2.hs index 4892358..025371f 100644 --- a/Proj2.hs +++ b/Proj2.hs @@ -40,7 +40,7 @@ -- -- 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 --- 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 -- candidate that has the smallest of this number as the next guess. @@ -54,8 +54,9 @@ module Proj2 ) where +import Data.Function (on) import Data.List -import Data.Map qualified as M +import Data.Map qualified as Map import Data.Ord (comparing) import Data.Set qualified as S @@ -178,8 +179,8 @@ initialGuess = (bestFirstGuess, allChords) -- strategy: -- 1. reduce the size of the search space by removing all guesses inconsistent -- with the answer received for the previous guess. --- 2. for each candidate, calculate the worst case number of remaining target --- 3. choose the candidate with the smallest of this number +-- 2. for each candidate, calculate the average number of remaining targets +-- 3. choose the candidate with the smallest average -- nextGuess :: ([Pitch], GameState) -> (Int, Int, Int) -> ([Pitch], GameState) nextGuess (prevGuess, state) prevFeedback = (chosen, newState) @@ -190,13 +191,14 @@ nextGuess (prevGuess, state) prevFeedback = (chosen, newState) scored = map (\x -> (x, score x candidates)) candidates candidates = filter (\x -> prevFeedback == feedback prevGuess x) state - -- maximum number of possible targets per candidate - score candidate candidates = - maximum $ - M.elems $ - M.fromListWith - (+) - [(feedback candidate target, 1) | target <- candidates] + -- average number of possible targets per candidate + score candidate candidates = ((/) `on` fromIntegral) (sum l) (length l) + where + l = + Map.elems $ + Map.fromListWith + (+) + [(feedback candidate target, 1) | target <- candidates] -- ==== HELPER FUNCTIONS ======================================================