Last active
August 29, 2015 14:07
-
-
Save gcmurphy/2ce934eb08f59cb2aa77 to your computer and use it in GitHub Desktop.
CS194 Homework week 2 (most of it)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module HW02 where | |
import Words | |
import Data.List | |
-- Though a Scrabble hand is the same Haskell type as a Scrabble word, they | |
-- have different properties. Specifically, a hand is unordered whereas a word | |
-- is ordered. We denote this distinction by using a type synonym to talk | |
-- about hands, even though we could just say `String`. | |
type Hand = [Char] | |
-- A `Template` is like a word, but it has '?' characters in some places as | |
-- placeholders for letters from a player's hand. Because real words do not | |
-- have '?' characters, we use another type synonym to track this distinction. | |
type Template = String | |
-- A 'STemplate' is like a template, but it has markers to indicate four kinds | |
-- of special board locations: double-letter noted with 'D', triple-letter | |
-- noted with 'T', double-word noted with '2', and triple-word noted with '3'. | |
-- For matching, these behave just like '?' does -- they can be filled in with | |
-- any letter. But, when scoring, any letter played on a 'D' gets double its | |
-- value, and any letter played on a 'T' gets triple its value. If any square | |
-- in the template is a '2', the whole word's value is doubled; if any square | |
-- in the template is a '3', the whole word's score is tripled. If multiple of | |
-- these special squares are in the same word, the effects multiply. | |
type STemplate = Template | |
-- Write your code below: | |
useLetter :: Hand -> Int -> Hand | |
useLetter [] _ = [] | |
useLetter xs n = ys ++ tail zs | |
where (ys,zs) = splitAt n xs | |
-- | Returns true when word can be formed by hand | |
-- >>> formableBy "fun" ['x','n','i','f','u','e','l'] | |
-- True | |
-- >>> formableBy "haskell" ['k', 'l', 'e', 'h', 'a', 'y', 's'] | |
-- False | |
formableBy :: String -> Hand -> Bool | |
formableBy [] _ = True | |
formableBy word [] = False | |
formableBy (x:xs) letters = case elemIndex x letters of | |
Just n -> formableBy xs (useLetter letters n) | |
Nothing -> False | |
-- | Returns number words from the supplied letters | |
-- >>> wordsFrom ['h','e', 'l', 'l', 'o'] | |
-- ["eh","el","ell","he","hell","hello","helo","ho","hoe","hole","lo","oe","oh","ole"] | |
wordsFrom :: Hand -> [String] | |
wordsFrom hand = filter (`formableBy` hand) allWords | |
-- | Returns true if word can be made by hand + template | |
-- >>> wordFitsTemplate "??r?" ['c', 'x', 'e', 'a', 'b', 'c', 'l'] "care" | |
-- True | |
-- >>> wordFitsTemplate "??r?" ['c', 'x', 'e', 'a', 'b', 'c', 'l'] "car" | |
-- False | |
-- >>> wordFitsTemplate "let" ['c', 'x', 'e', 'a', 'b', 'c', 'l'] "let" | |
-- True | |
wordFitsTemplate :: Template -> Hand -> String -> Bool | |
wordFitsTemplate [] _ [] = True | |
wordFitsTemplate (a:_) _ [] = False | |
wordFitsTemplate [] _ (a:_) = False | |
wordFitsTemplate (x:xs) letters (y:ys) | |
| x == y = wordFitsTemplate xs letters ys | |
| x == '?' = case elemIndex y letters of | |
Just n -> wordFitsTemplate xs (useLetter letters n) ys | |
Nothing -> False | |
| otherwise = False | |
-- | Will return true if word matches template | |
-- >>> wordsFittingTemplate "??r?" ['c', 'x', 'e', 'a', 'b', 'c', 'l'] | |
-- ["acre","bare","carb","care","carl","earl"] | |
wordsFittingTemplate :: Template -> Hand -> [String] | |
wordsFittingTemplate template letters = filter fn allWords | |
where fn = (\word -> wordFitsTemplate template letters word) | |
-- | Compute the scrabble value of a word | |
-- >>> scrabbleValueWord "care" | |
-- 6 | |
-- >>> scrabbleValueWord "quiz" | |
-- 22 | |
scrabbleValueWord :: String -> Int | |
scrabbleValueWord word = sum $ map scrabbleValue word | |
-- | Take only the best words | |
-- >>> bestWords (wordsFittingTemplate "??r?" ['c', 'x', 'e', 'a', 'b', 'c', 'l']) | |
-- ["carb"] | |
-- >>> bestWords ["cat", "rat", "bat"] | |
-- ["bat", "cat"] | |
-- >>> bestWords [] | |
-- [] | |
bestWords :: [String] -> [String] | |
bestWords ws = let scores = map scrabbleValueWord ws | |
scored = zip ws scores | |
highest = maximum( scores ) in | |
fst $ unzip $ filter (\(w, s) -> s >= highest ) scored |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment