---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
