Skip to content

Instantly share code, notes, and snippets.

@shoooe
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shoooe/9ad521def2a934e5e62b to your computer and use it in GitHub Desktop.
Save shoooe/9ad521def2a934e5e62b to your computer and use it in GitHub Desktop.
Exercise that I should have done in Java, but I decided to do in 100 lines of Haskell.
0 A VUOTO 1 2 VUOTO
1 B VUOTO VUOTO 3 0
2 C 0 3 VUOTO VUOTO
3 D 1 VUOTO VUOTO 2
{-# LANGUAGE OverloadedStrings #-}
module Main where
import System.IO (FilePath, withFile, hPutStrLn, IOMode(..))
import Data.Text (Text)
import Data.Map (Map)
import Data.List (find)
import System.Environment (getArgs)
import qualified Data.Map as M
import qualified Data.Text.IO as TIO
import qualified Data.Text as T
import Prelude hiding (id)
type PieceId = Text
type PieceContent = Char
data Piece = Piece { character :: PieceContent
, id :: PieceId
, northId :: PieceId
, eastId :: PieceId
, southId :: PieceId
, westId :: PieceId
} deriving (Eq, Show)
noneId :: Text
noneId = "VUOTO"
type UnsolvedPuzzle = [Piece]
type SolvedPuzzle = [[Piece]]
getFileLines :: FilePath -> IO [Text]
getFileLines path = do
content <- TIO.readFile path
return $ T.lines content
parsePieces :: [Text] -> UnsolvedPuzzle
parsePieces lines = map parsePiece $ lines
where parsePiece :: Text -> Piece
parsePiece s =
let segs = map T.strip $ T.split (== '\t') s
in Piece { character = T.head $ segs !! 1
, id = segs !! 0
, northId = segs !! 2
, eastId = segs !! 3
, southId = segs !! 4
, westId = segs !! 5 }
buildMap :: UnsolvedPuzzle -> Map PieceId Piece
buildMap ps = M.fromList . map buildMapElem $ ps
where buildMapElem :: Piece -> (PieceId, Piece)
buildMapElem p = (id p, p)
isTopLeft :: Piece -> Bool
isTopLeft p = northId p == noneId && westId p == noneId
getPiecesAlong :: (Piece -> PieceId) -> Map PieceId Piece -> Piece -> [Piece]
getPiecesAlong ex m p
| ex p == noneId = [p]
| otherwise =
let (Just np) = M.lookup (ex p) m
in p : getPiecesAlong ex m np
solvePuzzle :: UnsolvedPuzzle -> SolvedPuzzle
solvePuzzle ps =
let m = buildMap ps
(Just tl) = find isTopLeft ps
in map (getPiecesAlong eastId m) (getPiecesAlong southId m tl)
getPuzzleSize :: SolvedPuzzle -> (Int, Int)
getPuzzleSize sp = (w, h)
where w = (length . head) sp
h = length sp
showPuzzleString :: SolvedPuzzle -> String
showPuzzleString = map character . concat
showPuzzleSize :: SolvedPuzzle -> String
showPuzzleSize = (\(w, h) -> concat [show w, " ", show h]) . getPuzzleSize
showPuzzleTable :: SolvedPuzzle -> String
showPuzzleTable = concat . map ((++ "\n") . map character)
main :: IO ()
main = do
[inputPath, outputPath] <- getArgs
lines <- getFileLines inputPath
withFile outputPath WriteMode $ \fh -> do
let hPutStrLn2 fh = hPutStrLn fh . (++ "\n")
let sp = solvePuzzle . parsePieces $ lines
hPutStrLn2 fh . showPuzzleString $ sp
hPutStrLn fh . showPuzzleTable $ sp
hPutStrLn fh . showPuzzleSize $ sp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment