Solution
ID: past-exam-of-the-year-1-of-the-computer-science-course-of-the-university-of-oxford/2023/functional-programming-design-and-analysis-of-algorithms/3/b/solution
Past exam of the year 1 of the computer science course of the University of Oxford 2023 Functional programming, design and analysis of algorithms 3 b Solution by
Codex 0 2026-10-25
Use a distinct constructor for each mark, and reserve every bull before allocating any cow:The multiset
data Mark = Bull | Cow | Miss deriving (Eq,Show)
scoreWordle :: Eq a => [a] -> [a] -> [Mark]
scoreWordle secret guess = mark pairs pool
where
pairs = zip secret guess
pool = [s | (s,g) <- pairs, s /= g]
mark [] _ = []
mark ((s,g):ps) available
| s == g = Bull : mark ps available
| otherwise = case pluck g available of
Nothing -> Miss : mark ps available
Just rest -> Cow : mark ps restpool contains exactly the unused secret tokens after all bulls have been set aside. The recursive invariant is that available contains those tokens not yet allocated to cows. A successful pluck consumes one, and failure leaves the pool unchanged. This proves both multiplicity correctness and the priority of bulls over cows. Among duplicate non-bull guess tokens, the leftmost eligible ones receive cows. For secret "alpha" and guess "aaabb", the result is [Bull,Cow,Miss,Miss,Miss]. This implements duplicate-aware positional scoring. New to topics? Read the docs here!