0
0

More than 5 years have passed since last update.

# ビットボンバーマン(2013.3.1の過去問)

Posted at

``````{-# LANGUAGE Rank2Types #-}
module Doukaku.Bomberman where
import qualified Data.Array.IArray as IArray
import Control.Lens (review, preview)
import Control.Lens.Prism (Prism')
import Data.Array.Unboxed (UArray)
import Numeric.Lens (hex, binary)

type Board = UArray (Int, Int) Bool

solve :: String -> String
solve input = trans binary hex . (++ "00") . map char \$ [0..width * height - 1]
where
(ws, _:bs) = break (== '/') input
wall = parse ws
bomb = parse bs
char pos = let (y, x) = divMod pos width
in if isFired wall bomb (x, y) then '1' else '0'

width, height :: Int
(width, height) = (6, 5)

trans :: Prism' String Int -> Prism' String Int -> String -> String
trans from to = tail . maybe "" (review to) . preview from . ('1' :)

parse :: String -> Board
parse input' = IArray.listArray ((0, 0), (height - 1, width - 1)) (map toBool input)
where
input = trans hex binary input'
toBool '0' = False
toBool _   = True

isFired :: Board -> Board -> (Int, Int) -> Bool
isFired wall bomb (x, y) = or . map (existBomb wall bomb (x, y)) \$
[(1, 0), (-1, 0), (0, 1), (0, -1)]

existBomb :: Board -> Board -> (Int, Int) -> (Int, Int) -> Bool
existBomb wall bomb (x, y) (vx, vy)
| x < 0 || width <= x || y < 0 || height <= y = False
| bomb IArray.! (y, x) = True
| wall IArray.! (y, x) = False
| otherwise = existBomb wall bomb (x + vx, y + vy) (vx, vy)
``````

`isFired`関数で上下左右に爆弾があるかを探すだけです。その際、頻繁に`(x, y)`の要素を参照する必要があったので、
`[[Bool]]`ではなく`UArray (Int, Int) Bool`を使ってみました。

http://qiita.com/items/709d61dff282cff7a890 に他の方の回答もありますので、見ると参考になるでしょう。

0
0
0

Register as a new user and use Qiita more conveniently

1. You get articles that match your needs
2. You can efficiently read back useful information
3. You can use dark theme
What you can do with signing up
0
0