X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=honeycomb-unpartitioned.hs;fp=honeycomb-unpartitioned.hs;h=95f464dd4b3f71b2e46c2d1a4615e4657203ef2a;hb=978aa4af1b4a8753d0cd04f7fcceaf6d899bca79;hp=0000000000000000000000000000000000000000;hpb=68b4df6b83ce0f6bea2379d3f46d7296dd36a3c9;p=honeycomb-puzzle.git diff --git a/honeycomb-unpartitioned.hs b/honeycomb-unpartitioned.hs new file mode 100644 index 0000000..95f464d --- /dev/null +++ b/honeycomb-unpartitioned.hs @@ -0,0 +1,85 @@ +import qualified Data.Set as S +import qualified Data.Map.Strict as M +import Data.Map.Strict ((!)) +import Data.List +-- import Data.Function + +type LetterSet = S.Set Char +type WordSet = M.Map LetterSet (S.Set String) +type ScoredSet = M.Map LetterSet Int +type PartitionedScoredSet = M.Map Char ScoredSet + +data Honeycomb = Honeycomb Char LetterSet + deriving (Show, Eq, Ord) + +main = do + allWords <- readFile "enable1.txt" + let validWords = [w | w <- words allWords, + length w >= 4, + (S.size $ S.fromList w) <= 7, + 's' `notElem` w] + let wordSets = mkWordSets validWords + -- let scoredSets = M.mapWithKey (\ls _ -> scoreLetterSet wordSets ls) wordSets + let scoredSets = M.mapWithKey scoreLetterSet wordSets + let partScoredSets = mkPartitionedScoredSets scoredSets + -- let pangramSets = S.filter (\k -> (S.size k == 7) && (not ('s' `S.member` k))) $ M.keysSet scoredSets + let pangramSets = S.filter ((7 == ) . S.size) $ M.keysSet scoredSets + let plausibleHoneycombs = mkPlausibleHoneycombs pangramSets + -- this takes 6 minutes to execute + -- let bestHoneycomb = maximumBy (compare `on` (scoreHoneycombP partScoredSets)) + -- (S.toList plausibleHoneycombs) + + -- this takes 2 minutes to execute + let bestHoneycomb = findBestHoneycomb scoredSets plausibleHoneycombs + print bestHoneycomb + + +mkWordSets :: [String] -> WordSet +mkWordSets = foldr addWord M.empty + where addWord w = M.insertWith S.union (S.fromList w) (S.singleton w) + +present :: LetterSet -> Honeycomb -> Bool +present target (Honeycomb mandatory letters) = + (mandatory `S.member` target) && ({-# SCC "present_subset" #-} target `S.isSubsetOf` letters) + +-- scoreLetterSet :: WordSet -> LetterSet -> Int +-- scoreLetterSet wordSets letterSet = bonus + (sum $ fmap scoreAWord (S.toList scoringWords)) +-- where scoringWords = wordSets ! letterSet +-- scoreAWord w = if length w == 4 then 1 else length w +-- bonus = if (S.size letterSet) == 7 then (S.size scoringWords) * 7 else 0 +scoreLetterSet :: LetterSet -> S.Set String -> Int +-- scoreLetterSet letterSet scoringWords = bonus + (sum $ fmap scoreAWord (S.toAscList scoringWords)) +scoreLetterSet letterSet scoringWords = bonus + (S.foldr' (\w t -> t + scoreAWord w) 0 scoringWords) + where scoreAWord w + | length w == 4 = 1 + | otherwise = length w + bonus = if (S.size letterSet) == 7 then (S.size scoringWords) * 7 else 0 + +mkPartitionedScoredSets scoredSets = M.fromList [(c, scoreSetWithLetter c) | c <- ['a'..'z']] + where scoreSetWithLetter c = M.filterWithKey (\k _ -> c `S.member` k) scoredSets + + +scoreHoneycombSeparate, scoreHoneycomb :: ScoredSet -> Honeycomb -> Int +scoreHoneycombSeparate scoredSets honeycomb = sum(validScores) + where inHoneycomb = M.filterWithKey (\k _ -> present k honeycomb) scoredSets + validScores = M.elems inHoneycomb +scoreHoneycomb scoredSets honeycomb = M.foldrWithKey scoreLetters 0 scoredSets + where scoreLetters letters score total + | present letters honeycomb = score + total + | otherwise = total + + +mkPlausibleHoneycombs :: S.Set LetterSet -> S.Set Honeycomb +mkPlausibleHoneycombs pangramSets = S.foldr S.union S.empty honeycombSets + where honeycombSets = S.map honeycombsOfLetters pangramSets + honeycombsOfLetters ls = S.map (\l -> Honeycomb l ls) ls + + +findBestHoneycomb scoredSets honeycombs = + S.foldr (betterHc scoredSets) (0, initHc) honeycombs + where initHc = Honeycomb 'a' $ S.singleton 'a' + +betterHc scoredSets hc (bestScore, bestHc) + | thisScore > bestScore = (thisScore, hc) + | otherwise = (bestScore, bestHc) + where thisScore = scoreHoneycomb scoredSets hc