packages feed

unscramble-1.0: src/Unscramble/Input.hs

module Unscramble.Input (
    readGrid,
    readMult
) where

import Control.Applicative
import Control.Monad
import Data.Array
import Data.Char
import qualified Data.HashMap.Strict as H
import Data.List
import Data.Maybe
import System.IO
import Text.Printf
import Unscramble.Types

readMult :: IO Multiplier
readMult = do
    dls <- putStrLn "Enter coordinates for double letters, in\
           \ the form 'x y'. The lower left corner is '1 1'\
           \ and the top right is '4 4'. Press enter after each\
           \ set of coordinates. If there are no double\
           \ letters, press enter." >> getCoords
    dws <- putStrLn "Enter coordinates for double words. If there\
           \ are no double words, press enter." >> getCoords
    tls <- putStrLn "Enter coordinates for triple letters. If there\
           \ are no triple letters, press enter." >> getCoords
    tws <- putStrLn "Enter coordinates for triple words. If there\
           \ are no triple words, press enter." >> getCoords
    return $ Multiplier dls (listToMaybe dws) tls (listToMaybe tws)
    where
        getCoords = do
            eo <- isEOF
            if eo
                then return []
                else do
                    r <- getLine
                    case words r of
                        [a,b] -> do
                            l <- getCoords
                            return $ (4 - read b, read a - 1):l
                        [] -> return []
                        _ -> putStrLn "Invalid coordinates." >> return []

readGrid :: Int -> IO Grid
readGrid n = do
    _ <- printf "Enter a %dx%d grid. Remember:\n\
        \- Input only letters and press enter after each line.\n\
        \- You may enter a 'qu' tile as 'qu'.\n" n n
    lines' <- replicateM n (filter isLetter <$> getLine)
    putStrLn "Received grid."
    return $ arraign lines'

arraign :: [String] -> Grid
arraign grid = Grid (hash ar) ar
  where ar = array ((0,0),(len,len)) . redist . zip [0..]
           $ map (zip [0..] . groupBy (\x y -> [x,y] == "qu")) grid
        hash a = foldr (\(i,k) h -> H.insertWith (flip (++)) k [i] h) H.empty (assocs a)
        len = pred . length $ head grid
        redist ((x,ys):xs) = map (\(a,b) -> ((a,x),b)) ys ++ redist xs
        redist [] = []