Skip to content

Instantly share code, notes, and snippets.

@occipita
Created August 25, 2020 06:45
Show Gist options
  • Save occipita/c899478b913b678316ada31085494e87 to your computer and use it in GitHub Desktop.
Save occipita/c899478b913b678316ada31085494e87 to your computer and use it in GitHub Desktop.
Scrabble solver using equivalent algorithms to those at https://github.com/hyper-blade/scrabble-solvers
On my system, performance is about 20% slower than C++ and 20% faster than Java. Code length is 1314 characters, sitting between Ruby and PHP in the original list ordered by length (although this has since been removed).
module Main where
import System.IO
import Data.List
import qualified Data.Map.Strict as Map
countIn :: Eq a => [a] -> a -> Int
countIn l v = length $ filter (== v) l
generateWords :: [String] -> String -> [String]
generateWords dictionary letters = filter wordMatches dictionary
where
wordMatches :: String -> Bool
wordMatches word = all (letterCountMatches word) word
letterCountMatches word letter = letter == '\r' || countIn word letter <= countIn letters letter
scores :: Map.Map Char Int
scores = Map.fromAscList $ zip ['a'..'z'] [1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,4,10]
totalScore :: String -> Int
totalScore word = sum (map score word)
score :: Char -> Int
score letter = maybe 0 id (Map.lookup letter scores)
sortByScore :: [String] -> [String]
sortByScore = sortOn totalScore
countDownFrom :: Int -> [Int]
countDownFrom 0 = []
countDownFrom n = n : (countDownFrom $ n - 1)
showResults :: [String] -> IO ()
showResults words = putStr $ concatMap showWord (zip words (countDownFrom $length words))
where
showWord (word, num) = (show num) ++ ". " ++ word ++ "\n"
main :: IO ()
main = do
putStr "Letters: "
hFlush stdout
letters <- getLine
dictionary <- readFile "dictionary.txt"
showResults $ sortByScore $ generateWords (lines dictionary) letters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment