From 85f7e0bf2fea6223cd4f19a93e7285f9c8ae9fb3 Mon Sep 17 00:00:00 2001 From: MMZK1526 Date: Fri, 27 Sep 2024 21:54:57 +0100 Subject: [PATCH] Add comments to Year 2023 --- README.md | 23 +++++++------ src/Year2023/Solver.hs | 76 ++++++++++++++++++++++++++---------------- 2 files changed, 60 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 7314e47..702e727 100644 --- a/README.md +++ b/README.md @@ -24,17 +24,18 @@ Otherwise if you have not installed `cabal`, you can just copy the solution of a If there's any issue or doubt on running the solutions, you are more than welcomed to drop an issue or contact me directly, and I will do my best to assist. -| Year | Module Name | -| ---- | -------------------------------------------------------------------------------- | -| 2022 | `:m Test Year2022.Examples Year2022.SC Year2022.Types` | -| 2021 | `:m Test Year2021.Alloc Year2021.Examples Year2021.Types` | -| 2020 | `:m Test Year2020.Examples Year2020.HashFunctions Year2020.Tries Year2020.Types` | -| 2019 | `:m Test Year2019.SOL Year2019.TestData Year2019.Types` | -| 2018 | `:m Test Year2018.CP` | -| 2017 | `:m Test Year2017.DC` | -| 2016 | `:m Test Year2016.Exam` | -| 2015 | `:m Test Year2015.Exam` | -| 2014 | `:m Test Year2014.Exam` | +| Year | Module Name | +| ---- | ------------------------------------------------------------------------------------------ | +| 2023 | `:m Test Year2022.Clues Year2022.Examples Year2022.Solve Year2022.Types Year2022.WordData` | +| 2022 | `:m Test Year2022.Examples Year2022.SC Year2022.Types` | +| 2021 | `:m Test Year2021.Alloc Year2021.Examples Year2021.Types` | +| 2020 | `:m Test Year2020.Examples Year2020.HashFunctions Year2020.Tries Year2020.Types` | +| 2019 | `:m Test Year2019.SOL Year2019.TestData Year2019.Types` | +| 2018 | `:m Test Year2018.CP` | +| 2017 | `:m Test Year2017.DC` | +| 2016 | `:m Test Year2016.Exam` | +| 2015 | `:m Test Year2015.Exam` | +| 2014 | `:m Test Year2014.Exam` | ### Tests Since 2024 diff --git a/src/Year2023/Solver.hs b/src/Year2023/Solver.hs index 1023a49..9c353ac 100644 --- a/src/Year2023/Solver.hs +++ b/src/Year2023/Solver.hs @@ -3,6 +3,19 @@ {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeApplications #-} +-- > While the official "level of difficulty" for this test is only one-star, +-- > I actually spent the most time on this test, although it was partially due +-- > to my lack of availability to properly work on this. +-- > +-- > The algorithm is pretty straightforward, even though cryptic clues are a +-- > foreign concept for me. However, due to an error in the original test suite +-- > (not available on the website; from which the test suite in this file is +-- > based upon), I spent days on a bug that never exists, which to a certain +-- > extent dampened my zeal to complete this challenge. +-- > +-- > Note that I used a lot of do-notations in place for list comprehensions +-- > since the latter form would be too long. + module Year2023.Solver where import Control.Monad @@ -93,6 +106,8 @@ parseAnagram ws = do guard $ unwords ind `elem` anagramIndicators pure $ Anagram ind (concat args) +-- > `do { x <- xs; guard (p x); pure (f x)}` is equivalent to +-- > `[f x | x <- xs, p x]`. parseReversal :: [String] -> [ParseTree] parseReversal ws = do (ind, args) <- split2M ws @@ -101,36 +116,36 @@ parseReversal ws = do pure $ Reversal ind clue parseInsertion :: [String] -> [ParseTree] -parseInsertion ws = standardInsertions <> envelopeInsertions - where - standardInsertions = do - (arg, ind, arg') <- split3 ws - guard $ unwords ind `elem` insertionIndicators - clue <- parseWordplay arg - clue' <- parseWordplay arg' - pure $ Insertion ind clue clue' - envelopeInsertions = do - (arg, ind, arg') <- split3 ws - guard $ unwords ind `elem` envelopeIndicators - clue <- parseWordplay arg - clue' <- parseWordplay arg' - pure $ Insertion ind clue' clue +parseInsertion ws = do + (arg, ind, arg') <- split3 ws + -- > try both flavours of insertion. + let standardInsertions = do + guard $ unwords ind `elem` insertionIndicators + clue <- parseWordplay arg + clue' <- parseWordplay arg' + pure $ Insertion ind clue clue' + envelopeInsertions = do + guard $ unwords ind `elem` envelopeIndicators + clue <- parseWordplay arg + clue' <- parseWordplay arg' + pure $ Insertion ind clue' clue + standardInsertions <> envelopeInsertions parseCharade :: [String] -> [ParseTree] -parseCharade ws = beforeCharade <> afterCharade - where - beforeCharade = do - (arg, ind, arg') <- split3 ws - guard $ unwords ind `elem` beforeIndicators - clue <- parseWordplay arg - clue' <- parseWordplay arg' - pure $ Charade ind clue clue' - afterCharade = do - (arg, ind, arg') <- split3 ws - guard $ unwords ind `elem` afterIndicators - clue <- parseWordplay arg - clue' <- parseWordplay arg' - pure $ Charade ind clue' clue +parseCharade ws = do + (arg, ind, arg') <- split3 ws + -- > try both flavours of charade. + let beforeCharade = do + guard $ unwords ind `elem` beforeIndicators + clue <- parseWordplay arg + clue' <- parseWordplay arg' + pure $ Charade ind clue clue' + afterCharade = do + guard $ unwords ind `elem` afterIndicators + clue <- parseWordplay arg + clue' <- parseWordplay arg' + pure $ Charade ind clue' clue + beforeCharade <> afterCharade -- Given... parseClue :: Clue -> [Parse] @@ -162,6 +177,7 @@ parseHiddenWord ws = do guard (not . null $ synonyms hiddenWord) pure $ HiddenWord ind hiddenWord +-- > Get the non-empty, non-full suffixes/prefixes of a list. trueSuffixes :: [a] -> [[a]] truePrefixes :: [a] -> [[a]] trueSuffixes [] = [] @@ -169,6 +185,10 @@ trueSuffixes [_] = [] trueSuffixes (x : xs) = xs : trueSuffixes xs truePrefixes xs = reverse <$> trueSuffixes (reverse xs) +-- > Empty case: []; +-- > Singleton case: get true suffixes of true prefixes; +-- > Two-element: concat true suffixes of word 1 with true prefixes of word 2; +-- > Multi-element: similar to above but always require the entire middle words. extractHiddenWords :: [[a]] -> [[a]] extractHiddenWords [] = [] extractHiddenWords [w] = concatMap trueSuffixes (truePrefixes w)