summaryrefslogtreecommitdiffstats
path: root/circleWords.hs
blob: 0609579ef39ef9e8362eb134ca7e5f744f04a46a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import qualified Data.Set as Set
import Data.List
import System.Environment
import Data.Char

-- Return a list of all rotations of word
rotations :: String -> [String]
rotations word = list' word 0
   where list' ""           _    = [""]
         list' word@(w:ord) num
            | num == length word = []
            | otherwise          = word:list' (ord++[w]) (num+1)

isWord :: String -> (Set.Set String) -> Bool
isWord []   _     = True
isWord word words = word `Set.member` words

wordGroupsOfLength :: [String] -> Int -> [String]
wordGroupsOfLength words 1      = words
wordGroupsOfLength []    _      = []
wordGroupsOfLength words length = [initial++other|initial<-words,other<-wordGroupsOfLength words (length-1)]

-- All word groups, combinations of words
allGroups :: (Set.Set String) -> [String]
allGroups words = concat [wordGroupsOfLength (Set.toList words) x|x<-[1..]]

-- Given a string, return a list of possible junctions, which are lists of ways to break the word
allWords :: String -> Int -> [[String]]
allWords words 1 = [[words]]
allWords words 2 = [[take x words,drop x words]|x<-[0..length words]]
allWords words n = [take x words:remainder|x<-[0..length words],remainder<-allWords (drop x words) (n-1)]

-- Return True if words is composed of english words concatenated together
canMakeWords :: String -> (Set.Set String) -> Bool
canMakeWords words dict = canMakeWords' (allWords words (length words)) dict
   where canMakeWords' (x:xs) dict
             | allTrue (map (`isWord` dict) x) = True
             | otherwise                       = canMakeWords' xs dict
         canMakeWords' [] _ = False

allTrue :: [Bool] -> Bool
allTrue [] = True
allTrue (x:xs)
   | x == False = False
   | otherwise  = allTrue xs

-- Return True if the word is a valid rotatable word
testWord :: String -> (Set.Set String) -> Bool
testWord word dict = allTrue (map (`canMakeWords` dict) (rotations word))

-- Given a dictionary, return all groups that work (infinite list)
returnValids :: (Set.Set String) -> [String]
returnValids words = [validWords | validWords<-allGroups words, testWord validWords words]

main = do dict <- getContents
          args <- getArgs
          let num = if (args /= [])
                    then read (args !! 0)
                    else 5
--          print . take num . Set.toList . Set.fromList . lines $ dict
          mapM putStrLn (take num $ returnValids . Set.fromList . lines $ dict)