import Data.Array
import Data.Monoid
import Data.Foldable (foldMap)
minTurns x
| x < (0, 0) = -1
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 [] = False
goal
((Board
_ ts
):
_) = all painted
$ elems ts
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
search f g l x = getFirst $ foldMap (search' ([x])) ([l..] :: [Int])
where
search' (y:ys) d
| d == 0 = mempty
| g y = First $ Just y
search' (f y) (d - 1) <> search' ys d
search' _ _ = mempty
aW1wb3J0IERhdGEuQXJyYXkKaW1wb3J0IERhdGEuTW9ub2lkCmltcG9ydCBEYXRhLkZvbGRhYmxlIChmb2xkTWFwKQoKbWFpbiA6OiBJTyAoKQptYWluID0gKHByaW50IC4gbWluVHVybnMpID08PCBmbWFwIHJlYWQgZ2V0TGluZQoKbWluVHVybnMgOjogKEludCwgSW50KSAtPiBJbnQKbWluVHVybnMgeAogIHwgeCA8ICgwLCAwKSA9IC0xCiAgfCBvdGhlcndpc2UgID0KICAgIGxldCBscyA9IHNlYXJjaCBnZW5Cb2FyZHMgZ29hbCAodW5jdXJyeSAoKikgeCkgW2luaXRpYWxCb2FyZCB4XQogICAgaW4gY2FzZSBscyBvZiBOb3RoaW5nIC0+IC0xOyBKdXN0IGEgIC0+IGxlbmd0aCBhIC0gMQoKZGF0YSBUaWxlID0gVGlsZSB7cGFpbnRlZCA6OiBCb29sLCB3ZXQgOjogSW50fSBkZXJpdmluZyAoRXEpCmRhdGEgQm9hcmQgPSBCb2FyZCB7cG9zIDo6IChJbnQsIEludCksIHRpbGVzIDo6IEFycmF5IChJbnQsIEludCkgVGlsZX0gZGVyaXZpbmcgKEVxKQp0eXBlIEJvYXJkcyA9IFtCb2FyZF0KCmluaXRpYWxCb2FyZCA6OiAoSW50LCBJbnQpIC0+IEJvYXJkCmluaXRpYWxCb2FyZCB4ID0gQm9hcmQgKDEsIDEpIChsaXN0QXJyYXkgKCgxLCAxKSwgeCkgJCByZXBlYXQgKFRpbGUgRmFsc2UgMCkpCgpnb2FsIDo6IEJvYXJkcyAtPiBCb29sCmdvYWwgW10gICAgICAgICAgICAgICAgPSBGYWxzZQpnb2FsICgoQm9hcmQgXyB0cyk6XykgID0gYWxsIHBhaW50ZWQgJCBlbGVtcyB0cwoKbWFuZGlzdCA6OiAoSW50LCBJbnQpIC0+IChJbnQsIEludCkgLT4gSW50Cm1hbmRpc3QgKHgxLCB5MSkgKHgyLCB5MikgPSBhYnMgKHgxIC0geDIpICsgYWJzICh5MSAtIHkyKQoKZ2VuQm9hcmRzIDo6IEJvYXJkcyAtPiBbQm9hcmRzXQpnZW5Cb2FyZHMgW10gPSBbXQpnZW5Cb2FyZHMgbkAoYjpfKSA9IGdlbkJvYXJkcycgYgogIHdoZXJlCiAgICBnZW5Cb2FyZHMnIChCb2FyZCBwIHRzKSA9IFtiJyA6IG4gfCBiJyA8LSBhbGxQYWludHMgKysgYWxsU3RlcHMgKysgW0JvYXJkIHAgdHMnXV0KICAgICAgd2hlcmUKICAgICAgICBhbGxQYWludHMgOjogQm9hcmRzCiAgICAgICAgYWxsUGFpbnRzID0KICAgICAgICAgIFtCb2FyZCBwICh0cycgLy8gWyhpLCB0IHtwYWludGVkID0gVHJ1ZSwgd2V0ID0gNX0pXSkKICAgICAgICAgICAgfCAoaSwgdCkgPC0gYXNzb2NzIHRzLCBtYW5kaXN0IHAgaSA9PSAxLCBub3QgKHBhaW50ZWQgdCldCiAgICAgICAgYWxsU3RlcHMgOjogQm9hcmRzCiAgICAgICAgYWxsU3RlcHMgPQogICAgICAgICAgW0JvYXJkIGkgdHMnCiAgICAgICAgICAgIHwgKGksIHQpIDwtIGFzc29jcyB0cywgbWFuZGlzdCBwIGkgPT0gMSwgd2V0IHQgPT0gMF0KICAgICAgICB0cycgPSBmbWFwIChcdCAtPiB0IHt3ZXQgPSBkcnkgdH0pIHRzCiAgICAgICAgZHJ5IHQgfCB3IDwtIHdldCB0LCB3ID4gMCA9IHcgLSAxCiAgICAgICAgICAgICAgfCBvdGhlcndpc2UgICAgICAgICA9IDAKCnNlYXJjaCA6OiAoRXEgYSkgPT4gKGEgLT4gW2FdKSAtPiAoYSAtPiBCb29sKSAtPiBJbnQgLT4gYSAtPiBNYXliZSBhCnNlYXJjaCBmIGcgbCB4ID0gZ2V0Rmlyc3QgJCBmb2xkTWFwIChzZWFyY2gnIChbeF0pKSAoW2wuLl0gOjogW0ludF0pCiAgd2hlcmUKICAgIHNlYXJjaCcgKHk6eXMpIGQKICAgICAgfCBkID09IDAgICAgPSBtZW1wdHkKICAgICAgfCBnIHkgICAgICAgPSBGaXJzdCAkIEp1c3QgeQogICAgICB8IG90aGVyd2lzZSA9CiAgICAgICAgc2VhcmNoJyAoZiB5KSAoZCAtIDEpIDw+IHNlYXJjaCcgeXMgZAogICAgc2VhcmNoJyBfIF8gICA9IG1lbXB0eQo=