import Data.Array import Data.Monoid import Data.Foldable (foldMap) main :: IO () main = (print . minTurns) =<< fmap read getLine minTurns :: (Int, Int) -> Int minTurns x | x < (0, 0) = -1 | otherwise = let ls = search genBoards goal (uncurry (*) x) [initialBoard x] in case ls of Nothing -> -1; Just a -> length a - 1 data Tile = Tile {painted :: Bool, wet :: Int} deriving (Eq) data Board = Board {pos :: (Int, Int), tiles :: Array (Int, Int) Tile} deriving (Eq) type Boards = [Board] initialBoard :: (Int, Int) -> Board initialBoard x = Board (1, 1) (listArray ((1, 1), x) $ repeat (Tile False 0)) goal :: Boards -> Bool goal [] = False goal ((Board _ ts):_) = all painted $ elems ts mandist :: (Int, Int) -> (Int, Int) -> Int mandist (x1, y1) (x2, y2) = abs (x1 - x2) + abs (y1 - y2) genBoards :: Boards -> [Boards] genBoards [] = [] genBoards n@(b:_) = genBoards' b where genBoards' (Board p ts) = [b' : n | b' <- allPaints ++ allSteps ++ [Board p ts']] where allPaints :: Boards allPaints = [Board p (ts' // [(i, t {painted = True, wet = 5})]) | (i, t) <- assocs ts, mandist p i == 1, not (painted t)] allSteps :: Boards allSteps = [Board i ts' | (i, t) <- assocs ts, mandist p i == 1, wet t == 0] ts' = fmap (\t -> t {wet = dry t}) ts dry t | w <- wet t, w > 0 = w - 1 | otherwise = 0 search :: (Eq a) => (a -> [a]) -> (a -> Bool) -> Int -> a -> Maybe a search f g l x = getFirst $ foldMap (search' ([x])) ([l..] :: [Int]) where search' (y:ys) d | d == 0 = mempty | g y = First $ Just y | otherwise = search' (f y) (d - 1) <> search' ys d search' _ _ = mempty