diff options
Diffstat (limited to 'tests/lexers/lhs')
| -rw-r--r-- | tests/lexers/lhs/example.txt | 4933 | ||||
| -rw-r--r-- | tests/lexers/lhs/example2.txt | 4736 |
2 files changed, 9669 insertions, 0 deletions
diff --git a/tests/lexers/lhs/example.txt b/tests/lexers/lhs/example.txt new file mode 100644 index 00000000..d91b31b3 --- /dev/null +++ b/tests/lexers/lhs/example.txt @@ -0,0 +1,4933 @@ +---input--- + A Sukodku solver by Chris Kuklewicz (haskell (at) list (dot) mightyreason (dot) com) + The usual BSD license applies, copyright 2006. + Uploaded to HaskellWiki as DancingSudoku.lhs + + I compile on a powerbook G4 (Mac OS X, ghc 6.4.2) using + ghc -optc-O3 -funbox-strict-fields -O2 --make -fglasgow-exts + + This is a translation of Knuth's GDANCE from dance.w / dance.c + + http://www-cs-faculty.stanford.edu/~uno/preprints.html + http://www-cs-faculty.stanford.edu/~uno/programs.html + http://en.wikipedia.org/wiki/Dancing_Links + + I have an older verison that uses lazy ST to return the solutions on + demand, which was more useful when trying to generate new puzzles to + solve. + +> module Main where + +> import Prelude hiding (read) +> import Control.Monad +> import Control.Monad.Fix +> import Data.Array.IArray +> import Control.Monad.ST.Strict +> import Data.STRef.Strict +> import Data.Char(intToDigit,digitToInt) +> import Data.List(unfoldr,intersperse,inits) + +> new = newSTRef +> {-# INLINE new #-} +> read = readSTRef +> {-# INLINE read #-} +> write = writeSTRef +> {-# INLINE write #-} +> modify = modifySTRef +> {-# INLINE modify #-} + + Data types to prevent mixing different index and value types + +> type A = Int +> newtype R = R A deriving (Show,Read,Eq,Ord,Ix,Enum) +> newtype C = C A deriving (Show,Read,Eq,Ord,Ix,Enum) +> newtype V = V A deriving (Show,Read,Eq,Ord,Ix,Enum) +> newtype B = B A deriving (Show,Read,Eq,Ord,Ix,Enum) + + Sudoku also has block constraints, so we want to look up a block + index in an array: + +> lookupBlock :: Array (R,C) B +> lookupBlock = listArray bb [ toBlock ij | ij <- range bb ] +> where ra :: Array Int B +> ra = listArray (0,pred (rangeSize b)) [B (fst b) .. B (snd b)] +> toBlock (R i,C j) = ra ! ( (div (index b j) 3)+3*(div (index b i) 3) ) + + The values for an unknown location is 'u'. + The bound and range are given by b and rng. And bb is a 2D bound. + +> u = V 0 -- unknown value +> b :: (Int,Int) +> b = (1,9) -- min and max bounds +> rng = enumFromTo (fst b) (snd b) -- list from '1' to '9' +> bb = ((R (fst b),C (fst b)),(R (snd b),C (snd b))) + + A Spec can be turned into a parsed array with ease: + +> type Hint = ((R,C),V) +> newtype Spec = Spec [Hint] deriving (Eq,Show) + +> type PA = Array (R,C) V + +> parse :: Spec -> PA +> parse (Spec parsed) = let acc old new = new +> in accumArray acc u bb parsed + + The dancing links algorithm depends on a sparse 2D node structure. + Each column represents a constraint. Each row represents a Hint. + The number of possible hints is 9x9x9 = 271 + +> type (MutInt st) = (STRef st) Int + + The pointer types: + +> type (NodePtr st) = (STRef st) (Node st) +> type (HeadPtr st) = (STRef st) (Head st) + + The structures is a 2D grid of nodes, with Col's on the top of + columns and a sparse collection of nodes. Note that topNode of Head + is not a strict field. This is because the topNode needs to refer to + the Head, and they are both created monadically. + +> type HeadName = (Int,Int,Int) -- see below for meaning + +> data Head st = Head {headName:: !HeadName +> ,topNode:: (Node st) -- header node for this column +> ,len:: !(MutInt st) -- number of nodes below this head +> ,next,prev:: !(HeadPtr st) -- doubly-linked list +> } + +> data Node st = Node {getHint:: !Hint +> ,getHead:: !(Head st) -- head for the column this node is in +> ,up,down,left,right :: !(NodePtr st) -- two doubly-linked lists +> } + +> instance Eq (Head st) where +> a == b = headName a == headName b + +> instance Eq (Node st) where +> a == b = up a == up b + + To initialize the structures is a bit tedious. Knuth's code reads in + the problem description from a data file and builds the structure + based on that. Rather than short strings, I will use HeadName as the + identifier. + + The columns are (0,4,5) for nodes that put some value in Row 4 Col 5 + (1,2,3) for nodes that put Val 3 in Row 2 and some column + (2,7,4) for nodes that put Val 4 in Col 7 and some row + (3,1,8) for nodes that put Val 8 in some (row,column) in Block 1 + + The first head is (0,0,0) which is the root. The non-root head data + will be put in an array with the HeadName as an index. + +> headNames :: [HeadName] +> headNames = let names = [0,1,2,3] +> in (0,0,0):[ (l,i,j) | l<-names,i<-rng,j<-rng] + + A "row" of left-right linked nodes is a move. It is defined by a + list of head names. + +> type Move = [(Hint,HeadName)] + + Initial hints are enforced by making them the only legal move for + that location. Blank entries with value 'u = V 0' have a move for + all possible values [V 1..V 9]. + +> parseSpec :: Spec -> [Move] +> parseSpec spec = +> let rowsFrom :: Hint -> [Move] +> rowsFrom (rc@(R r,C c),mv@(V v')) = +> if mv == u then [ rsyms v | v <- rng ] +> else [ rsyms v' ] +> where (B b) = lookupBlock ! rc +> rsyms :: A -> Move +> rsyms v = map ( (,) (rc,V v) ) [(0,r,c),(1,r,v),(2,c,v),(3,b,v)] +> in concatMap rowsFrom (assocs (parse spec)) + + mkDList creates doubly linked lists using a monadic smart + constructor and the recursive "mdo" notation as documented at + http://www.haskell.org/ghc/docs/latest/html/users_guide/syntax-extns.html#mdo-notation + http://www.cse.ogi.edu/PacSoft/projects/rmb/ + + For more fun with this, see the wiki page at + http://haskell.org/hawiki/TyingTheKnot + +> mkDList :: (MonadFix m) => (b -> a -> b -> m b) -> [a] -> m b +> mkDList _ [] = error "must have at least one element" +> mkDList mkNode xs = mdo (first,last) <- go last xs first +> return first +> where go prev [] next = return (next,prev) +> go prev (x:xs) next = mdo this <- mkNode prev x rest +> (rest,last) <- go this xs next +> return (this,last) + + toSimple takes a function and a header node and iterates (read . function) + until the header is reached again, but does not return the header + itself. + +> toSingle step header = loop =<< (read . step) header +> where loop y = if header/=y then liftM (y:) (read (step y) >>= loop) +> else return [] +> + + forEach is an optimization of (toSimple step header >>= mapM_ act) + +> forEach step header act = loop =<< (read . step) header +> where loop y = if header/=y then (act y >> (read (step y)) >>= loop) +> else return () + + Now make the root node and all the head nodes. This also exploits mdo: + +> makeHeads :: [HeadName] -> (ST st) (Head st) +> makeHeads names = mkDList makeHead names +> where makeHead before name after = mdo +> ~newTopNode <- liftM4 (Node ((R 0,C 0),V 0) newHead) (new newTopNode) (new newTopNode) +> (new newTopNode) (new newTopNode) +> newHead <- liftM3 (Head name newTopNode) +> (new 0) (new after) (new before) +> return newHead + + The Head nodes will be places in an array for easy lookup while building moves: + +> type HArray st = Array HeadName (Head st) +> hBounds = ((0,1,1),(3,9,9)) +> type Root st = (Head st,HArray st) + + The addMove function creates the (four) nodes that represent a move and adds + them to the data structure. The HArray in Root makes for a fast + lookup of the Head data. + +> addMove :: forall st. (Root st) -> Move -> (ST st) (Node st) +> addMove (_,ha) move = mkDList addNode move +> where addNode :: (Node st) -> (Hint,HeadName) -> (Node st) -> (ST st) (Node st) +> addNode before (hint,name) after = do +> let head = ha ! name +> let below = topNode head +> above <- read (up below) +> newNode <- liftM4 (Node hint head) (new above) (new below) +> (new before) (new after) +> write (down above) newNode +> write (up below) newNode +> modify (len head) succ +> l <- read (len head) +> seq l (return newNode) + + Create the column headers, including the fast lookup array. These + will be resused between puzzles. + +> initHA :: (ST st) (Root st) +> initHA = do +> root <- makeHeads headNames +> heads <- toSingle next root +> let ha = array hBounds (zip (map headName heads) heads) +> return (root,ha) + + Take the Root from initHA and a puzzle Spec and fill in all the Nodes. + +> initRoot :: (Root st) -> Spec -> (ST st) () +> initRoot root spec = do +> let moves = parseSpec spec +> mapM_ (addMove root) moves + + Return the column headers to their condition after initHA + +> resetRoot :: (Root st) -> (ST st) () +> resetRoot (root,ha) = do +> let heads@(first:_) = elems ha +> let resetHead head = do +> write (len head) 0 +> let node = topNode head +> write (down node) node +> write (up node) node +> reset (last:[]) = do +> write (prev root) last +> write (next root) first +> reset (before:xs@(head:[])) = do +> resetHead head +> write (prev head) before +> write (next head) root +> reset xs +> reset (before:xs@(head:after:_)) = do +> resetHead head +> write (prev head) before +> write (next head) after +> reset xs +> reset (root:heads) + + getBest iterates over the unmet constraints (i.e. the Head that are + reachable from root). It locates the one with the lowest number of + possible moves that will solve it, aborting early if it finds 0 or 1 + moves. + +> getBest :: (Head st) -> (ST st) (Maybe (Head st)) +> getBest root = do +> first <- read (next root) +> if first == root then return Nothing +> else do +> let findMin m best head | head == root = return (Just best) +> | otherwise = do +> l <- read (len head) +> if l <= 1 then return (Just head) +> else if l < m then findMin l head =<< read (next head) +> else findMin l best =<< read (next head) +> findMin 10 first first + + The unlink and relink operations are from where Knuth got the name + "dancing links". So long as "a" does not change in between, the + relink call will undo the unlink call. Similarly, the unconver will + undo the changes of cover and unconverOthers will undo coverOthers. + +> unlink :: (a->STRef st a) -> (a->STRef st a) -> a -> (ST st) () +> unlink prev next a = do +> before <- read (prev a) +> after <- read (next a) +> write (next before) after +> write (prev after) before + +> relink :: (a->STRef st a) -> (a->STRef st a) -> a -> (ST st) () +> relink prev next a = do +> before <- read (prev a) +> after <- read (next a) +> write (next before) a +> write (prev after) a + +> cover :: (Head st) -> (ST st) () +> cover head = do +> unlink prev next head +> let eachDown rr = forEach right rr eachRight +> eachRight nn = do +> unlink up down nn +> modify (len $ getHead nn) pred +> forEach down (topNode head) eachDown + +> uncover :: (Head st) -> (ST st) () +> uncover head = do +> let eachUp rr = forEach left rr eachLeft +> eachLeft nn = do +> modify (len $ getHead nn) succ +> relink up down nn +> forEach up (topNode head) eachUp +> relink prev next head + +> coverOthers :: (Node st) -> (ST st) () +> coverOthers node = forEach right node (cover . getHead) + +> uncoverOthers :: (Node st) -> (ST st) () +> uncoverOthers node = forEach left node (uncover . getHead) + + A helper function for gdance: + +> choicesToSpec :: [(Node st)] -> Spec +> choicesToSpec = Spec . (map getHint) + + This is the heart of the algorithm. I have altered it to return only + the first solution, or produce an error if none is found. + + Knuth used several goto links to do what is done below with tail + recursion. + +> gdance :: (Head st) -> (ST st) Spec -- [Spec] +> gdance root = +> let +> forward choices = do +> maybeHead <- getBest root +> case maybeHead of +> Nothing -> if null choices +> then error "No choices in forward" -- return [] -- for [Spec] +> else do -- nextSols <- recover choices -- for [Spec] +> return $ (choicesToSpec choices) -- :nextSols -- for [Spec] +> Just head -> do cover head +> startRow <- readSTRef (down (topNode head)) +> advance (startRow:choices) +> +> advance choices@(newRow:oldChoices) = do +> let endOfRows = topNode (getHead newRow) +> if (newRow == endOfRows) +> then do uncover (getHead newRow) +> if (null oldChoices) +> then error "No choices in advance" -- return [] -- for [Spec] +> else recover oldChoices +> else do coverOthers newRow +> forward choices +> +> recover (oldRow:oldChoices) = do +> uncoverOthers oldRow +> newRow <- readSTRef (down oldRow) +> advance (newRow:oldChoices) +> +> in forward [] + + + Convert a text board into a Spec + +> parseBoard :: String -> Spec +> parseBoard s = Spec (zip rcs vs'check) +> where rcs :: [(R,C)] +> rcs = [ (R r,C c) | r <- rng, c <- rng ] +> isUnset c = (c=='.') || (c==' ') || (c=='0') +> isHint c = ('1'<=c) && (c<='9') +> cs = take 81 $ filter (\c -> isUnset c || isHint c) s +> vs :: [V] +> vs = map (\c -> if isUnset c then u else (V $ digitToInt c)) cs +> vs'check = if 81==length vs then vs else error ("parse of board failed\n"++s) + + This is quite useful as a utility function which partitions the list into groups of n elements. + Used by showSpec. + +> groupTake :: Int->[a]->[[a]] +> groupTake n b = unfoldr foo b +> where foo [] = Nothing +> foo b = Just (splitAt n b) + + Make a nice 2D ascii board from the Spec (not used at the moment) + +> showSpec :: Spec -> String +> showSpec spec = let pa = parse spec +> g = groupTake 9 (map (\(V v) -> if v == 0 then '.' else intToDigit v) $ elems pa) +> addV line = concat $ intersperse "|" (groupTake 3 line) +> addH list = concat $ intersperse ["---+---+---"] (groupTake 3 list) +> in unlines $ addH (map addV g) + + One line display + +> showCompact spec = map (\(V v) -> intToDigit v) (elems (parse spec)) + + The main routine is designed to handle the input from http://www.csse.uwa.edu.au/~gordon/sudoku17 + +> main = do +> all <- getContents +> let puzzles = zip [1..] (map parseBoard (lines all)) +> root <- stToIO initHA +> let act :: (Int,Spec) -> IO () +> act (i,spec) = do +> answer <- stToIO (do initRoot root spec +> answer <- gdance (fst root) +> resetRoot root +> return answer) +> print (i,showCompact answer) +> mapM_ act puzzles + +> inits' xn@(_:_) = zipWith take [0..] $ map (const xn) $ undefined:xn +> inits' _ = undefined + +---tokens--- +' A Sukodku solver by Chris Kuklewicz (haskell (at) list (dot) mightyreason (dot) com)\n' Text + +' The usual BSD license applies, copyright 2006.\n' Text + +' Uploaded to HaskellWiki as DancingSudoku.lhs\n' Text + +'\n' Text + +' I compile on a powerbook G4 (Mac OS X, ghc 6.4.2) using\n' Text + +' ghc -optc-O3 -funbox-strict-fields -O2 --make -fglasgow-exts\n' Text + +'\n' Text + +" This is a translation of Knuth's GDANCE from dance.w / dance.c\n" Text + +'\n' Text + +' http://www-cs-faculty.stanford.edu/~uno/preprints.html\n' Text + +' http://www-cs-faculty.stanford.edu/~uno/programs.html\n' Text + +' http://en.wikipedia.org/wiki/Dancing_Links\n' Text + +'\n' Text + +' I have an older verison that uses lazy ST to return the solutions on\n' Text + +' demand, which was more useful when trying to generate new puzzles to\n' Text + +' solve.\n' Text + +'\n' Text + +'> ' Comment.Special +'module' Keyword.Reserved +' ' Text +'Main' Name.Namespace +' ' Text +'where' Keyword.Reserved +'\n' Text + +'\n' Text + +'> ' Comment.Special +'import' Keyword.Reserved +' ' Text +'Prelude' Name.Namespace +' ' Text +'hiding' Keyword +' ' Text +'(' Punctuation +'read' Name.Function +')' Punctuation +'\n' Text + +'> ' Comment.Special +'import' Keyword.Reserved +' ' Text +'Control.Monad' Name.Namespace +'\n' Text + +'> ' Comment.Special +'import' Keyword.Reserved +' ' Text +'Control.Monad.Fix' Name.Namespace +'\n' Text + +'> ' Comment.Special +'import' Keyword.Reserved +' ' Text +'Data.Array.IArray' Name.Namespace +'\n' Text + +'> ' Comment.Special +'import' Keyword.Reserved +' ' Text +'Control.Monad.ST.Strict' Name.Namespace +'\n' Text + +'> ' Comment.Special +'import' Keyword.Reserved +' ' Text +'Data.STRef.Strict' Name.Namespace +'\n' Text + +'> ' Comment.Special +'import' Keyword.Reserved +' ' Text +'Data.Char' Name.Namespace +'(' Punctuation +'intToDigit' Name +',' Punctuation +'digitToInt' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'import' Keyword.Reserved +' ' Text +'Data.List' Name.Namespace +'(' Punctuation +'unfoldr' Name +',' Punctuation +'intersperse' Name +',' Punctuation +'inits' Name +')' Punctuation +'\n' Text + +'\n' Text + +'> ' Comment.Special +'new' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'newSTRef' Name +'\n' Text + +'> ' Comment.Special +'{-' Comment.Multiline +'# INLINE new #' Comment.Multiline +'-}' Comment.Multiline +'\n' Text + +'> ' Comment.Special +'read' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'readSTRef' Name +'\n' Text + +'> ' Comment.Special +'{-' Comment.Multiline +'# INLINE read #' Comment.Multiline +'-}' Comment.Multiline +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'writeSTRef' Name +'\n' Text + +'> ' Comment.Special +'{-' Comment.Multiline +'# INLINE write #' Comment.Multiline +'-}' Comment.Multiline +'\n' Text + +'> ' Comment.Special +'modify' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'modifySTRef' Name +'\n' Text + +'> ' Comment.Special +'{-' Comment.Multiline +'# INLINE modify #' Comment.Multiline +'-}' Comment.Multiline +'\n' Text + +'\n' Text + +' Data types to prevent mixing different index and value types\n' Text + +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'A' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'Int' Keyword.Type +'\n' Text + +'> ' Comment.Special +'newtype' Keyword.Reserved +' ' Text +'R' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'R' Keyword.Type +' ' Text +'A' Keyword.Type +' ' Text +'deriving' Keyword.Reserved +' ' Text +'(' Punctuation +'Show' Keyword.Type +',' Punctuation +'Read' Keyword.Type +',' Punctuation +'Eq' Keyword.Type +',' Punctuation +'Ord' Keyword.Type +',' Punctuation +'Ix' Keyword.Type +',' Punctuation +'Enum' Keyword.Type +')' Punctuation +'\n' Text + +'> ' Comment.Special +'newtype' Keyword.Reserved +' ' Text +'C' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'C' Keyword.Type +' ' Text +'A' Keyword.Type +' ' Text +'deriving' Keyword.Reserved +' ' Text +'(' Punctuation +'Show' Keyword.Type +',' Punctuation +'Read' Keyword.Type +',' Punctuation +'Eq' Keyword.Type +',' Punctuation +'Ord' Keyword.Type +',' Punctuation +'Ix' Keyword.Type +',' Punctuation +'Enum' Keyword.Type +')' Punctuation +'\n' Text + +'> ' Comment.Special +'newtype' Keyword.Reserved +' ' Text +'V' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'V' Keyword.Type +' ' Text +'A' Keyword.Type +' ' Text +'deriving' Keyword.Reserved +' ' Text +'(' Punctuation +'Show' Keyword.Type +',' Punctuation +'Read' Keyword.Type +',' Punctuation +'Eq' Keyword.Type +',' Punctuation +'Ord' Keyword.Type +',' Punctuation +'Ix' Keyword.Type +',' Punctuation +'Enum' Keyword.Type +')' Punctuation +'\n' Text + +'> ' Comment.Special +'newtype' Keyword.Reserved +' ' Text +'B' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'B' Keyword.Type +' ' Text +'A' Keyword.Type +' ' Text +'deriving' Keyword.Reserved +' ' Text +'(' Punctuation +'Show' Keyword.Type +',' Punctuation +'Read' Keyword.Type +',' Punctuation +'Eq' Keyword.Type +',' Punctuation +'Ord' Keyword.Type +',' Punctuation +'Ix' Keyword.Type +',' Punctuation +'Enum' Keyword.Type +')' Punctuation +'\n' Text + +'\n' Text + +' Sudoku also has block constraints, so we want to look up a block\n' Text + +' index in an array:\n' Text + +'\n' Text + +'> ' Comment.Special +'lookupBlock' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Array' Keyword.Type +' ' Text +'(' Punctuation +'R' Keyword.Type +',' Punctuation +'C' Keyword.Type +')' Punctuation +' ' Text +'B' Keyword.Type +'\n' Text + +'> ' Comment.Special +'lookupBlock' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'listArray' Name +' ' Text +'bb' Name +' ' Text +'[' Punctuation +' ' Text +'toBlock' Name +' ' Text +'ij' Name +' ' Text +'|' Operator +' ' Text +'ij' Name +' ' Text +'<-' Operator.Word +' ' Text +'range' Name +' ' Text +'bb' Name +' ' Text +']' Punctuation +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'ra' Name +' ' Text +'::' Operator.Word +' ' Text +'Array' Keyword.Type +' ' Text +'Int' Keyword.Type +' ' Text +'B' Keyword.Type +'\n' Text + +'> ' Comment.Special +'ra' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'listArray' Name +' ' Text +'(' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'pred' Name +' ' Text +'(' Punctuation +'rangeSize' Name +' ' Text +'b' Name +')' Punctuation +')' Punctuation +' ' Text +'[' Punctuation +'B' Keyword.Type +' ' Text +'(' Punctuation +'fst' Name +' ' Text +'b' Name +')' Punctuation +' ' Text +'..' Operator +' ' Text +'B' Keyword.Type +' ' Text +'(' Punctuation +'snd' Name +' ' Text +'b' Name +')' Punctuation +']' Punctuation +'\n' Text + +'> ' Comment.Special +'toBlock' Name.Function +' ' Text +'(' Punctuation +'R' Keyword.Type +' ' Text +'i' Name +',' Punctuation +'C' Keyword.Type +' ' Text +'j' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'ra' Name +' ' Text +'!' Operator +' ' Text +'(' Punctuation +' ' Text +'(' Punctuation +'div' Name +' ' Text +'(' Punctuation +'index' Name +' ' Text +'b' Name +' ' Text +'j' Name +')' Punctuation +' ' Text +'3' Literal.Number.Integer +')' Punctuation +'+' Operator +'3' Literal.Number.Integer +'*' Operator +'(' Punctuation +'div' Name +' ' Text +'(' Punctuation +'index' Name +' ' Text +'b' Name +' ' Text +'i' Name +')' Punctuation +' ' Text +'3' Literal.Number.Integer +')' Punctuation +' ' Text +')' Punctuation +'\n' Text + +'\n' Text + +" The values for an unknown location is 'u'.\n" Text + +' The bound and range are given by b and rng. And bb is a 2D bound.\n' Text + +'\n' Text + +'> ' Comment.Special +'u' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'V' Keyword.Type +' ' Text +'0' Literal.Number.Integer +' ' Text +'-- unknown value' Comment.Single +'\n' Text + +'> ' Comment.Special +'b' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Int' Keyword.Type +',' Punctuation +'Int' Keyword.Type +')' Punctuation +'\n' Text + +'> ' Comment.Special +'b' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +')' Punctuation +' ' Text +'-- min and max bounds' Comment.Single +'\n' Text + +'> ' Comment.Special +'rng' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'enumFromTo' Name +' ' Text +'(' Punctuation +'fst' Name +' ' Text +'b' Name +')' Punctuation +' ' Text +'(' Punctuation +'snd' Name +' ' Text +'b' Name +')' Punctuation +' ' Text +"-- list from '1' to '9'" Comment.Single +'\n' Text + +'> ' Comment.Special +'bb' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'(' Punctuation +'R' Keyword.Type +' ' Text +'(' Punctuation +'fst' Name +' ' Text +'b' Name +')' Punctuation +',' Punctuation +'C' Keyword.Type +' ' Text +'(' Punctuation +'fst' Name +' ' Text +'b' Name +')' Punctuation +')' Punctuation +',' Punctuation +'(' Punctuation +'R' Keyword.Type +' ' Text +'(' Punctuation +'snd' Name +' ' Text +'b' Name +')' Punctuation +',' Punctuation +'C' Keyword.Type +' ' Text +'(' Punctuation +'snd' Name +' ' Text +'b' Name +')' Punctuation +')' Punctuation +')' Punctuation +'\n' Text + +'\n' Text + +' A Spec can be turned into a parsed array with ease:\n' Text + +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'Hint' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'(' Punctuation +'R' Keyword.Type +',' Punctuation +'C' Keyword.Type +')' Punctuation +',' Punctuation +'V' Keyword.Type +')' Punctuation +'\n' Text + +'> ' Comment.Special +'newtype' Keyword.Reserved +' ' Text +'Spec' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'Spec' Keyword.Type +' ' Text +'[' Punctuation +'Hint' Keyword.Type +']' Punctuation +' ' Text +'deriving' Keyword.Reserved +' ' Text +'(' Punctuation +'Eq' Keyword.Type +',' Punctuation +'Show' Keyword.Type +')' Punctuation +'\n' Text + +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'PA' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'Array' Keyword.Type +' ' Text +'(' Punctuation +'R' Keyword.Type +',' Punctuation +'C' Keyword.Type +')' Punctuation +' ' Text +'V' Keyword.Type +'\n' Text + +'\n' Text + +'> ' Comment.Special +'parse' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Spec' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'PA' Keyword.Type +'\n' Text + +'> ' Comment.Special +'parse' Name.Function +' ' Text +'(' Punctuation +'Spec' Keyword.Type +' ' Text +'parsed' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'let' Keyword.Reserved +' ' Text +'acc' Name +' ' Text +'old' Name +' ' Text +'new' Name +' ' Text +'=' Operator.Word +' ' Text +'new' Name +'\n' Text + +'> ' Comment.Special +'in' Keyword.Reserved +' ' Text +'accumArray' Name +' ' Text +'acc' Name +' ' Text +'u' Name +' ' Text +'bb' Name +' ' Text +'parsed' Name +'\n' Text + +'\n' Text + +' The dancing links algorithm depends on a sparse 2D node structure.\n' Text + +' Each column represents a constraint. Each row represents a Hint.\n' Text + +' The number of possible hints is 9x9x9 = 271\n' Text + +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'(' Punctuation +'MutInt' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'STRef' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'Int' Keyword.Type +'\n' Text + +'\n' Text + +' The pointer types:\n' Text + +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'(' Punctuation +'NodePtr' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'STRef' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'(' Punctuation +'HeadPtr' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'STRef' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +'\n' Text + +'\n' Text + +" The structures is a 2D grid of nodes, with Col's on the top of\n" Text + +' columns and a sparse collection of nodes. Note that topNode of Head\n' Text + +' is not a strict field. This is because the topNode needs to refer to\n' Text + +' the Head, and they are both created monadically.\n' Text + +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'HeadName' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'Int' Keyword.Type +',' Punctuation +'Int' Keyword.Type +',' Punctuation +'Int' Keyword.Type +')' Punctuation +' ' Text +'-- see below for meaning' Comment.Single +'\n' Text + +'\n' Text + +'> ' Comment.Special +'data' Keyword.Reserved +' ' Text +'Head' Keyword.Type +' ' Text +'st' Name +' ' Text +'=' Operator.Word +' ' Text +'Head' Keyword.Type +' ' Text +'{' Punctuation +'headName' Name +'::' Operator.Word +' ' Text +'!' Operator +'HeadName' Keyword.Type +'\n' Text + +'> ' Comment.Special +',' Punctuation +'topNode' Name +'::' Operator.Word +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'-- header node for this column' Comment.Single +'\n' Text + +'> ' Comment.Special +',' Punctuation +'len' Name +'::' Operator.Word +' ' Text +'!' Operator +'(' Punctuation +'MutInt' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'-- number of nodes below this head' Comment.Single +'\n' Text + +'> ' Comment.Special +',' Punctuation +'next' Name +',' Punctuation +'prev' Name +'::' Operator.Word +' ' Text +'!' Operator +'(' Punctuation +'HeadPtr' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'-- doubly-linked list' Comment.Single +'\n' Text + +'> ' Comment.Special +'}' Punctuation +'\n' Text + +'\n' Text + +'> ' Comment.Special +'data' Keyword.Reserved +' ' Text +'Node' Keyword.Type +' ' Text +'st' Name +' ' Text +'=' Operator.Word +' ' Text +'Node' Keyword.Type +' ' Text +'{' Punctuation +'getHint' Name +'::' Operator.Word +' ' Text +'!' Operator +'Hint' Keyword.Type +'\n' Text + +'> ' Comment.Special +',' Punctuation +'getHead' Name +'::' Operator.Word +' ' Text +'!' Operator +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'-- head for the column this node is in' Comment.Single +'\n' Text + +'> ' Comment.Special +',' Punctuation +'up' Name +',' Punctuation +'down' Name +',' Punctuation +'left' Name +',' Punctuation +'right' Name +' ' Text +'::' Operator.Word +' ' Text +'!' Operator +'(' Punctuation +'NodePtr' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'-- two doubly-linked lists' Comment.Single +'\n' Text + +'> ' Comment.Special +'}' Punctuation +'\n' Text + +'\n' Text + +'> ' Comment.Special +'instance' Keyword.Reserved +' ' Text +'Eq' Keyword.Type +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'where' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'a' Name.Function +' ' Text +'==' Operator +' ' Text +'b' Name +' ' Text +'=' Operator.Word +' ' Text +'headName' Name +' ' Text +'a' Name +' ' Text +'==' Operator +' ' Text +'headName' Name +' ' Text +'b' Name +'\n' Text + +'\n' Text + +'> ' Comment.Special +'instance' Keyword.Reserved +' ' Text +'Eq' Keyword.Type +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'where' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'a' Name.Function +' ' Text +'==' Operator +' ' Text +'b' Name +' ' Text +'=' Operator.Word +' ' Text +'up' Name +' ' Text +'a' Name +' ' Text +'==' Operator +' ' Text +'up' Name +' ' Text +'b' Name +'\n' Text + +'\n' Text + +" To initialize the structures is a bit tedious. Knuth's code reads in\n" Text + +' the problem description from a data file and builds the structure\n' Text + +' based on that. Rather than short strings, I will use HeadName as the\n' Text + +' identifier.\n' Text + +' \n' Text + +' The columns are (0,4,5) for nodes that put some value in Row 4 Col 5\n' Text + +' (1,2,3) for nodes that put Val 3 in Row 2 and some column\n' Text + +' (2,7,4) for nodes that put Val 4 in Col 7 and some row\n' Text + +' (3,1,8) for nodes that put Val 8 in some (row,column) in Block 1\n' Text + +'\n' Text + +' The first head is (0,0,0) which is the root. The non-root head data\n' Text + +' will be put in an array with the HeadName as an index.\n' Text + +'\n' Text + +'> ' Comment.Special +'headNames' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'[' Punctuation +'HeadName' Keyword.Type +']' Punctuation +'\n' Text + +'> ' Comment.Special +'headNames' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'let' Keyword.Reserved +' ' Text +'names' Name +' ' Text +'=' Operator.Word +' ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +']' Punctuation +' \n' Text + +'> ' Comment.Special +'in' Keyword.Reserved +' ' Text +'(' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +')' Punctuation +':' Keyword.Type +'[' Punctuation +' ' Text +'(' Punctuation +'l' Name +',' Punctuation +'i' Name +',' Punctuation +'j' Name +')' Punctuation +' ' Text +'|' Operator +' ' Text +'l' Name +'<-' Operator.Word +'names' Name +',' Punctuation +'i' Name +'<-' Operator.Word +'rng' Name +',' Punctuation +'j' Name +'<-' Operator.Word +'rng' Name +']' Punctuation +'\n' Text + +'\n' Text + +' A "row" of left-right linked nodes is a move. It is defined by a\n' Text + +' list of head names.\n' Text + +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'Move' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Hint' Keyword.Type +',' Punctuation +'HeadName' Keyword.Type +')' Punctuation +']' Punctuation +'\n' Text + +'\n' Text + +' Initial hints are enforced by making them the only legal move for\n' Text + +" that location. Blank entries with value 'u = V 0' have a move for\n" Text + +' all possible values [V 1..V 9].\n' Text + +'\n' Text + +'> ' Comment.Special +'parseSpec' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Spec' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'Move' Keyword.Type +']' Punctuation +'\n' Text + +'> ' Comment.Special +'parseSpec' Name.Function +' ' Text +'spec' Name +' ' Text +'=' Operator.Word +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'rowsFrom' Name +' ' Text +'::' Operator.Word +' ' Text +'Hint' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'Move' Keyword.Type +']' Punctuation +'\n' Text + +'> ' Comment.Special +'rowsFrom' Name.Function +' ' Text +'(' Punctuation +'rc' Name +'@' Operator +'(' Punctuation +'R' Keyword.Type +' ' Text +'r' Name +',' Punctuation +'C' Keyword.Type +' ' Text +'c' Name +')' Punctuation +',' Punctuation +'mv' Name +'@' Operator +'(' Punctuation +'V' Keyword.Type +' ' Text +"v'" Name +')' Punctuation +')' Punctuation +' ' Text +'=' Operator.Word +' \n' Text + +'> ' Comment.Special +'if' Keyword.Reserved +' ' Text +'mv' Name +' ' Text +'==' Operator +' ' Text +'u' Name +' ' Text +'then' Keyword.Reserved +' ' Text +'[' Punctuation +' ' Text +'rsyms' Name +' ' Text +'v' Name +' ' Text +'|' Operator +' ' Text +'v' Name +' ' Text +'<-' Operator.Word +' ' Text +'rng' Name +' ' Text +']' Punctuation +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'[' Punctuation +' ' Text +'rsyms' Name +' ' Text +"v'" Name +' ' Text +']' Punctuation +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'(' Punctuation +'B' Keyword.Type +' ' Text +'b' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'lookupBlock' Name +' ' Text +'!' Operator +' ' Text +'rc' Name +'\n' Text + +'> ' Comment.Special +'rsyms' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'A' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'Move' Keyword.Type +'\n' Text + +'> ' Comment.Special +'rsyms' Name.Function +' ' Text +'v' Name +' ' Text +'=' Operator.Word +' ' Text +'map' Name +' ' Text +'(' Punctuation +' ' Text +'(' Punctuation +',' Punctuation +')' Punctuation +' ' Text +'(' Punctuation +'rc' Name +',' Punctuation +'V' Keyword.Type +' ' Text +'v' Name +')' Punctuation +' ' Text +')' Punctuation +' ' Text +'[' Punctuation +'(' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'r' Name +',' Punctuation +'c' Name +')' Punctuation +',' Punctuation +'(' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'r' Name +',' Punctuation +'v' Name +')' Punctuation +',' Punctuation +'(' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'c' Name +',' Punctuation +'v' Name +')' Punctuation +',' Punctuation +'(' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'b' Name +',' Punctuation +'v' Name +')' Punctuation +']' Punctuation +'\n' Text + +'> ' Comment.Special +'in' Keyword.Reserved +' ' Text +'concatMap' Name +' ' Text +'rowsFrom' Name +' ' Text +'(' Punctuation +'assocs' Name +' ' Text +'(' Punctuation +'parse' Name +' ' Text +'spec' Name +')' Punctuation +')' Punctuation +'\n' Text + +'\n' Text + +' mkDList creates doubly linked lists using a monadic smart\n' Text + +' constructor and the recursive "mdo" notation as documented at\n' Text + +' http://www.haskell.org/ghc/docs/latest/html/users_guide/syntax-extns.html#mdo-notation\n' Text + +' http://www.cse.ogi.edu/PacSoft/projects/rmb/\n' Text + +'\n' Text + +' For more fun with this, see the wiki page at\n' Text + +' http://haskell.org/hawiki/TyingTheKnot\n' Text + +'\n' Text + +'> ' Comment.Special +'mkDList' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'MonadFix' Keyword.Type +' ' Text +'m' Name +')' Punctuation +' ' Text +'=>' Operator.Word +' ' Text +'(' Punctuation +'b' Name +' ' Text +'->' Operator.Word +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'b' Name +' ' Text +'->' Operator.Word +' ' Text +'m' Name +' ' Text +'b' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'a' Name +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'m' Name +' ' Text +'b' Name +'\n' Text + +'> ' Comment.Special +'mkDList' Name.Function +' ' Text +'_' Keyword.Reserved +' ' Text +'[]' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'error' Name.Exception +' ' Text +'"' Literal.String +'must have at least one element' Literal.String +'"' Literal.String +'\n' Text + +'> ' Comment.Special +'mkDList' Name.Function +' ' Text +'mkNode' Name +' ' Text +'xs' Name +' ' Text +'=' Operator.Word +' ' Text +'mdo' Name +' ' Text +'(' Punctuation +'first' Name +',' Punctuation +'last' Name +')' Punctuation +' ' Text +'<-' Operator.Word +' ' Text +'go' Name +' ' Text +'last' Name +' ' Text +'xs' Name +' ' Text +'first' Name +'\n' Text + +'> ' Comment.Special +'return' Name.Function +' ' Text +'first' Name +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'go' Name +' ' Text +'prev' Name +' ' Text +'[]' Keyword.Type +' ' Text +'next' Name +' ' Text +'=' Operator.Word +' ' Text +'return' Name +' ' Text +'(' Punctuation +'next' Name +',' Punctuation +'prev' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'go' Name.Function +' ' Text +'prev' Name +' ' Text +'(' Punctuation +'x' Name +':' Keyword.Type +'xs' Name +')' Punctuation +' ' Text +'next' Name +' ' Text +'=' Operator.Word +' ' Text +'mdo' Name +' ' Text +'this' Name +' ' Text +'<-' Operator.Word +' ' Text +'mkNode' Name +' ' Text +'prev' Name +' ' Text +'x' Name +' ' Text +'rest' Name +'\n' Text + +'> ' Comment.Special +'(' Punctuation +'rest' Name +',' Punctuation +'last' Name +')' Punctuation +' ' Text +'<-' Operator.Word +' ' Text +'go' Name +' ' Text +'this' Name +' ' Text +'xs' Name +' ' Text +'next' Name +'\n' Text + +'> ' Comment.Special +'return' Name.Function +' ' Text +'(' Punctuation +'this' Name +',' Punctuation +'last' Name +')' Punctuation +'\n' Text + +'\n' Text + +' toSimple takes a function and a header node and iterates (read . function)\n' Text + +' until the header is reached again, but does not return the header\n' Text + +' itself.\n' Text + +'\n' Text + +'> ' Comment.Special +'toSingle' Name.Function +' ' Text +'step' Name +' ' Text +'header' Name +' ' Text +'=' Operator.Word +' ' Text +'loop' Name +' ' Text +'=<<' Operator +' ' Text +'(' Punctuation +'read' Name +' ' Text +'.' Operator +' ' Text +'step' Name +')' Punctuation +' ' Text +'header' Name +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'loop' Name +' ' Text +'y' Name +' ' Text +'=' Operator.Word +' ' Text +'if' Keyword.Reserved +' ' Text +'header' Name +'/=' Operator +'y' Name +' ' Text +'then' Keyword.Reserved +' ' Text +'liftM' Name +' ' Text +'(' Punctuation +'y' Name +':' Keyword.Type +')' Punctuation +' ' Text +'(' Punctuation +'read' Name +' ' Text +'(' Punctuation +'step' Name +' ' Text +'y' Name +')' Punctuation +' ' Text +'>>=' Operator +' ' Text +'loop' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'return' Name +' ' Text +'[]' Keyword.Type +'\n' Text + +'> ' Comment.Special +'\n' Text + +'\n' Text + +' forEach is an optimization of (toSimple step header >>= mapM_ act)\n' Text + +'\n' Text + +'> ' Comment.Special +'forEach' Name.Function +' ' Text +'step' Name +' ' Text +'header' Name +' ' Text +'act' Name +' ' Text +'=' Operator.Word +' ' Text +'loop' Name +' ' Text +'=<<' Operator +' ' Text +'(' Punctuation +'read' Name +' ' Text +'.' Operator +' ' Text +'step' Name +')' Punctuation +' ' Text +'header' Name +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'loop' Name +' ' Text +'y' Name +' ' Text +'=' Operator.Word +' ' Text +'if' Keyword.Reserved +' ' Text +'header' Name +'/=' Operator +'y' Name +' ' Text +'then' Keyword.Reserved +' ' Text +'(' Punctuation +'act' Name +' ' Text +'y' Name +' ' Text +'>>' Operator +' ' Text +'(' Punctuation +'read' Name +' ' Text +'(' Punctuation +'step' Name +' ' Text +'y' Name +')' Punctuation +')' Punctuation +' ' Text +'>>=' Operator +' ' Text +'loop' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'return' Name +' ' Text +'()' Name.Builtin +'\n' Text + +'\n' Text + +' Now make the root node and all the head nodes. This also exploits mdo:\n' Text + +'\n' Text + +'> ' Comment.Special +'makeHeads' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'[' Punctuation +'HeadName' Keyword.Type +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'makeHeads' Name.Function +' ' Text +'names' Name +' ' Text +'=' Operator.Word +' ' Text +'mkDList' Name +' ' Text +'makeHead' Name +' ' Text +'names' Name +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'makeHead' Name +' ' Text +'before' Name +' ' Text +'name' Name +' ' Text +'after' Name +' ' Text +'=' Operator.Word +' ' Text +'mdo' Name +'\n' Text + +'> ' Comment.Special +'~' Operator +'newTopNode' Name +' ' Text +'<-' Operator.Word +' ' Text +'liftM4' Name +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'(' Punctuation +'(' Punctuation +'R' Keyword.Type +' ' Text +'0' Literal.Number.Integer +',' Punctuation +'C' Keyword.Type +' ' Text +'0' Literal.Number.Integer +')' Punctuation +',' Punctuation +'V' Keyword.Type +' ' Text +'0' Literal.Number.Integer +')' Punctuation +' ' Text +'newHead' Name +')' Punctuation +' ' Text +'(' Punctuation +'new' Name +' ' Text +'newTopNode' Name +')' Punctuation +' ' Text +'(' Punctuation +'new' Name +' ' Text +'newTopNode' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'(' Punctuation +'new' Name +' ' Text +'newTopNode' Name +')' Punctuation +' ' Text +'(' Punctuation +'new' Name +' ' Text +'newTopNode' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'newHead' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'liftM3' Name +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'name' Name +' ' Text +'newTopNode' Name +')' Punctuation +' \n' Text + +'> ' Comment.Special +'(' Punctuation +'new' Name +' ' Text +'0' Literal.Number.Integer +')' Punctuation +' ' Text +'(' Punctuation +'new' Name +' ' Text +'after' Name +')' Punctuation +' ' Text +'(' Punctuation +'new' Name +' ' Text +'before' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'return' Name.Function +' ' Text +'newHead' Name +'\n' Text + +'\n' Text + +' The Head nodes will be places in an array for easy lookup while building moves:\n' Text + +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'HArray' Keyword.Type +' ' Text +'st' Name +' ' Text +'=' Operator.Word +' ' Text +'Array' Keyword.Type +' ' Text +'HeadName' Keyword.Type +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'hBounds' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'(' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +')' Punctuation +',' Punctuation +'(' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +')' Punctuation +')' Punctuation +'\n' Text + +'> ' Comment.Special +'type' Keyword.Reserved +' ' Text +'Root' Keyword.Type +' ' Text +'st' Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +',' Punctuation +'HArray' Keyword.Type +' ' Text +'st' Name +')' Punctuation +'\n' Text + +'\n' Text + +' The addMove function creates the (four) nodes that represent a move and adds\n' Text + +' them to the data structure. The HArray in Root makes for a fast\n' Text + +' lookup of the Head data.\n' Text + +'\n' Text + +'> ' Comment.Special +'addMove' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'forall' Name +' ' Text +'st' Name +'.' Operator +' ' Text +'(' Punctuation +'Root' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'Move' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'addMove' Name.Function +' ' Text +'(' Punctuation +'_' Keyword.Reserved +',' Punctuation +'ha' Name +')' Punctuation +' ' Text +'move' Name +' ' Text +'=' Operator.Word +' ' Text +'mkDList' Name +' ' Text +'addNode' Name +' ' Text +'move' Name +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'addNode' Name +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'Hint' Keyword.Type +',' Punctuation +'HeadName' Keyword.Type +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'addNode' Name.Function +' ' Text +'before' Name +' ' Text +'(' Punctuation +'hint' Name +',' Punctuation +'name' Name +')' Punctuation +' ' Text +'after' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'head' Name +' ' Text +'=' Operator.Word +' ' Text +'ha' Name +' ' Text +'!' Operator +' ' Text +'name' Name +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'below' Name +' ' Text +'=' Operator.Word +' ' Text +'topNode' Name +' ' Text +'head' Name +'\n' Text + +'> ' Comment.Special +'above' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'read' Name +' ' Text +'(' Punctuation +'up' Name +' ' Text +'below' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'newNode' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'liftM4' Name +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'hint' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'(' Punctuation +'new' Name +' ' Text +'above' Name +')' Punctuation +' ' Text +'(' Punctuation +'new' Name +' ' Text +'below' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'(' Punctuation +'new' Name +' ' Text +'before' Name +')' Punctuation +' ' Text +'(' Punctuation +'new' Name +' ' Text +'after' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'down' Name +' ' Text +'above' Name +')' Punctuation +' ' Text +'newNode' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'up' Name +' ' Text +'below' Name +')' Punctuation +' ' Text +'newNode' Name +'\n' Text + +'> ' Comment.Special +'modify' Name.Function +' ' Text +'(' Punctuation +'len' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'succ' Name +'\n' Text + +'> ' Comment.Special +'l' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'read' Name +' ' Text +'(' Punctuation +'len' Name +' ' Text +'head' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'seq' Name.Function +' ' Text +'l' Name +' ' Text +'(' Punctuation +'return' Name +' ' Text +'newNode' Name +')' Punctuation +'\n' Text + +'\n' Text + +' Create the column headers, including the fast lookup array. These\n' Text + +' will be resused between puzzles.\n' Text + +'\n' Text + +'> ' Comment.Special +'initHA' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'(' Punctuation +'Root' Keyword.Type +' ' Text +'st' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'initHA' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'root' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'makeHeads' Name +' ' Text +'headNames' Name +'\n' Text + +'> ' Comment.Special +'heads' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'toSingle' Name +' ' Text +'next' Name +' ' Text +'root' Name +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'ha' Name +' ' Text +'=' Operator.Word +' ' Text +'array' Name +' ' Text +'hBounds' Name +' ' Text +'(' Punctuation +'zip' Name +' ' Text +'(' Punctuation +'map' Name +' ' Text +'headName' Name +' ' Text +'heads' Name +')' Punctuation +' ' Text +'heads' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'return' Name.Function +' ' Text +'(' Punctuation +'root' Name +',' Punctuation +'ha' Name +')' Punctuation +'\n' Text + +'\n' Text + +' Take the Root from initHA and a puzzle Spec and fill in all the Nodes.\n' Text + +'\n' Text + +'> ' Comment.Special +'initRoot' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Root' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'Spec' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'initRoot' Name.Function +' ' Text +'root' Name +' ' Text +'spec' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'moves' Name +' ' Text +'=' Operator.Word +' ' Text +'parseSpec' Name +' ' Text +'spec' Name +'\n' Text + +'> ' Comment.Special +'mapM_' Name.Function +' ' Text +'(' Punctuation +'addMove' Name +' ' Text +'root' Name +')' Punctuation +' ' Text +'moves' Name +'\n' Text + +'\n' Text + +' Return the column headers to their condition after initHA\n' Text + +'\n' Text + +'> ' Comment.Special +'resetRoot' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Root' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'resetRoot' Name.Function +' ' Text +'(' Punctuation +'root' Name +',' Punctuation +'ha' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'heads' Name +'@' Operator +'(' Punctuation +'first' Name +':' Keyword.Type +'_' Keyword.Reserved +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'elems' Name +' ' Text +'ha' Name +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'resetHead' Name +' ' Text +'head' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'len' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'0' Literal.Number.Integer +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'node' Name +' ' Text +'=' Operator.Word +' ' Text +'topNode' Name +' ' Text +'head' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'down' Name +' ' Text +'node' Name +')' Punctuation +' ' Text +'node' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'up' Name +' ' Text +'node' Name +')' Punctuation +' ' Text +'node' Name +'\n' Text + +'> ' Comment.Special +'reset' Name.Function +' ' Text +'(' Punctuation +'last' Name +':' Keyword.Type +'[]' Keyword.Type +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'prev' Name +' ' Text +'root' Name +')' Punctuation +' ' Text +'last' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'next' Name +' ' Text +'root' Name +')' Punctuation +' ' Text +'first' Name +'\n' Text + +'> ' Comment.Special +'reset' Name.Function +' ' Text +'(' Punctuation +'before' Name +':' Keyword.Type +'xs' Name +'@' Operator +'(' Punctuation +'head' Name +':' Keyword.Type +'[]' Keyword.Type +')' Punctuation +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'resetHead' Name.Function +' ' Text +'head' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'prev' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'before' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'next' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'root' Name +'\n' Text + +'> ' Comment.Special +'reset' Name.Function +' ' Text +'xs' Name +'\n' Text + +'> ' Comment.Special +'reset' Name.Function +' ' Text +'(' Punctuation +'before' Name +':' Keyword.Type +'xs' Name +'@' Operator +'(' Punctuation +'head' Name +':' Keyword.Type +'after' Name +':' Keyword.Type +'_' Keyword.Reserved +')' Punctuation +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'resetHead' Name.Function +' ' Text +'head' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'prev' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'before' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'next' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'after' Name +'\n' Text + +'> ' Comment.Special +'reset' Name.Function +' ' Text +'xs' Name +'\n' Text + +'> ' Comment.Special +'reset' Name.Function +' ' Text +'(' Punctuation +'root' Name +':' Keyword.Type +'heads' Name +')' Punctuation +'\n' Text + +'\n' Text + +' getBest iterates over the unmet constraints (i.e. the Head that are\n' Text + +' reachable from root). It locates the one with the lowest number of\n' Text + +' possible moves that will solve it, aborting early if it finds 0 or 1\n' Text + +' moves.\n' Text + +'\n' Text + +'> ' Comment.Special +'getBest' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'(' Punctuation +'Maybe' Keyword.Type +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +')' Punctuation +'\n' Text + +'> ' Comment.Special +'getBest' Name.Function +' ' Text +'root' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'first' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'read' Name +' ' Text +'(' Punctuation +'next' Name +' ' Text +'root' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'if' Keyword.Reserved +' ' Text +'first' Name +' ' Text +'==' Operator +' ' Text +'root' Name +' ' Text +'then' Keyword.Reserved +' ' Text +'return' Name +' ' Text +'Nothing' Keyword.Type +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'findMin' Name +' ' Text +'m' Name +' ' Text +'best' Name +' ' Text +'head' Name +' ' Text +'|' Operator +' ' Text +'head' Name +' ' Text +'==' Operator +' ' Text +'root' Name +' ' Text +'=' Operator.Word +' ' Text +'return' Name +' ' Text +'(' Punctuation +'Just' Keyword.Type +' ' Text +'best' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'|' Operator +' ' Text +'otherwise' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'l' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'read' Name +' ' Text +'(' Punctuation +'len' Name +' ' Text +'head' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'if' Keyword.Reserved +' ' Text +'l' Name +' ' Text +'<=' Operator +' ' Text +'1' Literal.Number.Integer +' ' Text +'then' Keyword.Reserved +' ' Text +'return' Name +' ' Text +'(' Punctuation +'Just' Keyword.Type +' ' Text +'head' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'if' Keyword.Reserved +' ' Text +'l' Name +' ' Text +'<' Operator +' ' Text +'m' Name +' ' Text +'then' Keyword.Reserved +' ' Text +'findMin' Name +' ' Text +'l' Name +' ' Text +'head' Name +' ' Text +'=<<' Operator +' ' Text +'read' Name +' ' Text +'(' Punctuation +'next' Name +' ' Text +'head' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'findMin' Name +' ' Text +'l' Name +' ' Text +'best' Name +' ' Text +'=<<' Operator +' ' Text +'read' Name +' ' Text +'(' Punctuation +'next' Name +' ' Text +'head' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'findMin' Name.Function +' ' Text +'10' Literal.Number.Integer +' ' Text +'first' Name +' ' Text +'first' Name +'\n' Text + +'\n' Text + +' The unlink and relink operations are from where Knuth got the name\n' Text + +' "dancing links". So long as "a" does not change in between, the\n' Text + +' relink call will undo the unlink call. Similarly, the unconver will\n' Text + +' undo the changes of cover and unconverOthers will undo coverOthers.\n' Text + +'\n' Text + +'> ' Comment.Special +'unlink' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'a' Name +'->' Operator.Word +'STRef' Keyword.Type +' ' Text +'st' Name +' ' Text +'a' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'a' Name +'->' Operator.Word +'STRef' Keyword.Type +' ' Text +'st' Name +' ' Text +'a' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'unlink' Name.Function +' ' Text +'prev' Name +' ' Text +'next' Name +' ' Text +'a' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'before' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'read' Name +' ' Text +'(' Punctuation +'prev' Name +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'after' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'read' Name +' ' Text +'(' Punctuation +'next' Name +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'next' Name +' ' Text +'before' Name +')' Punctuation +' ' Text +'after' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'prev' Name +' ' Text +'after' Name +')' Punctuation +' ' Text +'before' Name +'\n' Text + +'\n' Text + +'> ' Comment.Special +'relink' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'a' Name +'->' Operator.Word +'STRef' Keyword.Type +' ' Text +'st' Name +' ' Text +'a' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'a' Name +'->' Operator.Word +'STRef' Keyword.Type +' ' Text +'st' Name +' ' Text +'a' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'relink' Name.Function +' ' Text +'prev' Name +' ' Text +'next' Name +' ' Text +'a' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'before' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'read' Name +' ' Text +'(' Punctuation +'prev' Name +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'after' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'read' Name +' ' Text +'(' Punctuation +'next' Name +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'next' Name +' ' Text +'before' Name +')' Punctuation +' ' Text +'a' Name +'\n' Text + +'> ' Comment.Special +'write' Name.Function +' ' Text +'(' Punctuation +'prev' Name +' ' Text +'after' Name +')' Punctuation +' ' Text +'a' Name +'\n' Text + +'\n' Text + +'> ' Comment.Special +'cover' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'cover' Name.Function +' ' Text +'head' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'unlink' Name.Function +' ' Text +'prev' Name +' ' Text +'next' Name +' ' Text +'head' Name +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'eachDown' Name +' ' Text +'rr' Name +' ' Text +'=' Operator.Word +' ' Text +'forEach' Name +' ' Text +'right' Name +' ' Text +'rr' Name +' ' Text +'eachRight' Name +'\n' Text + +'> ' Comment.Special +'eachRight' Name.Function +' ' Text +'nn' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'unlink' Name.Function +' ' Text +'up' Name +' ' Text +'down' Name +' ' Text +'nn' Name +'\n' Text + +'> ' Comment.Special +'modify' Name.Function +' ' Text +'(' Punctuation +'len' Name +' ' Text +'$' Operator +' ' Text +'getHead' Name +' ' Text +'nn' Name +')' Punctuation +' ' Text +'pred' Name +'\n' Text + +'> ' Comment.Special +'forEach' Name.Function +' ' Text +'down' Name +' ' Text +'(' Punctuation +'topNode' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'eachDown' Name +'\n' Text + +'\n' Text + +'> ' Comment.Special +'uncover' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'uncover' Name.Function +' ' Text +'head' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'eachUp' Name +' ' Text +'rr' Name +' ' Text +'=' Operator.Word +' ' Text +'forEach' Name +' ' Text +'left' Name +' ' Text +'rr' Name +' ' Text +'eachLeft' Name +'\n' Text + +'> ' Comment.Special +'eachLeft' Name.Function +' ' Text +'nn' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'modify' Name.Function +' ' Text +'(' Punctuation +'len' Name +' ' Text +'$' Operator +' ' Text +'getHead' Name +' ' Text +'nn' Name +')' Punctuation +' ' Text +'succ' Name +'\n' Text + +'> ' Comment.Special +'relink' Name.Function +' ' Text +'up' Name +' ' Text +'down' Name +' ' Text +'nn' Name +'\n' Text + +'> ' Comment.Special +'forEach' Name.Function +' ' Text +'up' Name +' ' Text +'(' Punctuation +'topNode' Name +' ' Text +'head' Name +')' Punctuation +' ' Text +'eachUp' Name +'\n' Text + +'> ' Comment.Special +'relink' Name.Function +' ' Text +'prev' Name +' ' Text +'next' Name +' ' Text +'head' Name +'\n' Text + +'\n' Text + +'> ' Comment.Special +'coverOthers' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'coverOthers' Name.Function +' ' Text +'node' Name +' ' Text +'=' Operator.Word +' ' Text +'forEach' Name +' ' Text +'right' Name +' ' Text +'node' Name +' ' Text +'(' Punctuation +'cover' Name +' ' Text +'.' Operator +' ' Text +'getHead' Name +')' Punctuation +'\n' Text + +'\n' Text + +'> ' Comment.Special +'uncoverOthers' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'uncoverOthers' Name.Function +' ' Text +'node' Name +' ' Text +'=' Operator.Word +' ' Text +'forEach' Name +' ' Text +'left' Name +' ' Text +'node' Name +' ' Text +'(' Punctuation +'uncover' Name +' ' Text +'.' Operator +' ' Text +'getHead' Name +')' Punctuation +'\n' Text + +'\n' Text + +' A helper function for gdance:\n' Text + +'\n' Text + +'> ' Comment.Special +'choicesToSpec' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Node' Keyword.Type +' ' Text +'st' Name +')' Punctuation +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'Spec' Keyword.Type +'\n' Text + +'> ' Comment.Special +'choicesToSpec' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'Spec' Keyword.Type +' ' Text +'.' Operator +' ' Text +'(' Punctuation +'map' Name +' ' Text +'getHint' Name +')' Punctuation +'\n' Text + +'\n' Text + +' This is the heart of the algorithm. I have altered it to return only\n' Text + +' the first solution, or produce an error if none is found.\n' Text + +'\n' Text + +' Knuth used several goto links to do what is done below with tail\n' Text + +' recursion.\n' Text + +'\n' Text + +'> ' Comment.Special +'gdance' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Head' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'ST' Keyword.Type +' ' Text +'st' Name +')' Punctuation +' ' Text +'Spec' Keyword.Type +' ' Text +'-- [Spec]' Comment.Single +'\n' Text + +'> ' Comment.Special +'gdance' Name.Function +' ' Text +'root' Name +' ' Text +'=' Operator.Word +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'forward' Name.Function +' ' Text +'choices' Name +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'maybeHead' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'getBest' Name +' ' Text +'root' Name +'\n' Text + +'> ' Comment.Special +'case' Keyword.Reserved +' ' Text +'maybeHead' Name +' ' Text +'of' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'Nothing' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'if' Keyword.Reserved +' ' Text +'null' Name +' ' Text +'choices' Name +'\n' Text + +'> ' Comment.Special +'then' Keyword.Reserved +' ' Text +'error' Name.Exception +' ' Text +'"' Literal.String +'No choices in forward' Literal.String +'"' Literal.String +' ' Text +'-- return [] -- for [Spec]' Comment.Single +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'do' Keyword.Reserved +' ' Text +'-- nextSols <- recover choices -- for [Spec]' Comment.Single +'\n' Text + +'> ' Comment.Special +'return' Name.Function +' ' Text +'$' Operator +' ' Text +'(' Punctuation +'choicesToSpec' Name +' ' Text +'choices' Name +')' Punctuation +' ' Text +'-- :nextSols -- for [Spec]' Comment.Single +'\n' Text + +'> ' Comment.Special +'Just' Keyword.Type +' ' Text +'head' Name +' ' Text +'->' Operator.Word +' ' Text +'do' Keyword.Reserved +' ' Text +'cover' Name +' ' Text +'head' Name +'\n' Text + +'> ' Comment.Special +'startRow' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'readSTRef' Name +' ' Text +'(' Punctuation +'down' Name +' ' Text +'(' Punctuation +'topNode' Name +' ' Text +'head' Name +')' Punctuation +')' Punctuation +'\n' Text + +'> ' Comment.Special +'advance' Name.Function +' ' Text +'(' Punctuation +'startRow' Name +':' Keyword.Type +'choices' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'\n' Text + +'> ' Comment.Special +'advance' Name.Function +' ' Text +'choices' Name +'@' Operator +'(' Punctuation +'newRow' Name +':' Keyword.Type +'oldChoices' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'endOfRows' Name +' ' Text +'=' Operator.Word +' ' Text +'topNode' Name +' ' Text +'(' Punctuation +'getHead' Name +' ' Text +'newRow' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'if' Keyword.Reserved +' ' Text +'(' Punctuation +'newRow' Name +' ' Text +'==' Operator +' ' Text +'endOfRows' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'then' Keyword.Reserved +' ' Text +'do' Keyword.Reserved +' ' Text +'uncover' Name +' ' Text +'(' Punctuation +'getHead' Name +' ' Text +'newRow' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'if' Keyword.Reserved +' ' Text +'(' Punctuation +'null' Name +' ' Text +'oldChoices' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'then' Keyword.Reserved +' ' Text +'error' Name.Exception +' ' Text +'"' Literal.String +'No choices in advance' Literal.String +'"' Literal.String +' ' Text +'-- return [] -- for [Spec]' Comment.Single +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'recover' Name +' ' Text +'oldChoices' Name +'\n' Text + +'> ' Comment.Special +'else' Keyword.Reserved +' ' Text +'do' Keyword.Reserved +' ' Text +'coverOthers' Name +' ' Text +'newRow' Name +'\n' Text + +'> ' Comment.Special +'forward' Name.Function +' ' Text +'choices' Name +'\n' Text + +'> ' Comment.Special +'\n' Text + +'> ' Comment.Special +'recover' Name.Function +' ' Text +'(' Punctuation +'oldRow' Name +':' Keyword.Type +'oldChoices' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'uncoverOthers' Name.Function +' ' Text +'oldRow' Name +'\n' Text + +'> ' Comment.Special +'newRow' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'readSTRef' Name +' ' Text +'(' Punctuation +'down' Name +' ' Text +'oldRow' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'advance' Name.Function +' ' Text +'(' Punctuation +'newRow' Name +':' Keyword.Type +'oldChoices' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'\n' Text + +'> ' Comment.Special +'in' Keyword.Reserved +' ' Text +'forward' Name +' ' Text +'[]' Keyword.Type +'\n' Text + +'\n' Text + +'\n' Text + +' Convert a text board into a Spec\n' Text + +'\n' Text + +'> ' Comment.Special +'parseBoard' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'String' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'Spec' Keyword.Type +'\n' Text + +'> ' Comment.Special +'parseBoard' Name.Function +' ' Text +'s' Name +' ' Text +'=' Operator.Word +' ' Text +'Spec' Keyword.Type +' ' Text +'(' Punctuation +'zip' Name +' ' Text +'rcs' Name +' ' Text +"vs'check" Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'rcs' Name +' ' Text +'::' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'R' Keyword.Type +',' Punctuation +'C' Keyword.Type +')' Punctuation +']' Punctuation +'\n' Text + +'> ' Comment.Special +'rcs' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'[' Punctuation +' ' Text +'(' Punctuation +'R' Keyword.Type +' ' Text +'r' Name +',' Punctuation +'C' Keyword.Type +' ' Text +'c' Name +')' Punctuation +' ' Text +'|' Operator +' ' Text +'r' Name +' ' Text +'<-' Operator.Word +' ' Text +'rng' Name +',' Punctuation +' ' Text +'c' Name +' ' Text +'<-' Operator.Word +' ' Text +'rng' Name +' ' Text +']' Punctuation +'\n' Text + +'> ' Comment.Special +'isUnset' Name.Function +' ' Text +'c' Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'c' Name +'==' Operator +"'.'" Literal.String.Char +')' Punctuation +' ' Text +'||' Operator +' ' Text +'(' Punctuation +'c' Name +'==' Operator +"' '" Literal.String.Char +')' Punctuation +' ' Text +'||' Operator +' ' Text +'(' Punctuation +'c' Name +'==' Operator +"'0'" Literal.String.Char +')' Punctuation +'\n' Text + +'> ' Comment.Special +'isHint' Name.Function +' ' Text +'c' Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +"'1'" Literal.String.Char +'<=' Operator +'c' Name +')' Punctuation +' ' Text +'&&' Operator +' ' Text +'(' Punctuation +'c' Name +'<=' Operator +"'9'" Literal.String.Char +')' Punctuation +'\n' Text + +'> ' Comment.Special +'cs' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'take' Name +' ' Text +'81' Literal.Number.Integer +' ' Text +'$' Operator +' ' Text +'filter' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'c' Name +' ' Text +'->' Operator.Word +' ' Text +'isUnset' Name +' ' Text +'c' Name +' ' Text +'||' Operator +' ' Text +'isHint' Name +' ' Text +'c' Name +')' Punctuation +' ' Text +'s' Name +'\n' Text + +'> ' Comment.Special +'vs' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'[' Punctuation +'V' Keyword.Type +']' Punctuation +'\n' Text + +'> ' Comment.Special +'vs' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'map' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'c' Name +' ' Text +'->' Operator.Word +' ' Text +'if' Keyword.Reserved +' ' Text +'isUnset' Name +' ' Text +'c' Name +' ' Text +'then' Keyword.Reserved +' ' Text +'u' Name +' ' Text +'else' Keyword.Reserved +' ' Text +'(' Punctuation +'V' Keyword.Type +' ' Text +'$' Operator +' ' Text +'digitToInt' Name +' ' Text +'c' Name +')' Punctuation +')' Punctuation +' ' Text +'cs' Name +'\n' Text + +'> ' Comment.Special +"vs'check" Name.Function +' ' Text +'=' Operator.Word +' ' Text +'if' Keyword.Reserved +' ' Text +'81' Literal.Number.Integer +'==' Operator +'length' Name +' ' Text +'vs' Name +' ' Text +'then' Keyword.Reserved +' ' Text +'vs' Name +' ' Text +'else' Keyword.Reserved +' ' Text +'error' Name.Exception +' ' Text +'(' Punctuation +'"' Literal.String +'parse of board failed' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'s' Name +')' Punctuation +'\n' Text + +'\n' Text + +' This is quite useful as a utility function which partitions the list into groups of n elements.\n' Text + +' Used by showSpec.\n' Text + +'\n' Text + +'> ' Comment.Special +'groupTake' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Int' Keyword.Type +'->' Operator.Word +'[' Punctuation +'a' Name +']' Punctuation +'->' Operator.Word +'[' Punctuation +'[' Punctuation +'a' Name +']' Punctuation +']' Punctuation +'\n' Text + +'> ' Comment.Special +'groupTake' Name.Function +' ' Text +'n' Name +' ' Text +'b' Name +' ' Text +'=' Operator.Word +' ' Text +'unfoldr' Name +' ' Text +'foo' Name +' ' Text +'b' Name +'\n' Text + +'> ' Comment.Special +'where' Keyword.Reserved +' ' Text +'foo' Name +' ' Text +'[]' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'Nothing' Keyword.Type +'\n' Text + +'> ' Comment.Special +'foo' Name.Function +' ' Text +'b' Name +' ' Text +'=' Operator.Word +' ' Text +'Just' Keyword.Type +' ' Text +'(' Punctuation +'splitAt' Name +' ' Text +'n' Name +' ' Text +'b' Name +')' Punctuation +'\n' Text + +' \n' Text + +' Make a nice 2D ascii board from the Spec (not used at the moment)\n' Text + +'\n' Text + +'> ' Comment.Special +'showSpec' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Spec' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'String' Keyword.Type +'\n' Text + +'> ' Comment.Special +'showSpec' Name.Function +' ' Text +'spec' Name +' ' Text +'=' Operator.Word +' ' Text +'let' Keyword.Reserved +' ' Text +'pa' Name +' ' Text +'=' Operator.Word +' ' Text +'parse' Name +' ' Text +'spec' Name +'\n' Text + +'> ' Comment.Special +'g' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'groupTake' Name +' ' Text +'9' Literal.Number.Integer +' ' Text +'(' Punctuation +'map' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'(' Punctuation +'V' Keyword.Type +' ' Text +'v' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'if' Keyword.Reserved +' ' Text +'v' Name +' ' Text +'==' Operator +' ' Text +'0' Literal.Number.Integer +' ' Text +'then' Keyword.Reserved +' ' Text +"'.'" Literal.String.Char +' ' Text +'else' Keyword.Reserved +' ' Text +'intToDigit' Name +' ' Text +'v' Name +')' Punctuation +' ' Text +'$' Operator +' ' Text +'elems' Name +' ' Text +'pa' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'addV' Name.Function +' ' Text +'line' Name +' ' Text +'=' Operator.Word +' ' Text +'concat' Name +' ' Text +'$' Operator +' ' Text +'intersperse' Name +' ' Text +'"' Literal.String +'|' Literal.String +'"' Literal.String +' ' Text +'(' Punctuation +'groupTake' Name +' ' Text +'3' Literal.Number.Integer +' ' Text +'line' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'addH' Name.Function +' ' Text +'list' Name +' ' Text +'=' Operator.Word +' ' Text +'concat' Name +' ' Text +'$' Operator +' ' Text +'intersperse' Name +' ' Text +'[' Punctuation +'"' Literal.String +'---+---+---' Literal.String +'"' Literal.String +']' Punctuation +' ' Text +'(' Punctuation +'groupTake' Name +' ' Text +'3' Literal.Number.Integer +' ' Text +'list' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'in' Keyword.Reserved +' ' Text +'unlines' Name +' ' Text +'$' Operator +' ' Text +'addH' Name +' ' Text +'(' Punctuation +'map' Name +' ' Text +'addV' Name +' ' Text +'g' Name +')' Punctuation +'\n' Text + +'\n' Text + +' One line display\n' Text + +'\n' Text + +'> ' Comment.Special +'showCompact' Name.Function +' ' Text +'spec' Name +' ' Text +'=' Operator.Word +' ' Text +'map' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'(' Punctuation +'V' Keyword.Type +' ' Text +'v' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'intToDigit' Name +' ' Text +'v' Name +')' Punctuation +' ' Text +'(' Punctuation +'elems' Name +' ' Text +'(' Punctuation +'parse' Name +' ' Text +'spec' Name +')' Punctuation +')' Punctuation +'\n' Text + +'\n' Text + +' The main routine is designed to handle the input from http://www.csse.uwa.edu.au/~gordon/sudoku17\n' Text + +'\n' Text + +'> ' Comment.Special +'main' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'all' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'getContents' Name +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'puzzles' Name +' ' Text +'=' Operator.Word +' ' Text +'zip' Name +' ' Text +'[' Punctuation +'1' Literal.Number.Integer +'..' Operator +']' Punctuation +' ' Text +'(' Punctuation +'map' Name +' ' Text +'parseBoard' Name +' ' Text +'(' Punctuation +'lines' Name +' ' Text +'all' Name +')' Punctuation +')' Punctuation +'\n' Text + +'> ' Comment.Special +'root' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'stToIO' Name +' ' Text +'initHA' Name +'\n' Text + +'> ' Comment.Special +'let' Keyword.Reserved +' ' Text +'act' Name +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Int' Keyword.Type +',' Punctuation +'Spec' Keyword.Type +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'IO' Keyword.Type +' ' Text +'()' Name.Builtin +'\n' Text + +'> ' Comment.Special +'act' Name.Function +' ' Text +'(' Punctuation +'i' Name +',' Punctuation +'spec' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n' Text + +'> ' Comment.Special +'answer' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'stToIO' Name +' ' Text +'(' Punctuation +'do' Keyword.Reserved +' ' Text +'initRoot' Name +' ' Text +'root' Name +' ' Text +'spec' Name +' \n' Text + +'> ' Comment.Special +'answer' Name.Function +' ' Text +'<-' Operator.Word +' ' Text +'gdance' Name +' ' Text +'(' Punctuation +'fst' Name +' ' Text +'root' Name +')' Punctuation +' \n' Text + +'> ' Comment.Special +'resetRoot' Name.Function +' ' Text +'root' Name +'\n' Text + +'> ' Comment.Special +'return' Name.Function +' ' Text +'answer' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'print' Name.Function +' ' Text +'(' Punctuation +'i' Name +',' Punctuation +'showCompact' Name +' ' Text +'answer' Name +')' Punctuation +'\n' Text + +'> ' Comment.Special +'mapM_' Name.Function +' ' Text +'act' Name +' ' Text +'puzzles' Name +'\n' Text + +'\n' Text + +'> ' Comment.Special +"inits'" Name.Function +' ' Text +'xn' Name +'@' Operator +'(' Punctuation +'_' Keyword.Reserved +':' Keyword.Type +'_' Keyword.Reserved +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'zipWith' Name +' ' Text +'take' Name +' ' Text +'[' Punctuation +'0' Literal.Number.Integer +'..' Operator +']' Punctuation +' ' Text +'$' Operator +' ' Text +'map' Name +' ' Text +'(' Punctuation +'const' Name +' ' Text +'xn' Name +')' Punctuation +' ' Text +'$' Operator +' ' Text +'undefined' Name +':' Keyword.Type +'xn' Name +'\n' Text + +'> ' Comment.Special +"inits'" Name.Function +' ' Text +'_' Keyword.Reserved +' ' Text +'=' Operator.Word +' ' Text +'undefined' Name +'\n' Text diff --git a/tests/lexers/lhs/example2.txt b/tests/lexers/lhs/example2.txt new file mode 100644 index 00000000..2ed06b6a --- /dev/null +++ b/tests/lexers/lhs/example2.txt @@ -0,0 +1,4736 @@ +---input--- +% Copyright 2005 Brian Alliet + +\documentclass[11pt]{article} +\usepackage{palatino} +\usepackage{fullpage} +\usepackage{parskip} +\usepackage{lhs} + +\begin{document} + +\title{Sudoku Solver} +\author{Brian Alliet} +\maketitle + +\ignore{ +\begin{code} +module Sudoku ( + Sudoku, + makeSudoku, solve, eliminate, analyze, backtrack, + main + ) where + +import Array +import Monad +import List (union,intersperse,transpose,(\\),nub,nubBy) +\end{code} +} + +\section{Introduction} + +This Haskell module implements a solver for Sudoku~\footnote{http://en.wikipedia.org/wiki/Sudoku} puzzles. It can solve +any Sudoku puzzle, even those that require backtracking. + +\section{Data Types} + +\begin{code} +data CellState a = Known a | Unknown [a] | Impossible deriving Eq +\end{code} + +Each cell in a Sudoku grid can be in one of three states: ``Known'' if it has a known correct value~\footnote{Actually +this doesn't always means it is correct. While we are in the backtracking stage we make our guesses ``Known''.}, +``Unknown'' if there is still more than one possible correct value, or ``Impossible'' if there is no value that can +possibly fit the cell. Sudoku grids with ``Impossible'' cells are quickly discarded by the {\tt solve} function. + +\begin{code} +type Coords = (Int,Int) +type Grid a = Array Coords (CellState a) +newtype Sudoku a = Sudoku { unSudoku :: Grid a } deriving Eq +\end{code} + +We represent a Sudoku grid as an Array indexed by integer coordinates. We additionally define a newtype wrapper for the +grid. The smart constructor, {\tt makeSudoku} verifies some invariants before creating the Sudoku value. All the public +API functions operate on the Sudoku type. + +\begin{code} +instance Show a => Show (Sudoku a) where showsPrec p = showParen (p>0) . showsGrid . unSudoku +instance Show a => Show (CellState a) where showsPrec _ = showsCell +\end{code} + +We define {\tt Show} instances for the above types. + +\section{Internal Functions} + +\begin{code} +size :: Grid a -> Int +size = (+1).fst.snd.bounds +\end{code} + +{\tt size} returns the size (the width, height, and number of subboxes) for a Sudoku grid. We ensure Grid's are always +square and indexed starting at $(0,0)$ so simply incrementing either of the array's upper bounds is correct. + +\begin{code} +getRow,getCol,getBox :: Grid a -> Int -> [(Coords,CellState a)] +getRow grid r = [let l = (r,c) in (l,grid!l)|c <- [0..size grid - 1]] +getCol grid c = [let l = (r,c) in (l,grid!l)|r <- [0..size grid - 1]] +getBox grid b = [let l = (r,c) in (l,grid!l)|r <- [boxR..boxR+boxN-1],c <- [boxC..boxC+boxN-1]] + where + boxN = intSqrt (size grid); boxR = b `quot` boxN * boxN; boxC = b `rem` boxN * boxN + +getBoxOf :: Grid a -> Coords -> [(Coords,CellState a)] +getBoxOf grid (r,c) = grid `getBox` ((r `quot` boxN * boxN) + (c `quot` boxN)) + where boxN = intSqrt (size grid) +\end{code} + +{\tt getRow}, {\tt getCol}, and {\tt getBox} return the coordinates and values of the cell in row, column, or box +number {\tt n}, {\tt r}, or {\tt b}. + +\begin{code} +getNeighbors :: Eq a => Grid a -> Coords -> [(Coords,CellState a)] +getNeighbors grid l@(r,c) = filter ((/=l).fst) + $ foldr (union.($grid)) [] + [(`getRow`r),(`getCol`c),(`getBoxOf`l)] +\end{code} + +{\tt getNeighbors} returns the coordinates and values of all the neighbors of this cell. + +\begin{code} +impossible :: Eq a => Grid a -> Coords -> [a] +impossible grid l = map snd $ justKnowns $ grid `getNeighbors` l +\end{code} + +{\tt impossible} returns a list of impossible values for a given cell. The impossible values consist of the values any +``Known'' neighbors. + +\begin{code} +justUnknowns :: [(Coords,CellState a)] -> [(Coords,[a])] +justUnknowns = foldr (\c -> case c of (p,Unknown xs) -> ((p,xs):); _ -> id) [] + +justKnowns :: [(Coords,CellState a)] -> [(Coords,a)] +justKnowns = foldr (\c -> case c of (p,Known x) -> ((p,x):); _ -> id) [] +\end{code} + +{\tt justUnknowns} and {\tt justKnowns} return only the Known or Unknown values (with the constructor stripped off) +from a list of cells. + +\begin{code} +updateGrid :: Grid a -> [(Coords,CellState a)] -> Maybe (Grid a) +updateGrid _ [] = Nothing +updateGrid grid xs = Just $ grid // nubBy (\(x,_) (y,_) -> x==y) xs +\end{code} + +{\tt updateGrid} applies a set of updates to a grid and returns the new grid only if it was updated. + +\section{Public API} + +\begin{code} +makeSudoku :: (Num a, Ord a, Enum a) => [[a]] -> Sudoku a +makeSudoku xs + | not (all ((==size).length) xs) = error "error not a square" + | (intSqrt size)^(2::Int) /= size = error "error dims aren't perfect squares" + | any (\x -> x < 0 || x > fromIntegral size) (concat xs) = error "value out of range" + | otherwise = Sudoku (listArray ((0,0),(size-1,size-1)) states) + where + size = length xs + states = map f (concat xs) + f 0 = Unknown [1..fromIntegral size] + f x = Known x +\end{code} + +{\tt makeSudoku} makes a {\tt Sudoku} value from a list of numbers. The given matrix must be square and have dimensions +that are a perfect square. The possible values for each cell range from 1 to the dimension of the square with ``0'' +representing unknown values.\footnote{The rest of the code doesn't depend on any of this weird ``0'' is unknown +representation. In fact, it doesn't depend on numeric values at all. ``0'' is just used here because it makes +representing grids in Haskell source code easier.} + +\begin{code} +eliminate :: Eq a => Sudoku a -> Maybe (Sudoku a) +eliminate (Sudoku grid) = fmap Sudoku $ updateGrid grid changes >>= sanitize + where + changes = concatMap findChange $ assocs grid + findChange (l,Unknown xs) + = map ((,) l) + $ case filter (not.(`elem`impossible grid l)) xs of + [] -> return Impossible + [x] -> return $ Known x + xs' + | xs' /= xs -> return $ Unknown xs' + | otherwise -> mzero + findChange _ = mzero + sanitize grid = return $ grid // [(l,Impossible) | + (l,x) <- justKnowns changes, x `elem` impossible grid l] +\end{code} + +The {\tt eliminate} phase tries to remove possible choices for ``Unknowns'' based on ``Known'' values in the same row, +column, or box as the ``Unknown'' value. For each cell on the grid we find its ``neighbors'', that is, cells in the +same row, column, or box. Out of those neighbors we get a list of all the ``Known'' values. We can eliminate all of +these from our list of candidates for this cell. If we're lucky enough to eliminate all the candidates but one we have +a new ``Known'' value. If we're unlucky enough to have eliminates {\bf all} the possible candidates we have a new +``Impossible'' value. + +After iterating though every cell we make one more pass looking for conflicting changes. {\tt sanitize} marks cells as +``Impossible'' if we have conflicting ``Known'' values. + +\begin{code} +analyze :: Eq a => Sudoku a -> Maybe (Sudoku a) +analyze (Sudoku grid) = fmap Sudoku $ updateGrid grid $ nub [u | + f <- map ($grid) [getRow,getCol,getBox], + n <- [0..size grid - 1], + u <- unique (f n)] + where + unique xs = foldr f [] $ foldr (union.snd) [] unknowns \\ map snd (justKnowns xs) + where + unknowns = justUnknowns xs + f c = case filter ((c`elem`).snd) unknowns of + [(p,_)] -> ((p,Known c):) + _ -> id +\end{code} + +The {\tt analyze} phase tries to turn ``Unknowns'' into ``Knowns'' when a certain ``Unknown'' is the only cell that +contains a value needed in a given row, column, or box. We apply each of the functions {\tt getRow}, {\tt getCol}, and +{\tt getBox} to all the indices on the grid, apply {\tt unique} to each group, and update the array with the +results. {\tt unique} gets a list of all the unknown cells in the group and finds all the unknown values in each of +those cells. Each of these values are iterated though looking for a value that is only contained in one cell. If such a +value is found the cell containing it must be that value. + +\begin{code} +backtrack :: (MonadPlus m, Eq a) => Sudoku a -> m (Sudoku a) +backtrack (Sudoku grid) = case (justUnknowns (assocs grid)) of + [] -> return $ Sudoku grid + ((p,xs):_) -> msum $ map (\x -> solve $ Sudoku $ grid // [(p,Known x)]) xs +\end{code} + +Sometimes the above two phases still aren't enough to solve a puzzle. For these rare puzzles backtracking is required. +We attempt to solve the puzzle by replacing the first ``Unknown'' value with each of the candidate values and solving +the resulting puzzles. Hopefully at least one of our choices will result in a solvable puzzle. + +We could actually solve any puzzle using backtracking alone, although this would be very inefficient. The above +functions simplify most puzzles enough that the backtracking phase has to do hardly any work. + +\begin{code} +solve :: (MonadPlus m, Eq a) => Sudoku a -> m (Sudoku a) +solve sudoku = + case eliminate sudoku of + Just new + | any (==Impossible) (elems (unSudoku new))-> mzero + | otherwise -> solve new + Nothing -> case analyze sudoku of + Just new -> solve new + Nothing -> backtrack sudoku +\end{code} + +{\tt solve} glues all the above phases together. First we run the {\tt eliminate} phase. If that found the puzzle to +be unsolvable we abort immediately. If {\tt eliminate} changed the grid we go though the {\tt eliminate} phase again +hoping to eliminate more. Once {\tt eliminate} can do no more work we move on to the {\tt analyze} phase. If this +succeeds in doing some work we start over again with the {\tt eliminate} phase. Once {\tt analyze} can do no more work +we have no choice but to resort to backtracking. (However in most cases backtracking won't actually do anything because +the puzzle is already solved.) + +\begin{code} +showsCell :: Show a => CellState a -> ShowS +showsCell (Known x) = shows x +showsCell (Impossible) = showChar 'X' +showsCell (Unknown xs) = \rest -> ('(':) + $ foldr id (')':rest) + $ intersperse (showChar ' ') + $ map shows xs +\end{code} + +{\tt showCell} shows a cell. + +\begin{code} +showsGrid :: Show a => Grid a -> ShowS +showsGrid grid = showsTable [[grid!(r,c) | c <- [0..size grid-1]] | r <- [0..size grid-1]] +\end{code} + +{\tt showGrid} show a grid. + +\begin{code} +-- FEATURE: This is pretty inefficient +showsTable :: Show a => [[a]] -> ShowS +showsTable xs = (showChar '\n' .) $ showString $ unlines $ map (concat . intersperse " ") xs'' + where + xs' = (map.map) show xs + colWidths = map (max 2 . maximum . map length) (transpose xs') + xs'' = map (zipWith (\n s -> s ++ (replicate (n - length s) ' ')) colWidths) xs' +\end{code} + +{\tt showsTable} shows a table (or matrix). Every column has the same width so things line up. + +\begin{code} +intSqrt :: Integral a => a -> a +intSqrt n + | n < 0 = error "intSqrt: negative n" + | otherwise = f n + where + f x = if y < x then f y else x + where y = (x + (n `quot` x)) `quot` 2 +\end{code} + +{\tt intSqrt} is Newton`s Iteration for finding integral square roots. + +\ignore{ +\begin{code} +test :: Sudoku Int +test = makeSudoku [ + [0,6,0,1,0,4,0,5,0], + [0,0,8,3,0,5,6,0,0], + [2,0,0,0,0,0,0,0,1], + [8,0,0,4,0,7,0,0,6], + [0,0,6,0,0,0,3,0,0], + [7,0,0,9,0,1,0,0,4], + [5,0,0,0,0,0,0,0,2], + [0,0,7,2,0,6,9,0,0], + [0,4,0,5,0,8,0,7,0]] + +test2 :: Sudoku Int +test2 = makeSudoku [ + [0,7,0,0,0,0,8,0,0], + [0,0,0,2,0,4,0,0,0], + [0,0,6,0,0,0,0,3,0], + [0,0,0,5,0,0,0,0,6], + [9,0,8,0,0,2,0,4,0], + [0,5,0,0,3,0,9,0,0], + [0,0,2,0,8,0,0,6,0], + [0,6,0,9,0,0,7,0,1], + [4,0,0,0,0,3,0,0,0]] + +testSmall :: Sudoku Int +testSmall = makeSudoku [ + [1,0,0,0,0,0,0,0,0], + [0,0,2,7,4,0,0,0,0], + [0,0,0,5,0,0,0,0,4], + [0,3,0,0,0,0,0,0,0], + [7,5,0,0,0,0,0,0,0], + [0,0,0,0,0,9,6,0,0], + [0,4,0,0,0,6,0,0,0], + [0,0,0,0,0,0,0,7,1], + [0,0,0,0,0,1,0,3,0]] + +testHard :: Sudoku Int +testHard = makeSudoku [ + [0,0,0,8,0,2,0,0,0], + [5,0,0,0,0,0,0,0,1], + [0,0,6,0,5,0,3,0,0], + [0,0,9,0,1,0,8,0,0], + [1,0,0,0,0,0,0,0,2], + [0,0,0,9,0,7,0,0,0], + [0,6,1,0,3,0,7,8,0], + [0,5,0,0,0,0,0,4,0], + [0,7,2,0,4,0,1,5,0]] + +testHard2 :: Sudoku Int +testHard2 = makeSudoku [ + [3,0,0,2,0,0,9,0,0], + [0,0,0,0,0,0,0,0,5], + [0,7,0,1,0,4,0,0,0], + [0,0,9,0,0,0,8,0,0], + [5,0,0,0,7,0,0,0,6], + [0,0,1,0,0,0,2,0,0], + [0,0,0,3,0,9,0,4,0], + [8,0,0,0,0,0,0,0,0], + [0,0,6,0,0,5,0,0,7]] + +testHW :: Sudoku Int +testHW = makeSudoku [ + [0,0,0,1,0,0,7,0,2], + [0,3,0,9,5,0,0,0,0], + [0,0,1,0,0,2,0,0,3], + [5,9,0,0,0,0,3,0,1], + [0,2,0,0,0,0,0,7,0], + [7,0,3,0,0,0,0,9,8], + [8,0,0,2,0,0,1,0,0], + [0,0,0,0,8,5,0,6,0], + [6,0,5,0,0,9,0,0,0]] + +testTough :: Sudoku Int +testTough = makeSudoku $ map (map read . words) $ lines $ + "8 3 0 0 0 0 0 4 6\n"++ + "0 2 0 1 0 4 0 3 0\n"++ + "0 0 0 0 0 0 0 0 0\n"++ + "0 0 2 9 0 6 5 0 0\n"++ + "1 4 0 0 0 0 0 2 3\n"++ + "0 0 5 4 0 3 1 0 0\n"++ + "0 0 0 0 0 0 0 0 0\n"++ + "0 6 0 3 0 8 0 7 0\n"++ + "9 5 0 0 0 0 0 6 2\n" + +testDiabolical :: Sudoku Int +testDiabolical = makeSudoku $ map (map read . words) $ lines $ + "8 0 0 7 0 1 0 0 2\n"++ + "0 0 6 0 0 0 7 0 0\n"++ + "0 1 7 0 0 0 8 9 0\n"++ + "0 0 0 1 7 3 0 0 0\n"++ + "7 0 0 0 0 0 0 0 6\n"++ + "0 0 0 9 5 6 0 0 0\n"++ + "0 9 5 0 0 0 4 1 0\n"++ + "0 0 8 0 0 0 5 0 0\n"++ + "3 0 0 6 0 5 0 0 7\n" + +main :: IO () +main = do + let + solve' p = case solve p of + [] -> fail $ "couldn't solve: " ++ show p + sols -> return sols + mapM_ (\p -> solve' p >>= putStrLn.show) [test,test2,testSmall,testHard,testHard2,testHW,testTough,testDiabolical] + return () + +\end{code} +} + +\end{document} + +---tokens--- +'% Copyright 2005 Brian Alliet\n' Comment + +'\n' Text + +'\\documentclass' Keyword +'[11pt]' Name.Attribute +'{' Name.Builtin +'article' Text +'}' Name.Builtin +'\n' Text + +'\\usepackage' Keyword +'{' Name.Builtin +'palatino' Text +'}' Name.Builtin +'\n' Text + +'\\usepackage' Keyword +'{' Name.Builtin +'fullpage' Text +'}' Name.Builtin +'\n' Text + +'\\usepackage' Keyword +'{' Name.Builtin +'parskip' Text +'}' Name.Builtin +'\n' Text + +'\\usepackage' Keyword +'{' Name.Builtin +'lhs' Text +'}' Name.Builtin +'\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'document' Text +'}' Name.Builtin +'\n\n' Text + +'\\title' Keyword +'{' Name.Builtin +'Sudoku Solver' Text +'}' Name.Builtin +'\n' Text + +'\\author' Keyword +'{' Name.Builtin +'Brian Alliet' Text +'}' Name.Builtin +'\n' Text + +'\\maketitle' Keyword +'\n\n' Text + +'\\ignore' Keyword +'{' Name.Builtin +'\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'module' Keyword.Reserved +' ' Text +'Sudoku' Name.Namespace +' ' Text +'(' Punctuation +'\n ' Text +'Sudoku' Keyword.Type +',' Punctuation +'\n ' Text +'makeSudoku' Name.Function +',' Punctuation +' ' Text +'solve' Name.Function +',' Punctuation +' ' Text +'eliminate' Name.Function +',' Punctuation +' ' Text +'analyze' Name.Function +',' Punctuation +' ' Text +'backtrack' Name.Function +',' Punctuation +'\n ' Text +'main' Name.Function +'\n ' Text +')' Punctuation +' ' Text +'where' Keyword.Reserved +'\n\n' Text + +'import' Keyword.Reserved +' ' Text +'Array' Name.Namespace +'\n' Text + +'import' Keyword.Reserved +' ' Text +'Monad' Name.Namespace +'\n' Text + +'import' Keyword.Reserved +' ' Text +'List' Name.Namespace +' ' Text +'(' Punctuation +'union' Name.Function +',' Punctuation +'intersperse' Name.Function +',' Punctuation +'transpose' Name.Function +',' Punctuation +'(' Punctuation +'\\\\' Operator +')' Punctuation +',' Punctuation +'nub' Name.Function +',' Punctuation +'nubBy' Name.Function +')' Punctuation +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'}' Name.Builtin +'\n\n' Text + +'\\section' Keyword +'{' Name.Builtin +'Introduction' Text +'}' Name.Builtin +'\n\nThis Haskell module implements a solver for Sudoku~' Text +'\\footnote' Keyword +'{' Name.Builtin +'http://en.wikipedia.org/wiki/Sudoku' Text +'}' Name.Builtin +' puzzles. It can solve\nany Sudoku puzzle, even those that require backtracking.\n\n' Text + +'\\section' Keyword +'{' Name.Builtin +'Data Types' Text +'}' Name.Builtin +'\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'data' Keyword.Reserved +' ' Text +'CellState' Keyword.Type +' ' Text +'a' Name +' ' Text +'=' Operator.Word +' ' Text +'Known' Keyword.Type +' ' Text +'a' Name +' ' Text +'|' Operator +' ' Text +'Unknown' Keyword.Type +' ' Text +'[' Punctuation +'a' Name +']' Punctuation +' ' Text +'|' Operator +' ' Text +'Impossible' Keyword.Type +' ' Text +'deriving' Keyword.Reserved +' ' Text +'Eq' Keyword.Type +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +"\n\nEach cell in a Sudoku grid can be in one of three states: ``Known'' if it has a known correct value~" Text +'\\footnote' Keyword +'{' Name.Builtin +"Actually\nthis doesn't always means it is correct. While we are in the backtracking stage we make our guesses ``Known''." Text +'}' Name.Builtin +",\n``Unknown'' if there is still more than one possible correct value, or ``Impossible'' if there is no value that can\npossibly fit the cell. Sudoku grids with ``Impossible'' cells are quickly discarded by the " Text +'{' Name.Builtin +'\\tt' Keyword +' solve' Text +'}' Name.Builtin +' function.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'type' Keyword.Reserved +' ' Text +'Coords' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'Int' Keyword.Type +',' Punctuation +'Int' Keyword.Type +')' Punctuation +'\n' Text + +'type' Keyword.Reserved +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'=' Operator.Word +' ' Text +'Array' Keyword.Type +' ' Text +'Coords' Keyword.Type +' ' Text +'(' Punctuation +'CellState' Keyword.Type +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'newtype' Keyword.Reserved +' ' Text +'Sudoku' Keyword.Type +' ' Text +'a' Name +' ' Text +'=' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'{' Punctuation +' ' Text +'unSudoku' Name +' ' Text +'::' Operator.Word +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'}' Punctuation +' ' Text +'deriving' Keyword.Reserved +' ' Text +'Eq' Keyword.Type +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\nWe represent a Sudoku grid as an Array indexed by integer coordinates. We additionally define a newtype wrapper for the\ngrid. The smart constructor, ' Text +'{' Name.Builtin +'\\tt' Keyword +' makeSudoku' Text +'}' Name.Builtin +' verifies some invariants before creating the Sudoku value. All the public\nAPI functions operate on the Sudoku type.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'instance' Keyword.Reserved +' ' Text +'Show' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'Show' Keyword.Type +' ' Text +'(' Punctuation +'Sudoku' Keyword.Type +' ' Text +'a' Name +')' Punctuation +' ' Text +'where' Keyword.Reserved +' ' Text +'showsPrec' Name +' ' Text +'p' Name +' ' Text +'=' Operator.Word +' ' Text +'showParen' Name +' ' Text +'(' Punctuation +'p' Name +'>' Operator +'0' Literal.Number.Integer +')' Punctuation +' ' Text +'.' Operator +' ' Text +'showsGrid' Name +' ' Text +'.' Operator +' ' Text +'unSudoku' Name +'\n' Text + +'instance' Keyword.Reserved +' ' Text +'Show' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'Show' Keyword.Type +' ' Text +'(' Punctuation +'CellState' Keyword.Type +' ' Text +'a' Name +')' Punctuation +' ' Text +'where' Keyword.Reserved +' ' Text +'showsPrec' Name +' ' Text +'_' Keyword.Reserved +' ' Text +'=' Operator.Word +' ' Text +'showsCell' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\nWe define ' Text +'{' Name.Builtin +'\\tt' Keyword +' Show' Text +'}' Name.Builtin +' instances for the above types.\n\n' Text + +'\\section' Keyword +'{' Name.Builtin +'Internal Functions' Text +'}' Name.Builtin +'\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'size' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'Int' Keyword.Type +'\n' Text + +'size' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'+' Operator +'1' Literal.Number.Integer +')' Punctuation +'.' Operator +'fst' Name +'.' Operator +'snd' Name +'.' Operator +'bounds' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' size' Text +'}' Name.Builtin +" returns the size (the width, height, and number of subboxes) for a Sudoku grid. We ensure Grid's are always\nsquare and indexed starting at " Text +'$' Literal.String +'(' Operator +'0' Literal.Number +',' Name.Builtin +'0' Literal.Number +')' Operator +'$' Literal.String +" so simply incrementing either of the array's upper bounds is correct.\n\n" Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'getRow' Name.Function +',' Punctuation +'getCol' Name +',' Punctuation +'getBox' Name +' ' Text +'::' Operator.Word +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'Int' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Coords' Keyword.Type +',' Punctuation +'CellState' Keyword.Type +' ' Text +'a' Name +')' Punctuation +']' Punctuation +'\n' Text + +'getRow' Name.Function +' ' Text +'grid' Name +' ' Text +'r' Name +' ' Text +'=' Operator.Word +' ' Text +'[' Punctuation +'let' Keyword.Reserved +' ' Text +'l' Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'r' Name +',' Punctuation +'c' Name +')' Punctuation +' ' Text +'in' Keyword.Reserved +' ' Text +'(' Punctuation +'l' Name +',' Punctuation +'grid' Name +'!' Operator +'l' Name +')' Punctuation +'|' Operator +'c' Name +' ' Text +'<-' Operator.Word +' ' Text +'[' Punctuation +'0' Literal.Number.Integer +'..' Operator +'size' Name +' ' Text +'grid' Name +' ' Text +'-' Operator +' ' Text +'1' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n' Text + +'getCol' Name.Function +' ' Text +'grid' Name +' ' Text +'c' Name +' ' Text +'=' Operator.Word +' ' Text +'[' Punctuation +'let' Keyword.Reserved +' ' Text +'l' Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'r' Name +',' Punctuation +'c' Name +')' Punctuation +' ' Text +'in' Keyword.Reserved +' ' Text +'(' Punctuation +'l' Name +',' Punctuation +'grid' Name +'!' Operator +'l' Name +')' Punctuation +'|' Operator +'r' Name +' ' Text +'<-' Operator.Word +' ' Text +'[' Punctuation +'0' Literal.Number.Integer +'..' Operator +'size' Name +' ' Text +'grid' Name +' ' Text +'-' Operator +' ' Text +'1' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n' Text + +'getBox' Name.Function +' ' Text +'grid' Name +' ' Text +'b' Name +' ' Text +'=' Operator.Word +' ' Text +'[' Punctuation +'let' Keyword.Reserved +' ' Text +'l' Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'r' Name +',' Punctuation +'c' Name +')' Punctuation +' ' Text +'in' Keyword.Reserved +' ' Text +'(' Punctuation +'l' Name +',' Punctuation +'grid' Name +'!' Operator +'l' Name +')' Punctuation +'|' Operator +'r' Name +' ' Text +'<-' Operator.Word +' ' Text +'[' Punctuation +'boxR' Name +'..' Operator +'boxR' Name +'+' Operator +'boxN' Name +'-' Operator +'1' Literal.Number.Integer +']' Punctuation +',' Punctuation +'c' Name +' ' Text +'<-' Operator.Word +' ' Text +'[' Punctuation +'boxC' Name +'..' Operator +'boxC' Name +'+' Operator +'boxN' Name +'-' Operator +'1' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n ' Text +'where' Keyword.Reserved +'\n ' Text +'boxN' Name +' ' Text +'=' Operator.Word +' ' Text +'intSqrt' Name +' ' Text +'(' Punctuation +'size' Name +' ' Text +'grid' Name +')' Punctuation +';' Punctuation +' ' Text +'boxR' Name +' ' Text +'=' Operator.Word +' ' Text +'b' Name +' ' Text +'`' Punctuation +'quot' Name +'`' Punctuation +' ' Text +'boxN' Name +' ' Text +'*' Operator +' ' Text +'boxN' Name +';' Punctuation +' ' Text +'boxC' Name +' ' Text +'=' Operator.Word +' ' Text +'b' Name +' ' Text +'`' Punctuation +'rem' Name +'`' Punctuation +' ' Text +'boxN' Name +' ' Text +'*' Operator +' ' Text +'boxN' Name +'\n\n' Text + +'getBoxOf' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'Coords' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Coords' Keyword.Type +',' Punctuation +'CellState' Keyword.Type +' ' Text +'a' Name +')' Punctuation +']' Punctuation +'\n' Text + +'getBoxOf' Name.Function +' ' Text +'grid' Name +' ' Text +'(' Punctuation +'r' Name +',' Punctuation +'c' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'grid' Name +' ' Text +'`' Punctuation +'getBox' Name +'`' Punctuation +' ' Text +'(' Punctuation +'(' Punctuation +'r' Name +' ' Text +'`' Punctuation +'quot' Name +'`' Punctuation +' ' Text +'boxN' Name +' ' Text +'*' Operator +' ' Text +'boxN' Name +')' Punctuation +' ' Text +'+' Operator +' ' Text +'(' Punctuation +'c' Name +' ' Text +'`' Punctuation +'quot' Name +'`' Punctuation +' ' Text +'boxN' Name +')' Punctuation +')' Punctuation +'\n ' Text +'where' Keyword.Reserved +' ' Text +'boxN' Name +' ' Text +'=' Operator.Word +' ' Text +'intSqrt' Name +' ' Text +'(' Punctuation +'size' Name +' ' Text +'grid' Name +')' Punctuation +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' getRow' Text +'}' Name.Builtin +', ' Text +'{' Name.Builtin +'\\tt' Keyword +' getCol' Text +'}' Name.Builtin +', and ' Text +'{' Name.Builtin +'\\tt' Keyword +' getBox' Text +'}' Name.Builtin +' return the coordinates and values of the cell in row, column, or box\nnumber ' Text +'{' Name.Builtin +'\\tt' Keyword +' n' Text +'}' Name.Builtin +', ' Text +'{' Name.Builtin +'\\tt' Keyword +' r' Text +'}' Name.Builtin +', or ' Text +'{' Name.Builtin +'\\tt' Keyword +' b' Text +'}' Name.Builtin +'.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'getNeighbors' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Eq' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'Coords' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Coords' Keyword.Type +',' Punctuation +'CellState' Keyword.Type +' ' Text +'a' Name +')' Punctuation +']' Punctuation +'\n' Text + +'getNeighbors' Name.Function +' ' Text +'grid' Name +' ' Text +'l' Name +'@' Operator +'(' Punctuation +'r' Name +',' Punctuation +'c' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'filter' Name +' ' Text +'(' Punctuation +'(' Punctuation +'/=' Operator +'l' Name +')' Punctuation +'.' Operator +'fst' Name +')' Punctuation +' \n ' Text +'$' Operator +' ' Text +'foldr' Name +' ' Text +'(' Punctuation +'union' Name +'.' Operator +'(' Punctuation +'$' Operator +'grid' Name +')' Punctuation +')' Punctuation +' ' Text +'[]' Keyword.Type +' \n ' Text +'[' Punctuation +'(' Punctuation +'`' Punctuation +'getRow' Name +'`' Punctuation +'r' Name +')' Punctuation +',' Punctuation +'(' Punctuation +'`' Punctuation +'getCol' Name +'`' Punctuation +'c' Name +')' Punctuation +',' Punctuation +'(' Punctuation +'`' Punctuation +'getBoxOf' Name +'`' Punctuation +'l' Name +')' Punctuation +']' Punctuation +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' getNeighbors' Text +'}' Name.Builtin +' returns the coordinates and values of all the neighbors of this cell.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'impossible' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Eq' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'Coords' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'a' Name +']' Punctuation +'\n' Text + +'impossible' Name.Function +' ' Text +'grid' Name +' ' Text +'l' Name +' ' Text +'=' Operator.Word +' ' Text +'map' Name +' ' Text +'snd' Name +' ' Text +'$' Operator +' ' Text +'justKnowns' Name +' ' Text +'$' Operator +' ' Text +'grid' Name +' ' Text +'`' Punctuation +'getNeighbors' Name +'`' Punctuation +' ' Text +'l' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' impossible' Text +'}' Name.Builtin +" returns a list of impossible values for a given cell. The impossible values consist of the values any\n``Known'' neighbors.\n\n" Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'justUnknowns' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Coords' Keyword.Type +',' Punctuation +'CellState' Keyword.Type +' ' Text +'a' Name +')' Punctuation +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Coords' Keyword.Type +',' Punctuation +'[' Punctuation +'a' Name +']' Punctuation +')' Punctuation +']' Punctuation +'\n' Text + +'justUnknowns' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'foldr' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'c' Name +' ' Text +'->' Operator.Word +' ' Text +'case' Keyword.Reserved +' ' Text +'c' Name +' ' Text +'of' Keyword.Reserved +' ' Text +'(' Punctuation +'p' Name +',' Punctuation +'Unknown' Keyword.Type +' ' Text +'xs' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'(' Punctuation +'p' Name +',' Punctuation +'xs' Name +')' Punctuation +':' Keyword.Type +')' Punctuation +';' Punctuation +' ' Text +'_' Keyword.Reserved +' ' Text +'->' Operator.Word +' ' Text +'id' Name +')' Punctuation +' ' Text +'[]' Keyword.Type +'\n\n' Text + +'justKnowns' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Coords' Keyword.Type +',' Punctuation +'CellState' Keyword.Type +' ' Text +'a' Name +')' Punctuation +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Coords' Keyword.Type +',' Punctuation +'a' Name +')' Punctuation +']' Punctuation +'\n' Text + +'justKnowns' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'foldr' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'c' Name +' ' Text +'->' Operator.Word +' ' Text +'case' Keyword.Reserved +' ' Text +'c' Name +' ' Text +'of' Keyword.Reserved +' ' Text +'(' Punctuation +'p' Name +',' Punctuation +'Known' Keyword.Type +' ' Text +'x' Name +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'(' Punctuation +'p' Name +',' Punctuation +'x' Name +')' Punctuation +':' Keyword.Type +')' Punctuation +';' Punctuation +' ' Text +'_' Keyword.Reserved +' ' Text +'->' Operator.Word +' ' Text +'id' Name +')' Punctuation +' ' Text +'[]' Keyword.Type +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' justUnknowns' Text +'}' Name.Builtin +' and ' Text +'{' Name.Builtin +'\\tt' Keyword +' justKnowns' Text +'}' Name.Builtin +' return only the Known or Unknown values (with the constructor stripped off)\nfrom a list of cells.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'updateGrid' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'[' Punctuation +'(' Punctuation +'Coords' Keyword.Type +',' Punctuation +'CellState' Keyword.Type +' ' Text +'a' Name +')' Punctuation +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'Maybe' Keyword.Type +' ' Text +'(' Punctuation +'Grid' Keyword.Type +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'updateGrid' Name.Function +' ' Text +'_' Keyword.Reserved +' ' Text +'[]' Keyword.Type +' ' Text +'=' Operator.Word +' ' Text +'Nothing' Keyword.Type +'\n' Text + +'updateGrid' Name.Function +' ' Text +'grid' Name +' ' Text +'xs' Name +' ' Text +'=' Operator.Word +' ' Text +'Just' Keyword.Type +' ' Text +'$' Operator +' ' Text +'grid' Name +' ' Text +'//' Operator +' ' Text +'nubBy' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'(' Punctuation +'x' Name +',' Punctuation +'_' Keyword.Reserved +')' Punctuation +' ' Text +'(' Punctuation +'y' Name +',' Punctuation +'_' Keyword.Reserved +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'x' Name +'==' Operator +'y' Name +')' Punctuation +' ' Text +'xs' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' updateGrid' Text +'}' Name.Builtin +' applies a set of updates to a grid and returns the new grid only if it was updated.\n\n' Text + +'\\section' Keyword +'{' Name.Builtin +'Public API' Text +'}' Name.Builtin +'\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'makeSudoku' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'Num' Keyword.Type +' ' Text +'a' Name +',' Punctuation +' ' Text +'Ord' Keyword.Type +' ' Text +'a' Name +',' Punctuation +' ' Text +'Enum' Keyword.Type +' ' Text +'a' Name +')' Punctuation +' ' Text +'=>' Operator.Word +' ' Text +'[' Punctuation +'[' Punctuation +'a' Name +']' Punctuation +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'a' Name +'\n' Text + +'makeSudoku' Name.Function +' ' Text +'xs' Name +'\n ' Text +'|' Operator +' ' Text +'not' Name +' ' Text +'(' Punctuation +'all' Name +' ' Text +'(' Punctuation +'(' Punctuation +'==' Operator +'size' Name +')' Punctuation +'.' Operator +'length' Name +')' Punctuation +' ' Text +'xs' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'error' Name.Exception +' ' Text +'"' Literal.String +'error not a square' Literal.String +'"' Literal.String +'\n ' Text +'|' Operator +' ' Text +'(' Punctuation +'intSqrt' Name +' ' Text +'size' Name +')' Punctuation +'^' Operator +'(' Punctuation +'2' Literal.Number.Integer +'::' Operator.Word +'Int' Keyword.Type +')' Punctuation +' ' Text +'/=' Operator +' ' Text +'size' Name +' ' Text +'=' Operator.Word +' ' Text +'error' Name.Exception +' ' Text +'"' Literal.String +"error dims aren't perfect squares" Literal.String +'"' Literal.String +'\n ' Text +'|' Operator +' ' Text +'any' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'x' Name +' ' Text +'->' Operator.Word +' ' Text +'x' Name +' ' Text +'<' Operator +' ' Text +'0' Literal.Number.Integer +' ' Text +'||' Operator +' ' Text +'x' Name +' ' Text +'>' Operator +' ' Text +'fromIntegral' Name +' ' Text +'size' Name +')' Punctuation +' ' Text +'(' Punctuation +'concat' Name +' ' Text +'xs' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'error' Name.Exception +' ' Text +'"' Literal.String +'value out of range' Literal.String +'"' Literal.String +'\n ' Text +'|' Operator +' ' Text +'otherwise' Name +' ' Text +'=' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'(' Punctuation +'listArray' Name +' ' Text +'(' Punctuation +'(' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +')' Punctuation +',' Punctuation +'(' Punctuation +'size' Name +'-' Operator +'1' Literal.Number.Integer +',' Punctuation +'size' Name +'-' Operator +'1' Literal.Number.Integer +')' Punctuation +')' Punctuation +' ' Text +'states' Name +')' Punctuation +'\n ' Text +'where' Keyword.Reserved +'\n ' Text +'size' Name +' ' Text +'=' Operator.Word +' ' Text +'length' Name +' ' Text +'xs' Name +'\n ' Text +'states' Name +' ' Text +'=' Operator.Word +' ' Text +'map' Name +' ' Text +'f' Name +' ' Text +'(' Punctuation +'concat' Name +' ' Text +'xs' Name +')' Punctuation +'\n ' Text +'f' Name +' ' Text +'0' Literal.Number.Integer +' ' Text +'=' Operator.Word +' ' Text +'Unknown' Keyword.Type +' ' Text +'[' Punctuation +'1' Literal.Number.Integer +'..' Operator +'fromIntegral' Name +' ' Text +'size' Name +']' Punctuation +'\n ' Text +'f' Name +' ' Text +'x' Name +' ' Text +'=' Operator.Word +' ' Text +'Known' Keyword.Type +' ' Text +'x' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' makeSudoku' Text +'}' Name.Builtin +' makes a ' Text +'{' Name.Builtin +'\\tt' Keyword +' Sudoku' Text +'}' Name.Builtin +" value from a list of numbers. The given matrix must be square and have dimensions\nthat are a perfect square. The possible values for each cell range from 1 to the dimension of the square with ``0''\nrepresenting unknown values." Text +'\\footnote' Keyword +'{' Name.Builtin +"The rest of the code doesn't depend on any of this weird ``0'' is unknown\nrepresentation. In fact, it doesn't depend on numeric values at all. ``0'' is just used here because it makes\nrepresenting grids in Haskell source code easier." Text +'}' Name.Builtin +'\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'eliminate' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Eq' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'Maybe' Keyword.Type +' ' Text +'(' Punctuation +'Sudoku' Keyword.Type +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'eliminate' Name.Function +' ' Text +'(' Punctuation +'Sudoku' Keyword.Type +' ' Text +'grid' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'fmap' Name +' ' Text +'Sudoku' Keyword.Type +' ' Text +'$' Operator +' ' Text +'updateGrid' Name +' ' Text +'grid' Name +' ' Text +'changes' Name +' ' Text +'>>=' Operator +' ' Text +'sanitize' Name +'\n ' Text +'where' Keyword.Reserved +'\n ' Text +'changes' Name +' ' Text +'=' Operator.Word +' ' Text +'concatMap' Name +' ' Text +'findChange' Name +' ' Text +'$' Operator +' ' Text +'assocs' Name +' ' Text +'grid' Name +'\n ' Text +'findChange' Name +' ' Text +'(' Punctuation +'l' Name +',' Punctuation +'Unknown' Keyword.Type +' ' Text +'xs' Name +')' Punctuation +' \n ' Text +'=' Operator.Word +' ' Text +'map' Name +' ' Text +'(' Punctuation +'(' Punctuation +',' Punctuation +')' Punctuation +' ' Text +'l' Name +')' Punctuation +' \n ' Text +'$' Operator +' ' Text +'case' Keyword.Reserved +' ' Text +'filter' Name +' ' Text +'(' Punctuation +'not' Name +'.' Operator +'(' Punctuation +'`' Punctuation +'elem' Name +'`' Punctuation +'impossible' Name +' ' Text +'grid' Name +' ' Text +'l' Name +')' Punctuation +')' Punctuation +' ' Text +'xs' Name +' ' Text +'of' Keyword.Reserved +'\n ' Text +'[]' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'return' Name +' ' Text +'Impossible' Keyword.Type +'\n ' Text +'[' Punctuation +'x' Name +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'return' Name +' ' Text +'$' Operator +' ' Text +'Known' Keyword.Type +' ' Text +'x' Name +'\n ' Text +"xs'" Name +'\n ' Text +'|' Operator +' ' Text +"xs'" Name +' ' Text +'/=' Operator +' ' Text +'xs' Name +' ' Text +'->' Operator.Word +' ' Text +'return' Name +' ' Text +'$' Operator +' ' Text +'Unknown' Keyword.Type +' ' Text +"xs'" Name +'\n ' Text +'|' Operator +' ' Text +'otherwise' Name +' ' Text +'->' Operator.Word +' ' Text +'mzero' Name +'\n ' Text +'findChange' Name +' ' Text +'_' Keyword.Reserved +' ' Text +'=' Operator.Word +' ' Text +'mzero' Name +'\n ' Text +'sanitize' Name +' ' Text +'grid' Name +' ' Text +'=' Operator.Word +' ' Text +'return' Name +' ' Text +'$' Operator +' ' Text +'grid' Name +' ' Text +'//' Operator +' ' Text +'[' Punctuation +'(' Punctuation +'l' Name +',' Punctuation +'Impossible' Keyword.Type +')' Punctuation +' ' Text +'|' Operator +' \n ' Text +'(' Punctuation +'l' Name +',' Punctuation +'x' Name +')' Punctuation +' ' Text +'<-' Operator.Word +' ' Text +'justKnowns' Name +' ' Text +'changes' Name +',' Punctuation +' ' Text +'x' Name +' ' Text +'`' Punctuation +'elem' Name +'`' Punctuation +' ' Text +'impossible' Name +' ' Text +'grid' Name +' ' Text +'l' Name +']' Punctuation +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\nThe ' Text +'{' Name.Builtin +'\\tt' Keyword +' eliminate' Text +'}' Name.Builtin +" phase tries to remove possible choices for ``Unknowns'' based on ``Known'' values in the same row,\ncolumn, or box as the ``Unknown'' value. For each cell on the grid we find its ``neighbors'', that is, cells in the\nsame row, column, or box. Out of those neighbors we get a list of all the ``Known'' values. We can eliminate all of\nthese from our list of candidates for this cell. If we're lucky enough to eliminate all the candidates but one we have\na new ``Known'' value. If we're unlucky enough to have eliminates " Text +'{' Name.Builtin +'\\bf' Keyword +' all' Text +'}' Name.Builtin +" the possible candidates we have a new\n``Impossible'' value.\n\nAfter iterating though every cell we make one more pass looking for conflicting changes. " Text +'{' Name.Builtin +'\\tt' Keyword +' sanitize' Text +'}' Name.Builtin +" marks cells as\n``Impossible'' if we have conflicting ``Known'' values.\n\n" Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'analyze' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Eq' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'Maybe' Keyword.Type +' ' Text +'(' Punctuation +'Sudoku' Keyword.Type +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'analyze' Name.Function +' ' Text +'(' Punctuation +'Sudoku' Keyword.Type +' ' Text +'grid' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'fmap' Name +' ' Text +'Sudoku' Keyword.Type +' ' Text +'$' Operator +' ' Text +'updateGrid' Name +' ' Text +'grid' Name +' ' Text +'$' Operator +' ' Text +'nub' Name +' ' Text +'[' Punctuation +'u' Name +' ' Text +'|' Operator +'\n ' Text +'f' Name +' ' Text +'<-' Operator.Word +' ' Text +'map' Name +' ' Text +'(' Punctuation +'$' Operator +'grid' Name +')' Punctuation +' ' Text +'[' Punctuation +'getRow' Name +',' Punctuation +'getCol' Name +',' Punctuation +'getBox' Name +']' Punctuation +',' Punctuation +'\n ' Text +'n' Name +' ' Text +'<-' Operator.Word +' ' Text +'[' Punctuation +'0' Literal.Number.Integer +'..' Operator +'size' Name +' ' Text +'grid' Name +' ' Text +'-' Operator +' ' Text +'1' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'u' Name +' ' Text +'<-' Operator.Word +' ' Text +'unique' Name +' ' Text +'(' Punctuation +'f' Name +' ' Text +'n' Name +')' Punctuation +']' Punctuation +'\n ' Text +'where' Keyword.Reserved +'\n ' Text +'unique' Name +' ' Text +'xs' Name +' ' Text +'=' Operator.Word +' ' Text +'foldr' Name +' ' Text +'f' Name +' ' Text +'[]' Keyword.Type +' ' Text +'$' Operator +' ' Text +'foldr' Name +' ' Text +'(' Punctuation +'union' Name +'.' Operator +'snd' Name +')' Punctuation +' ' Text +'[]' Keyword.Type +' ' Text +'unknowns' Name +' ' Text +'\\\\' Operator +' ' Text +'map' Name +' ' Text +'snd' Name +' ' Text +'(' Punctuation +'justKnowns' Name +' ' Text +'xs' Name +')' Punctuation +'\n ' Text +'where' Keyword.Reserved +'\n ' Text +'unknowns' Name +' ' Text +'=' Operator.Word +' ' Text +'justUnknowns' Name +' ' Text +'xs' Name +'\n ' Text +'f' Name +' ' Text +'c' Name +' ' Text +'=' Operator.Word +' ' Text +'case' Keyword.Reserved +' ' Text +'filter' Name +' ' Text +'(' Punctuation +'(' Punctuation +'c' Name +'`' Punctuation +'elem' Name +'`' Punctuation +')' Punctuation +'.' Operator +'snd' Name +')' Punctuation +' ' Text +'unknowns' Name +' ' Text +'of' Keyword.Reserved +'\n ' Text +'[' Punctuation +'(' Punctuation +'p' Name +',' Punctuation +'_' Keyword.Reserved +')' Punctuation +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +'(' Punctuation +'p' Name +',' Punctuation +'Known' Keyword.Type +' ' Text +'c' Name +')' Punctuation +':' Keyword.Type +')' Punctuation +'\n ' Text +'_' Keyword.Reserved +' ' Text +'->' Operator.Word +' ' Text +'id' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\nThe ' Text +'{' Name.Builtin +'\\tt' Keyword +' analyze' Text +'}' Name.Builtin +" phase tries to turn ``Unknowns'' into ``Knowns'' when a certain ``Unknown'' is the only cell that\ncontains a value needed in a given row, column, or box. We apply each of the functions " Text +'{' Name.Builtin +'\\tt' Keyword +' getRow' Text +'}' Name.Builtin +', ' Text +'{' Name.Builtin +'\\tt' Keyword +' getCol' Text +'}' Name.Builtin +', and\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' getBox' Text +'}' Name.Builtin +' to all the indices on the grid, apply ' Text +'{' Name.Builtin +'\\tt' Keyword +' unique' Text +'}' Name.Builtin +' to each group, and update the array with the\nresults. ' Text +'{' Name.Builtin +'\\tt' Keyword +' unique' Text +'}' Name.Builtin +' gets a list of all the unknown cells in the group and finds all the unknown values in each of\nthose cells. Each of these values are iterated though looking for a value that is only contained in one cell. If such a\nvalue is found the cell containing it must be that value.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'backtrack' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'MonadPlus' Keyword.Type +' ' Text +'m' Name +',' Punctuation +' ' Text +'Eq' Keyword.Type +' ' Text +'a' Name +')' Punctuation +' ' Text +'=>' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'m' Name +' ' Text +'(' Punctuation +'Sudoku' Keyword.Type +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'backtrack' Name.Function +' ' Text +'(' Punctuation +'Sudoku' Keyword.Type +' ' Text +'grid' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'case' Keyword.Reserved +' ' Text +'(' Punctuation +'justUnknowns' Name +' ' Text +'(' Punctuation +'assocs' Name +' ' Text +'grid' Name +')' Punctuation +')' Punctuation +' ' Text +'of' Keyword.Reserved +'\n ' Text +'[]' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'return' Name +' ' Text +'$' Operator +' ' Text +'Sudoku' Keyword.Type +' ' Text +'grid' Name +'\n ' Text +'(' Punctuation +'(' Punctuation +'p' Name +',' Punctuation +'xs' Name +')' Punctuation +':' Keyword.Type +'_' Keyword.Reserved +')' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'msum' Name +' ' Text +'$' Operator +' ' Text +'map' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'x' Name +' ' Text +'->' Operator.Word +' ' Text +'solve' Name +' ' Text +'$' Operator +' ' Text +'Sudoku' Keyword.Type +' ' Text +'$' Operator +' ' Text +'grid' Name +' ' Text +'//' Operator +' ' Text +'[' Punctuation +'(' Punctuation +'p' Name +',' Punctuation +'Known' Keyword.Type +' ' Text +'x' Name +')' Punctuation +']' Punctuation +')' Punctuation +' ' Text +'xs' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +"\n\nSometimes the above two phases still aren't enough to solve a puzzle. For these rare puzzles backtracking is required.\nWe attempt to solve the puzzle by replacing the first ``Unknown'' value with each of the candidate values and solving\nthe resulting puzzles. Hopefully at least one of our choices will result in a solvable puzzle.\n\nWe could actually solve any puzzle using backtracking alone, although this would be very inefficient. The above\nfunctions simplify most puzzles enough that the backtracking phase has to do hardly any work.\n\n" Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'solve' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'(' Punctuation +'MonadPlus' Keyword.Type +' ' Text +'m' Name +',' Punctuation +' ' Text +'Eq' Keyword.Type +' ' Text +'a' Name +')' Punctuation +' ' Text +'=>' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'m' Name +' ' Text +'(' Punctuation +'Sudoku' Keyword.Type +' ' Text +'a' Name +')' Punctuation +'\n' Text + +'solve' Name.Function +' ' Text +'sudoku' Name +' ' Text +'=' Operator.Word +' \n ' Text +'case' Keyword.Reserved +' ' Text +'eliminate' Name +' ' Text +'sudoku' Name +' ' Text +'of' Keyword.Reserved +'\n ' Text +'Just' Keyword.Type +' ' Text +'new' Name +' \n ' Text +'|' Operator +' ' Text +'any' Name +' ' Text +'(' Punctuation +'==' Operator +'Impossible' Keyword.Type +')' Punctuation +' ' Text +'(' Punctuation +'elems' Name +' ' Text +'(' Punctuation +'unSudoku' Name +' ' Text +'new' Name +')' Punctuation +')' Punctuation +'->' Operator.Word +' ' Text +'mzero' Name +'\n ' Text +'|' Operator +' ' Text +'otherwise' Name +' ' Text +'->' Operator.Word +' ' Text +'solve' Name +' ' Text +'new' Name +'\n ' Text +'Nothing' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'case' Keyword.Reserved +' ' Text +'analyze' Name +' ' Text +'sudoku' Name +' ' Text +'of' Keyword.Reserved +'\n ' Text +'Just' Keyword.Type +' ' Text +'new' Name +' ' Text +'->' Operator.Word +' ' Text +'solve' Name +' ' Text +'new' Name +'\n ' Text +'Nothing' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'backtrack' Name +' ' Text +'sudoku' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' solve' Text +'}' Name.Builtin +' glues all the above phases together. First we run the ' Text +'{' Name.Builtin +'\\tt' Keyword +' eliminate' Text +'}' Name.Builtin +' phase. If that found the puzzle to\nbe unsolvable we abort immediately. If ' Text +'{' Name.Builtin +'\\tt' Keyword +' eliminate' Text +'}' Name.Builtin +' changed the grid we go though the ' Text +'{' Name.Builtin +'\\tt' Keyword +' eliminate' Text +'}' Name.Builtin +' phase again\nhoping to eliminate more. Once ' Text +'{' Name.Builtin +'\\tt' Keyword +' eliminate' Text +'}' Name.Builtin +' can do no more work we move on to the ' Text +'{' Name.Builtin +'\\tt' Keyword +' analyze' Text +'}' Name.Builtin +' phase. If this\nsucceeds in doing some work we start over again with the ' Text +'{' Name.Builtin +'\\tt' Keyword +' eliminate' Text +'}' Name.Builtin +' phase. Once ' Text +'{' Name.Builtin +'\\tt' Keyword +' analyze' Text +'}' Name.Builtin +" can do no more work\nwe have no choice but to resort to backtracking. (However in most cases backtracking won't actually do anything because\nthe puzzle is already solved.)\n\n" Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'showsCell' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Show' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'CellState' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'ShowS' Keyword.Type +'\n' Text + +'showsCell' Name.Function +' ' Text +'(' Punctuation +'Known' Keyword.Type +' ' Text +'x' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'shows' Name +' ' Text +'x' Name +'\n' Text + +'showsCell' Name.Function +' ' Text +'(' Punctuation +'Impossible' Keyword.Type +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'showChar' Name +' ' Text +"'X'" Literal.String.Char +'\n' Text + +'showsCell' Name.Function +' ' Text +'(' Punctuation +'Unknown' Keyword.Type +' ' Text +'xs' Name +')' Punctuation +' ' Text +'=' Operator.Word +' ' Text +'\\' Name.Function +'rest' Name +' ' Text +'->' Operator.Word +' ' Text +'(' Punctuation +"'('" Literal.String.Char +':' Keyword.Type +')' Punctuation +' \n ' Text +'$' Operator +' ' Text +'foldr' Name +' ' Text +'id' Name +' ' Text +'(' Punctuation +"')'" Literal.String.Char +':' Keyword.Type +'rest' Name +')' Punctuation +'\n ' Text +'$' Operator +' ' Text +'intersperse' Name +' ' Text +'(' Punctuation +'showChar' Name +' ' Text +"' '" Literal.String.Char +')' Punctuation +'\n ' Text +'$' Operator +' ' Text +'map' Name +' ' Text +'shows' Name +' ' Text +'xs' Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' showCell' Text +'}' Name.Builtin +' shows a cell.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'showsGrid' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Show' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'Grid' Keyword.Type +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'ShowS' Keyword.Type +'\n' Text + +'showsGrid' Name.Function +' ' Text +'grid' Name +' ' Text +'=' Operator.Word +' ' Text +'showsTable' Name +' ' Text +'[' Punctuation +'[' Punctuation +'grid' Name +'!' Operator +'(' Punctuation +'r' Name +',' Punctuation +'c' Name +')' Punctuation +' ' Text +'|' Operator +' ' Text +'c' Name +' ' Text +'<-' Operator.Word +' ' Text +'[' Punctuation +'0' Literal.Number.Integer +'..' Operator +'size' Name +' ' Text +'grid' Name +'-' Operator +'1' Literal.Number.Integer +']' Punctuation +']' Punctuation +' ' Text +'|' Operator +' ' Text +'r' Name +' ' Text +'<-' Operator.Word +' ' Text +'[' Punctuation +'0' Literal.Number.Integer +'..' Operator +'size' Name +' ' Text +'grid' Name +'-' Operator +'1' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' showGrid' Text +'}' Name.Builtin +' show a grid.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'-- FEATURE: This is pretty inefficient' Comment.Single +'\n' Text + +'showsTable' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Show' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'[' Punctuation +'[' Punctuation +'a' Name +']' Punctuation +']' Punctuation +' ' Text +'->' Operator.Word +' ' Text +'ShowS' Keyword.Type +'\n' Text + +'showsTable' Name.Function +' ' Text +'xs' Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'showChar' Name +' ' Text +"'\\" Keyword.Type +"n'" Name +' ' Text +'.' Operator +')' Punctuation +' ' Text +'$' Operator +' ' Text +'showString' Name +' ' Text +'$' Operator +' ' Text +'unlines' Name +' ' Text +'$' Operator +' ' Text +'map' Name +' ' Text +'(' Punctuation +'concat' Name +' ' Text +'.' Operator +' ' Text +'intersperse' Name +' ' Text +'"' Literal.String +' ' Literal.String +'"' Literal.String +')' Punctuation +' ' Text +"xs''" Name +'\n ' Text +'where' Keyword.Reserved +'\n ' Text +"xs'" Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'map' Name +'.' Operator +'map' Name +')' Punctuation +' ' Text +'show' Name +' ' Text +'xs' Name +'\n ' Text +'colWidths' Name +' ' Text +'=' Operator.Word +' ' Text +'map' Name +' ' Text +'(' Punctuation +'max' Name +' ' Text +'2' Literal.Number.Integer +' ' Text +'.' Operator +' ' Text +'maximum' Name +' ' Text +'.' Operator +' ' Text +'map' Name +' ' Text +'length' Name +')' Punctuation +' ' Text +'(' Punctuation +'transpose' Name +' ' Text +"xs'" Name +')' Punctuation +'\n ' Text +"xs''" Name +' ' Text +'=' Operator.Word +' ' Text +'map' Name +' ' Text +'(' Punctuation +'zipWith' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'n' Name +' ' Text +'s' Name +' ' Text +'->' Operator.Word +' ' Text +'s' Name +' ' Text +'++' Operator +' ' Text +'(' Punctuation +'replicate' Name +' ' Text +'(' Punctuation +'n' Name +' ' Text +'-' Operator +' ' Text +'length' Name +' ' Text +'s' Name +')' Punctuation +' ' Text +"' '" Literal.String.Char +')' Punctuation +')' Punctuation +' ' Text +'colWidths' Name +')' Punctuation +' ' Text +"xs'" Name +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' showsTable' Text +'}' Name.Builtin +' shows a table (or matrix). Every column has the same width so things line up.\n\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'intSqrt' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Integral' Keyword.Type +' ' Text +'a' Name +' ' Text +'=>' Operator.Word +' ' Text +'a' Name +' ' Text +'->' Operator.Word +' ' Text +'a' Name +'\n' Text + +'intSqrt' Name.Function +' ' Text +'n' Name +'\n ' Text +'|' Operator +' ' Text +'n' Name +' ' Text +'<' Operator +' ' Text +'0' Literal.Number.Integer +' ' Text +'=' Operator.Word +' ' Text +'error' Name.Exception +' ' Text +'"' Literal.String +'intSqrt: negative n' Literal.String +'"' Literal.String +'\n ' Text +'|' Operator +' ' Text +'otherwise' Name +' ' Text +'=' Operator.Word +' ' Text +'f' Name +' ' Text +'n' Name +'\n ' Text +'where' Keyword.Reserved +'\n ' Text +'f' Name +' ' Text +'x' Name +' ' Text +'=' Operator.Word +' ' Text +'if' Keyword.Reserved +' ' Text +'y' Name +' ' Text +'<' Operator +' ' Text +'x' Name +' ' Text +'then' Keyword.Reserved +' ' Text +'f' Name +' ' Text +'y' Name +' ' Text +'else' Keyword.Reserved +' ' Text +'x' Name +'\n ' Text +'where' Keyword.Reserved +' ' Text +'y' Name +' ' Text +'=' Operator.Word +' ' Text +'(' Punctuation +'x' Name +' ' Text +'+' Operator +' ' Text +'(' Punctuation +'n' Name +' ' Text +'`' Punctuation +'quot' Name +'`' Punctuation +' ' Text +'x' Name +')' Punctuation +')' Punctuation +' ' Text +'`' Punctuation +'quot' Name +'`' Punctuation +' ' Text +'2' Literal.Number.Integer +'\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n\n' Text + +'{' Name.Builtin +'\\tt' Keyword +' intSqrt' Text +'}' Name.Builtin +' is Newton`s Iteration for finding integral square roots.\n\n' Text + +'\\ignore' Keyword +'{' Name.Builtin +'\n' Text + +'\\begin' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'test' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'Int' Keyword.Type +'\n' Text + +'test' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'makeSudoku' Name +' ' Text +'[' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n\n' Text + +'test2' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'Int' Keyword.Type +'\n' Text + +'test2' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'makeSudoku' Name +' ' Text +'[' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n\n' Text + +'testSmall' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'Int' Keyword.Type +'\n' Text + +'testSmall' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'makeSudoku' Name +' ' Text +'[' Punctuation +'\n ' Text +'[' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n\n' Text + +'testHard' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'Int' Keyword.Type +'\n' Text + +'testHard' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'makeSudoku' Name +' ' Text +'[' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n\n' Text + +'testHard2' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'Int' Keyword.Type +'\n' Text + +'testHard2' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'makeSudoku' Name +' ' Text +'[' Punctuation +'\n ' Text +'[' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'4' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n\n' Text + +'testHW' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'Int' Keyword.Type +'\n' Text + +'testHW' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'makeSudoku' Name +' ' Text +'[' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +']' Punctuation +',' Punctuation +' \n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'7' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'3' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'2' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'1' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'8' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +',' Punctuation +'\n ' Text +'[' Punctuation +'6' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'5' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'9' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +',' Punctuation +'0' Literal.Number.Integer +']' Punctuation +']' Punctuation +'\n\n' Text + +'testTough' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'Int' Keyword.Type +'\n' Text + +'testTough' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'makeSudoku' Name +' ' Text +'$' Operator +' ' Text +'map' Name +' ' Text +'(' Punctuation +'map' Name +' ' Text +'read' Name +' ' Text +'.' Operator +' ' Text +'words' Name +')' Punctuation +' ' Text +'$' Operator +' ' Text +'lines' Name +' ' Text +'$' Operator +'\n ' Text +'"' Literal.String +'8 3 0 0 0 0 0 4 6' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 2 0 1 0 4 0 3 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 0 0 0 0 0 0 0 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 0 2 9 0 6 5 0 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'1 4 0 0 0 0 0 2 3' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 0 5 4 0 3 1 0 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 0 0 0 0 0 0 0 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 6 0 3 0 8 0 7 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'9 5 0 0 0 0 0 6 2' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'\n\n' Text + +'testDiabolical' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'Sudoku' Keyword.Type +' ' Text +'Int' Keyword.Type +' \n' Text + +'testDiabolical' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'makeSudoku' Name +' ' Text +'$' Operator +' ' Text +'map' Name +' ' Text +'(' Punctuation +'map' Name +' ' Text +'read' Name +' ' Text +'.' Operator +' ' Text +'words' Name +')' Punctuation +' ' Text +'$' Operator +' ' Text +'lines' Name +' ' Text +'$' Operator +'\n ' Text +'"' Literal.String +'8 0 0 7 0 1 0 0 2' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 0 6 0 0 0 7 0 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 1 7 0 0 0 8 9 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 0 0 1 7 3 0 0 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'7 0 0 0 0 0 0 0 6' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 0 0 9 5 6 0 0 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 9 5 0 0 0 4 1 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'0 0 8 0 0 0 5 0 0' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'++' Operator +'\n ' Text +'"' Literal.String +'3 0 0 6 0 5 0 0 7' Literal.String +'\\' Literal.String.Escape +'n' Literal.String.Escape +'"' Literal.String +'\n\n' Text + +'main' Name.Function +' ' Text +'::' Operator.Word +' ' Text +'IO' Keyword.Type +' ' Text +'()' Name.Builtin +'\n' Text + +'main' Name.Function +' ' Text +'=' Operator.Word +' ' Text +'do' Keyword.Reserved +'\n ' Text +'let' Keyword.Reserved +'\n ' Text +"solve'" Name +' ' Text +'p' Name +' ' Text +'=' Operator.Word +' ' Text +'case' Keyword.Reserved +' ' Text +'solve' Name +' ' Text +'p' Name +' ' Text +'of' Keyword.Reserved +'\n ' Text +'[]' Keyword.Type +' ' Text +'->' Operator.Word +' ' Text +'fail' Name +' ' Text +'$' Operator +' ' Text +'"' Literal.String +"couldn't solve: " Literal.String +'"' Literal.String +' ' Text +'++' Operator +' ' Text +'show' Name +' ' Text +'p' Name +'\n ' Text +'sols' Name +' ' Text +'->' Operator.Word +' ' Text +'return' Name +' ' Text +'sols' Name +'\n ' Text +'mapM_' Name +' ' Text +'(' Punctuation +'\\' Name.Function +'p' Name +' ' Text +'->' Operator.Word +' ' Text +"solve'" Name +' ' Text +'p' Name +' ' Text +'>>=' Operator +' ' Text +'putStrLn' Name +'.' Operator +'show' Name +')' Punctuation +' ' Text +'[' Punctuation +'test' Name +',' Punctuation +'test2' Name +',' Punctuation +'testSmall' Name +',' Punctuation +'testHard' Name +',' Punctuation +'testHard2' Name +',' Punctuation +'testHW' Name +',' Punctuation +'testTough' Name +',' Punctuation +'testDiabolical' Name +']' Punctuation +'\n ' Text +'return' Name +' ' Text +'()' Name.Builtin +'\n\n' Text + +'\\end' Keyword +'{' Name.Builtin +'code' Text +'}' Name.Builtin +'\n' Text + +'}' Name.Builtin +'\n\n' Text + +'\\end' Keyword +'{' Name.Builtin +'document' Text +'}' Name.Builtin +'\n' Text |
