{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE BangPatterns          #-}
{-# LANGUAGE CPP                   #-}
{-# LANGUAGE LambdaCase            #-}
{-# LANGUAGE MagicHash             #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MultiWayIf            #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TupleSections         #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE ViewPatterns          #-}

import           Control.Applicative
import           Control.Exception
import           Control.Monad
import           Control.Monad.Primitive
import           Control.Monad.ST
import           Control.Monad.State.Strict
import           Data.Bool
import qualified Data.ByteString             as B
import qualified Data.ByteString.Char8       as C
import qualified Data.ByteString.Unsafe      as B
import           Data.Char
import qualified Data.Foldable               as F
import           Data.Function
import qualified Data.IntMap.Strict          as IM
import qualified Data.IntSet                 as IS
import qualified Data.List                   as L
import qualified Data.Map.Strict             as M
import           Data.Monoid
import           Data.Ord
import           Data.Primitive.ByteArray
import           Data.Primitive.MutVar
import qualified Data.Primitive.Types        as P

import qualified Data.Set                    as S
import           Data.Tuple
import qualified Data.Vector                 as V
import qualified Data.Vector.Generic         as G
import qualified Data.Vector.Generic.Mutable as GM
import qualified Data.Vector.Unboxed         as U
import qualified Data.Vector.Unboxed.Mutable as UM
import           Debug.Trace
import           Foreign                     hiding (void)
import           GHC.Exts
import           Unsafe.Coerce

main :: IO ()
main = do
    [h, w] <- map read.words <$> getLine :: IO [Int]
    m <- U.filter (not.isSpace) . U.unfoldrN (h*w+h) C.uncons <$> C.getContents
    print $ solve h w m

convert :: Char -> Int
convert = (inf *) . fromEnum . (/= '#')

inf :: Int
inf = 0x3f3f3f3f

solve :: Int -> Int -> U.Vector Char -> Int
solve h w (U.map convert -> m) = runST $ do
    q <- newQueueM
    U.forM_ (U.findIndices (== 0) m) $ \xy -> do
        enqueueM xy q

    d <- U.unsafeThaw m

    fix $ \loop -> do
        dequeueM q >>= \case
            Just xy -> do
                forNeighborM xy $ \nxny -> do
                    dnxny <- UM.unsafeRead d nxny
                    when (dnxny == inf) $ do
                        UM.unsafeRead d xy >>= UM.unsafeWrite d nxny . (+1)
                        enqueueM nxny q
                loop
            Nothing -> do
                h <- readByteArray (queueInfo q) 0
                readByteArray (queueData q) (h - 1) >>= UM.unsafeRead d

  where
    forNeighborM :: (PrimMonad m) => Int -> (Int -> m ()) -> m ()
    forNeighborM xy f = do
        let y = rem xy w
        when (y > 0) $ f (xy - 1)
        when (y + 1 < w) $ f (xy + 1)
        when (xy >= w) $ f (xy - w)
        when (xy + w < h * w) $ f (xy + w)
    {-# INLINE forNeighborM #-}

-------------------------------------------------------------------------------
data VecQueue m a = VecQueue
    { queueInfo :: !(MutableByteArray m)
    , queueData :: !(MutableByteArray m)
    }

newQueueM :: (PrimMonad m, P.Prim a) => m (VecQueue (PrimState m) a)
newQueueM = do
    info <- newByteArray (2 * 8)
    writeByteArray info 0 (0 :: Int)
    writeByteArray info 1 (0 :: Int)
    q <- newByteArray (1024 * 1024 * 8)
    return $ VecQueue info q

dequeueM :: (PrimMonad m, P.Prim a) => VecQueue (PrimState m) a -> m (Maybe a)
dequeueM (VecQueue info q) = do
    h <- readByteArray info 0
    t <- readByteArray info 1
    if h < t
    then do
        writeByteArray info 0 (h + 1 :: Int)
        pure <$> readByteArray q h
    else return Nothing
{-# INLINE dequeueM #-}

enqueueM :: (PrimMonad m, P.Prim a) => a -> VecQueue (PrimState m) a -> m ()
enqueueM x (VecQueue info q) = do
    t <- readByteArray info 1
    writeByteArray q t x
    writeByteArray info 1 (t + 1 :: Int)
{-# INLINE enqueueM #-}

type Parser a = C.ByteString -> Maybe (a, C.ByteString)

parseInt :: Parser Int
parseInt = C.readInt . C.dropWhile isSpace

parseInt2 :: Parser (Int, Int)
parseInt2 = runStateT $
    (,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)

parseInt3 :: Parser (Int, Int, Int)
parseInt3 = runStateT $
    (,,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)

parseInt4 :: Parser (Int, Int, Int, Int)
parseInt4 = runStateT $
    (,,,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)


{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs, PatternGuards,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}
{-# OPTIONS_GHC -O2 #-}

import Data.Bits
import Data.List
import Data.Maybe
import Data.Tuple
import Data.Ord
import Data.Int
import Data.Word
import Data.Char
import Data.Function
import Data.STRef
import Data.IORef
import Data.Monoid
import Data.Functor
import System.IO
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.State.Strict
import Control.Monad.ST
import Control.Monad.ST.Lazy (strictToLazyST, lazyToStrictST)
import qualified Control.Monad.ST.Lazy as STL
-- import Control.Monad.ST.Safe
import Control.DeepSeq
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.ByteString.Builder as BSB
import Data.IntMap (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Attoparsec.ByteString.Char8 as Atto
import qualified Data.Primitive as Pr

main :: IO ()
main = do
  [h,w] <- map readInt . words <$> getLine
  mas <- VUM.replicate ((h+2)*(w+2)) False :: IO (VUM.MVector RealWorld Bool)
  forM_ [1..h] $ \ !r ->
    VU.copy (VUM.slice (r*(w+2)+1) w mas)
      =<< VU.map (=='#') . VU.unfoldrN w BS.uncons <$> BS.getLine
  as <- VU.unsafeFreeze mas
  print $ query h w as

query :: Int -> Int -> VU.Vector Bool -> Int
query h w !as = VU.maximum checksheet
  where
    checksheet = VU.create $ do
      chksht <- VUM.replicate ((h+2)*(w+2)) (shiftR maxBound 1 :: Int)
      VU.forM_ (VU.enumFromStepN (w+3) (w+2) h) $ \ !p ->
        VU.forM_ (VU.enumFromN p w) $ \ !p ->
        if as VU.! p
          then VUM.write chksht p 0
          else VUM.write chksht p . (+1)
               =<< liftA2 min (VUM.read chksht (p-1))
                              (VUM.read chksht (p-(w+2)))
      VU.forM_ (VU.enumFromStepN ((h+1)*(w+2)-2) (-(w+2)) h) $ \ !p ->
        VU.forM_ (VU.enumFromStepN p (-1) w) $ \ !p ->
        VUM.write chksht p
        =<< liftA2 min
             (VUM.read chksht p)
             ((+1) <$> liftA2 min (VUM.read chksht (p+1))
                                  (VUM.read chksht (p+w+2)))
      VUM.set (VUM.take (w+2) chksht) 0
      VUM.set (VUM.slice ((h+1)*(w+2)) (w+2) chksht) 0
      VU.forM_ (VU.enumFromStepN (w+2) (w+2) h) $ \ !p -> do
        VUM.write chksht p       0
        VUM.write chksht (p+w+1) 0
      return chksht

#define IL(f) {-# INLINE f #-}; f

rInt :: StateT BSL.ByteString Maybe Int
IL(rInt) = StateT $ BSL.readInt . BSL.dropWhile (<'!')
rIntS :: StateT BS.ByteString Maybe Int
IL(rIntS) = StateT $ BS.readInt . BS.dropWhile (<'!')

-- unlessM, whenM :: (Monad m) => m Bool -> m () -> m ()
IL(whenM) = (. flip when) . (>>=)
IL(unlessM) = (. flip unless) . (>>=)

IL(wrA) = A.writeArray
IL(rdA) = A.readArray
IL(mdA) = \arr f !i -> do
  ai <- rdA arr i
  let fai = f ai
  wrA arr i fai
  return (ai,fai)
{-# INLINE mdA' #-}
mdA' = \arr f !i -> do
  !ai <- rdA arr i
  let !fai = f ai
  wrA arr i fai
  return (ai,fai)
IL(swapA) = \arr !i !j -> do
  ai <- rdA arr i
  wrA arr i =<< rdA arr j
  wrA arr j ai

#define D(f,r,d)\
  IL(f) :: Integral a=>a->d; f=fromIntegral;\
  IL(r) :: String->d; r=read
#define C(f,r,g,h,d) D(f,r,d);\
  g,h :: RealFrac a=>a->d; IL(g)=floor; IL(h)=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,h,a,m)\
  IL(f) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e);\
  f=A.newArray;\
  IL(g) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e);\
  g=A.newArray_;\
  IL(h) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> [e] -> m (a i e);\
  h=A.newListArray
#define C(a,m)
N(newIOA,newIOA_,newIOAL,IOArray,IO)
N(newSTA,newSTA_,newSTAL,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,newIOUAL,IOUArray,IO)
N(newSTUA,newSTUA_,newSTUAL,STUArray s,ST s)
#undef C
#undef N

#undef IL

Global OOD problem IDs are disjoint from train, validation, and in-distribution test problem IDs.

Score : 300 points

Problem Statement

You are given a grid of squares with H horizontal rows and W vertical columns, where each square is painted white or black.
HW characters from A_{11} to A_{HW} represent the colors of the squares.
A_{ij} is # if the square at the i-th row from the top and the j-th column from the left is black, and A_{ij} is . if that square is white.

We will repeatedly perform the following operation until all the squares are black:

Every white square that shares a side with a black square, becomes black.

Find the number of operations that will be performed.
The initial grid has at least one black square.

Constraints

1 \leq H,W \leq 1000

A_{ij} is # or ..

The given grid has at least one black square.

Input

Input is given from Standard Input in the following format:

H W
A_{11}A_{12}...A_{1W}
:
A_{H1}A_{H2}...A_{HW}

Output

Print the number of operations that will be performed.

Sample Input 1

3 3
...
.#.
...

Sample Output 1

2

After one operation, all but the corners of the grid will be black. After one more operation, all the squares will be black.

Sample Input 2

6 6
..#..#
......
#..#..
......
.#....
....#.

Sample Output 2

3

Submitted source-code file size, in bytes.

Execution CPU time reported by official Project CodeNet metadata, in milliseconds.

Peak memory usage reported by official Project CodeNet metadata, in kilobytes.


{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs, PatternGuards,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}
{-# OPTIONS_GHC -O2 #-}

import Data.Bits
import Data.List
import Data.Maybe
import Data.Tuple
import Data.Ord
import Data.Int
import Data.Word
import Data.Char
import Data.Function
import Data.STRef
import Data.IORef
import Data.Monoid
import Data.Functor
import System.IO
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.State.Strict
import Control.Monad.ST
import Control.Monad.ST.Lazy (strictToLazyST, lazyToStrictST)
import qualified Control.Monad.ST.Lazy as STL
-- import Control.Monad.ST.Safe
import Control.DeepSeq
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.ByteString.Builder as BSB
import Data.IntMap (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Attoparsec.ByteString.Char8 as Atto
import qualified Data.Primitive as Pr

main :: IO ()
main = do
  [h,w] <- map readInt . words <$> getLine
  mas <- VUM.replicate ((h+2)*(w+2)) False :: IO (VUM.MVector RealWorld Bool)
  forM_ [1..h] $ \ !r ->
    VU.copy (VUM.slice (r*(w+2)+1) w mas)
      =<< VU.map (=='#') . VU.unfoldrN w BS.uncons <$> BS.getLine
  as <- VU.unsafeFreeze mas
  print $ query h w as

query :: Int -> Int -> VU.Vector Bool -> Int
query h w !as = VU.maximum checksheet
  where
    checksheet = VU.create $ do
      chksht <- VUM.replicate ((h+2)*(w+2)) (shiftR maxBound 1 :: Int)
      forM_ [1*(w+2),2*(w+2)..h*(w+2)] $ \ !p -> forM_ [p+1..p+w] $ \ !p ->
        if as VU.! p
          then VUM.write chksht p 0
          else VUM.write chksht p . (+1)
               =<< liftA2 min (VUM.read chksht (p-1))
                              (VUM.read chksht (p-(w+2)))
      forM_ [h*(w+2),(h-1)*(w+2)..1*(w+2)]
        $ \ !p -> forM_ [p+w,p+w-1..p+1] $ \ !p ->
        VUM.write chksht p
        =<< liftA2 min
             (VUM.read chksht p)
             ((+1) <$> liftA2 min (VUM.read chksht (p+1))
                                  (VUM.read chksht (p+w+2)))
      VUM.set (VUM.take (w+2) chksht) 0
      VUM.set (VUM.slice ((h+1)*(w+2)) (w+2) chksht) 0
      forM_ [1*(w+2),2*(w+2)..h*(w+2)] $ \ !p -> do
        VUM.write chksht p       0
        VUM.write chksht (p+w+1) 0
      return chksht

#define IL(f) {-# INLINE f #-}; f

rInt :: StateT BSL.ByteString Maybe Int
IL(rInt) = StateT $ BSL.readInt . BSL.dropWhile (<'!')
rIntS :: StateT BS.ByteString Maybe Int
IL(rIntS) = StateT $ BS.readInt . BS.dropWhile (<'!')

-- unlessM, whenM :: (Monad m) => m Bool -> m () -> m ()
IL(whenM) = (. flip when) . (>>=)
IL(unlessM) = (. flip unless) . (>>=)

IL(wrA) = A.writeArray
IL(rdA) = A.readArray
IL(mdA) = \arr f !i -> do
  ai <- rdA arr i
  let fai = f ai
  wrA arr i fai
  return (ai,fai)
{-# INLINE mdA' #-}
mdA' = \arr f !i -> do
  !ai <- rdA arr i
  let !fai = f ai
  wrA arr i fai
  return (ai,fai)
IL(swapA) = \arr !i !j -> do
  ai <- rdA arr i
  wrA arr i =<< rdA arr j
  wrA arr j ai

#define D(f,r,d)\
  IL(f) :: Integral a=>a->d; f=fromIntegral;\
  IL(r) :: String->d; r=read
#define C(f,r,g,h,d) D(f,r,d);\
  g,h :: RealFrac a=>a->d; IL(g)=floor; IL(h)=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,h,a,m)\
  IL(f) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e);\
  f=A.newArray;\
  IL(g) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e);\
  g=A.newArray_;\
  IL(h) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> [e] -> m (a i e);\
  h=A.newListArray
#define C(a,m)
N(newIOA,newIOA_,newIOAL,IOArray,IO)
N(newSTA,newSTA_,newSTAL,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,newIOUAL,IOUArray,IO)
N(newSTUA,newSTUA_,newSTUAL,STUArray s,ST s)
#undef C
#undef N

#undef IL


{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs, PatternGuards,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}

import Data.Bits
import Data.List
import Data.Maybe
import Data.Tuple
import Data.Ord
import Data.Int
import Data.Word
import Data.Char
import Data.Function
import Data.STRef
import Data.IORef
import Data.Monoid
import Data.Functor
import System.IO
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.State.Strict
import Control.Monad.ST
import Control.Monad.ST.Lazy (strictToLazyST, lazyToStrictST)
import qualified Control.Monad.ST.Lazy as STL
-- import Control.Monad.ST.Safe
import Control.DeepSeq
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.ByteString.Builder as BSB
import Data.IntMap (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Attoparsec.ByteString.Char8 as Atto
import qualified Data.Primitive as Pr

main :: IO ()
main = do
  [h,w] <- map readInt . words <$> getLine
  mas <- VUM.replicate ((h+2)*(w+2)) False :: IO (VUM.MVector RealWorld Bool)
  forM_ [1..h] $ \ !r ->
    VU.copy (VUM.slice (r*(w+2)+1) w mas)
      =<< VU.map (=='#') . VU.unfoldrN w BS.uncons <$> BS.getLine
  as <- VU.unsafeFreeze mas
  print $ query h w as

query :: Int -> Int -> VU.Vector Bool -> Int
query h w !as = VU.maximum checksheet
  where
    checksheet = VU.create $ do
      chksht <- VUM.replicate ((h+2)*(w+2)) (shiftR maxBound 1 :: Int)
      forM_ [1*(w+2),2*(w+2)..h*(w+2)] $ \ !p -> forM_ [p+1..p+w] $ \ !p ->
        if as VU.! p
          then VUM.write chksht p 0
          else VUM.write chksht p . (+1)
               =<< liftA2 min (VUM.read chksht (p-1))
                              (VUM.read chksht (p-(w+2)))
      forM_ [h*(w+2),(h-1)*(w+2)..1*(w+2)]
        $ \ !p -> forM_ [p+w,p+w-1..p+1] $ \ !p ->
        VUM.write chksht p
        =<< liftA2 min
             (VUM.read chksht p)
             ((+1) <$> liftA2 min (VUM.read chksht (p+1))
                                  (VUM.read chksht (p+w+2)))
      VUM.set (VUM.take (w+2) chksht) 0
      VUM.set (VUM.slice ((h+1)*(w+2)) (w+2) chksht) 0
      forM_ [1*(w+2),2*(w+2)..h*(w+2)] $ \ !p -> do
        VUM.write chksht p       0
        VUM.write chksht (p+w+1) 0
      return chksht

#define IL(f) {-# INLINE f #-}; f

rInt :: StateT BSL.ByteString Maybe Int
IL(rInt) = StateT $ BSL.readInt . BSL.dropWhile (<'!')
rIntS :: StateT BS.ByteString Maybe Int
IL(rIntS) = StateT $ BS.readInt . BS.dropWhile (<'!')

-- unlessM, whenM :: (Monad m) => m Bool -> m () -> m ()
IL(whenM) = (. flip when) . (>>=)
IL(unlessM) = (. flip unless) . (>>=)

IL(wrA) = A.writeArray
IL(rdA) = A.readArray
IL(mdA) = \arr f !i -> do
  ai <- rdA arr i
  let fai = f ai
  wrA arr i fai
  return (ai,fai)
{-# INLINE mdA' #-}
mdA' = \arr f !i -> do
  !ai <- rdA arr i
  let !fai = f ai
  wrA arr i fai
  return (ai,fai)
IL(swapA) = \arr !i !j -> do
  ai <- rdA arr i
  wrA arr i =<< rdA arr j
  wrA arr j ai

#define D(f,r,d)\
  IL(f) :: Integral a=>a->d; f=fromIntegral;\
  IL(r) :: String->d; r=read
#define C(f,r,g,h,d) D(f,r,d);\
  g,h :: RealFrac a=>a->d; IL(g)=floor; IL(h)=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,h,a,m)\
  IL(f) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e);\
  f=A.newArray;\
  IL(g) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e);\
  g=A.newArray_;\
  IL(h) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> [e] -> m (a i e);\
  h=A.newListArray
#define C(a,m)
N(newIOA,newIOA_,newIOAL,IOArray,IO)
N(newSTA,newSTA_,newSTAL,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,newIOUAL,IOUArray,IO)
N(newSTUA,newSTUA_,newSTUAL,STUArray s,ST s)
#undef C
#undef N

#undef IL


{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs, PatternGuards,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}

import Data.Bits
import Data.List
import Data.Maybe
import Data.Tuple
import Data.Ord
import Data.Int
import Data.Word
import Data.Char
import Data.Function
import Data.STRef
import Data.IORef
import Data.Monoid
import Data.Functor
import System.IO
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.State.Strict
import Control.Monad.ST
import Control.Monad.ST.Lazy (strictToLazyST, lazyToStrictST)
import qualified Control.Monad.ST.Lazy as STL
-- import Control.Monad.ST.Safe
import Control.DeepSeq
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.ByteString.Builder as BSB
import Data.IntMap (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Attoparsec.ByteString.Char8 as Atto
import qualified Data.Primitive as Pr

main :: IO ()
main = do
  [h,w] <- map readInt . words <$> getLine
  as <- VU.map (=='#') . VU.take (h*w) . VU.filter (>='!') .
    VU.unfoldr BSL.uncons <$> BSL.getContents
  print $ query h w as

query :: Int -> Int -> VU.Vector Bool -> Int
query h w !as = runST $ do
  !queue <- initQueue (h*w)
  forM_ [0..h-1] $ \ !r ->
    forM_ [0..w-1] $ \ !c ->
      when (as VU.! (r*w+c)) $ putQueue queue (r,c,0)
  mas <- VU.unsafeThaw as
  let loop (!r,!c,!d) = do
        forM_ [rc | (b,rc) <- [(r>0,   (r-1, c)),
                               (r<h-1, (r+1, c)),
                               (c>0,   (r, c-1)),
                               (c<w-1, (r, c+1))], b]
          $ \(r1,c1) -> unlessM (VUM.read mas (r1*w+c1)) $ do
          VUM.write mas (r1*w+c1) True
          putQueue queue (r1,c1,d+1)
        maybe (return d) loop =<< takeQueue queue
  maybe (return $! -1) loop =<< takeQueue queue

type QueueEntry = (Int,Int,Int)

data Queue s = Queue {-# UNPACK #-} !(Pr.MutableByteArray s)
               {-# UNPACK #-} !(VUM.MVector s QueueEntry)

{-# INLINE initQueue #-}
initQueue :: Int -> ST s (Queue s)
initQueue len = do
  startEnd <- Pr.newByteArray (2 * Pr.sizeOf (0::Int))
  Pr.setByteArray startEnd 0 2 (0::Int)
  place <- VUM.new len
  return $! (Queue startEnd place)

{-# INLINE putQueue #-}
putQueue :: Queue s -> QueueEntry -> ST s ()
putQueue (Queue startEnd place) val = do
  end <- Pr.readByteArray startEnd 1
--  unsafeIOToPrim $ putStrLn $ "putQueue " ++ show val ++ " with end:"
--                               ++ show end
  if end >= VUM.length place then error "putQueue: capacity full" else do
  Pr.writeByteArray startEnd 1 $! end+1
  VUM.unsafeWrite place end val

{-# INLINE takeQueue #-}
takeQueue :: Queue s -> ST s (Maybe QueueEntry)
takeQueue (Queue startEnd place) = do
  start <- Pr.readByteArray startEnd 0
  end <- Pr.readByteArray startEnd 1
--  unsafeIOToPrim $ putStrLn $ "takeQueue start:" ++ show start ++ " end:"
--    ++ show end
  if start >= end then return Nothing else do
  Pr.writeByteArray startEnd 0 $! start+1
  Just <$> VUM.unsafeRead place start

#define IL(f) {-# INLINE f #-}; f

rInt :: StateT BSL.ByteString Maybe Int
IL(rInt) = StateT $ BSL.readInt . BSL.dropWhile (<'!')
rIntS :: StateT BS.ByteString Maybe Int
IL(rIntS) = StateT $ BS.readInt . BS.dropWhile (<'!')

-- unlessM, whenM :: (Monad m) => m Bool -> m () -> m ()
IL(whenM) = (. flip when) . (>>=)
IL(unlessM) = (. flip unless) . (>>=)

IL(wrA) = A.writeArray
IL(rdA) = A.readArray
IL(mdA) = \arr f !i -> do
  ai <- rdA arr i
  let fai = f ai
  wrA arr i fai
  return (ai,fai)
{-# INLINE mdA' #-}
mdA' = \arr f !i -> do
  !ai <- rdA arr i
  let !fai = f ai
  wrA arr i fai
  return (ai,fai)
IL(swapA) = \arr !i !j -> do
  ai <- rdA arr i
  wrA arr i =<< rdA arr j
  wrA arr j ai

#define D(f,r,d)\
  IL(f) :: Integral a=>a->d; f=fromIntegral;\
  IL(r) :: String->d; r=read
#define C(f,r,g,h,d) D(f,r,d);\
  g,h :: RealFrac a=>a->d; IL(g)=floor; IL(h)=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,h,a,m)\
  IL(f) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e);\
  f=A.newArray;\
  IL(g) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e);\
  g=A.newArray_;\
  IL(h) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> [e] -> m (a i e);\
  h=A.newListArray
#define C(a,m)
N(newIOA,newIOA_,newIOAL,IOArray,IO)
N(newSTA,newSTA_,newSTAL,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,newIOUAL,IOUArray,IO)
N(newSTUA,newSTUA_,newSTUAL,STUArray s,ST s)
#undef C
#undef N

#undef IL


{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE BangPatterns          #-}
{-# LANGUAGE CPP                   #-}
{-# LANGUAGE LambdaCase            #-}
{-# LANGUAGE MagicHash             #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MultiWayIf            #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TupleSections         #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE ViewPatterns          #-}

import           Control.Applicative
import           Control.Exception
import           Control.Monad
import           Control.Monad.Primitive
import           Control.Monad.ST
import           Control.Monad.State.Strict
import           Data.Bool
import qualified Data.ByteString             as B
import qualified Data.ByteString.Char8       as C
import qualified Data.ByteString.Unsafe      as B
import           Data.Char
import qualified Data.Foldable               as F
import           Data.Function
import qualified Data.IntMap.Strict          as IM
import qualified Data.IntSet                 as IS
import qualified Data.List                   as L
import qualified Data.Map.Strict             as M
import           Data.Monoid
import           Data.Ord
import           Data.Primitive.MutVar
import qualified Data.Set                    as S
import           Data.Tuple
import qualified Data.Vector                 as V
import qualified Data.Vector.Generic         as G
import qualified Data.Vector.Generic.Mutable as GM
import qualified Data.Vector.Unboxed         as U
import qualified Data.Vector.Unboxed.Mutable as UM
import           Debug.Trace
import           Foreign                     hiding (void)
import           GHC.Exts
import           Unsafe.Coerce

main :: IO ()
main = do
    [h, w] <- map read.words <$> getLine :: IO [Int]
    m <- U.filter (not.isSpace) . U.unfoldrN (h*w+h) C.uncons <$> C.getContents
    print $ solve h w m

convert :: Char -> Int
convert = (inf *) . fromEnum . (/= '#')

inf :: Int
inf = 0x3f3f3f3f

solve :: Int -> Int -> U.Vector Char -> Int
solve h w (U.map convert -> m) = U.maximum dist
  where
    ix x y = x * w + y
    unIx xy = quotRem xy w

    forNeighborM :: (PrimMonad m) => Int -> (Int -> m ()) -> m ()
    forNeighborM xy f = do
        let y = rem xy w
        when (y > 0) $ f (xy - 1)
        when (y + 1 < w) $ f (xy + 1)
        when (xy >= w) $ f (xy - w)
        when (xy + w < h * w) $ f (xy + w)
    {-# INLINE forNeighborM #-}

    dist = U.create $ do
        q <- newQueueM
        U.forM_ (U.findIndices (== 0) m) $ \xy -> do
            enqueueM xy q

        d <- U.unsafeThaw m

        fix $ \loop -> do
            dequeueM q >>= \case
                Nothing -> return ()
                Just xy -> do
                    dxy <- UM.unsafeRead d xy
                    forNeighborM xy $ \nxny -> do
                        dnxny <- UM.unsafeRead d nxny
                        when (dnxny > dxy + 1) $ do
                            UM.unsafeWrite d nxny (dxy + 1)
                            enqueueM nxny q
                    loop
        return d

-------------------------------------------------------------------------------
data VecQueue m a = VecQueue
    { queueInfo :: !(UM.MVector m Int)
    , queueData :: !(UM.MVector m a)
    }

newQueueM :: (PrimMonad m, U.Unbox a) => m (VecQueue (PrimState m) a)
newQueueM = do
    info <- UM.replicate 2 0
    q <- UM.unsafeNew (1024 * 1024)
    return $ VecQueue info q

dequeueM :: (PrimMonad m, U.Unbox a) => VecQueue (PrimState m) a -> m (Maybe a)
dequeueM (VecQueue info q) = do
    l <- UM.unsafeRead info 1
    if l > 0
    then do
        UM.unsafeWrite info 1 (l - 1)
        h <- UM.unsafeRead info 0
        UM.unsafeWrite info 0 (h + 1)
        pure <$!> UM.unsafeRead q h
    else return Nothing
{-# INLINE dequeueM #-}

enqueueM :: (PrimMonad m, U.Unbox a) => a -> VecQueue (PrimState m) a -> m ()
enqueueM x (VecQueue info q) = do
    h <- UM.unsafeRead info 0
    l <- UM.unsafeRead info 1
    UM.unsafeWrite q (h + l) x
    UM.unsafeWrite info 1 (l + 1)
{-# INLINE enqueueM #-}

type Parser a = C.ByteString -> Maybe (a, C.ByteString)

parseInt :: Parser Int
parseInt = C.readInt . C.dropWhile isSpace

parseInt2 :: Parser (Int, Int)
parseInt2 = runStateT $
    (,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)

parseInt3 :: Parser (Int, Int, Int)
parseInt3 = runStateT $
    (,,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)

parseInt4 :: Parser (Int, Int, Int, Int)
parseInt4 = runStateT $
    (,,,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)


{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE BangPatterns          #-}
{-# LANGUAGE CPP                   #-}
{-# LANGUAGE LambdaCase            #-}
{-# LANGUAGE MagicHash             #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE MultiWayIf            #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE TupleSections         #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE ViewPatterns          #-}

import           Control.Applicative
import           Control.Exception
import           Control.Monad
import           Control.Monad.Primitive
import           Control.Monad.ST
import           Control.Monad.State.Strict
import           Data.Bool
import qualified Data.ByteString             as B
import qualified Data.ByteString.Char8       as C
import qualified Data.ByteString.Unsafe      as B
import           Data.Char
import qualified Data.Foldable               as F
import           Data.Function
import qualified Data.IntMap.Strict          as IM
import qualified Data.IntSet                 as IS
import qualified Data.List                   as L
import qualified Data.Map.Strict             as M
import           Data.Monoid
import           Data.Ord
import           Data.Primitive.MutVar
import qualified Data.Set                    as S
import           Data.Tuple
import qualified Data.Vector                 as V
import qualified Data.Vector.Generic         as G
import qualified Data.Vector.Generic.Mutable as GM
import qualified Data.Vector.Unboxed         as U
import qualified Data.Vector.Unboxed.Mutable as UM
import           Debug.Trace
import           Foreign                     hiding (void)
import           GHC.Exts
import           Unsafe.Coerce

main :: IO ()
main = do
    [h, w] <- map read.words <$> getLine :: IO [Int]
    m <- U.filter (not.isSpace) . U.unfoldrN (h*w+h) C.uncons <$> C.getContents
    print $ solve h w m

convert :: Char -> Int
convert = (inf *) . fromEnum . (/= '#')

inf :: Int
inf = 0x3f3f3f3f

solve :: Int -> Int -> U.Vector Char -> Int
solve h w (U.map convert -> m) = U.maximum dist
  where
    ix x y = x * w + y
    unIx xy = quotRem xy w
    inGrid x y = 0<=x && x<h && 0<=y && y<w
    neighbor xy = [ix nx ny|(nx,ny)<-[(x+1,y),(x-1,y),(x,y+1),(x,y-1)], inGrid nx ny]
      where
        (x, y) = unIx xy
    dist = U.create $ do
        q <- newQueueM
        U.forM_ (U.findIndices (== 0) m) $ \xy -> do
            enqueueM xy q

        d <- U.unsafeThaw m

        fix $ \loop -> do
            dequeueM q >>= \case
                Nothing -> return ()
                Just xy -> do
                    dxy <- UM.unsafeRead d xy
                    forM_ (neighbor xy) $ \nxny -> do
                        dnxny <- UM.unsafeRead d nxny
                        when (dnxny > dxy + 1) $ do
                            UM.unsafeWrite d nxny (dxy + 1)
                            enqueueM nxny q
                    loop
        return d

-------------------------------------------------------------------------------
data VecQueue m a = VecQueue
    { queueInfo :: !(UM.MVector m Int)
    , queueData :: !(UM.MVector m a)
    }

newQueueM :: (PrimMonad m, U.Unbox a) => m (VecQueue (PrimState m) a)
newQueueM = do
    info <- UM.replicate 2 0
    q <- UM.unsafeNew (1024 * 1024)
    return $ VecQueue info q

dequeueM :: (PrimMonad m, U.Unbox a) => VecQueue (PrimState m) a -> m (Maybe a)
dequeueM (VecQueue info q) = do
    l <- UM.unsafeRead info 1
    if l > 0
    then do
        UM.unsafeWrite info 1 (l - 1)
        h <- UM.unsafeRead info 0
        UM.unsafeWrite info 0 (h + 1)
        pure <$> UM.unsafeRead q h
    else return Nothing
{-# INLINE dequeueM #-}

enqueueM :: (PrimMonad m, U.Unbox a) => a -> VecQueue (PrimState m) a -> m ()
enqueueM x (VecQueue info q) = do
    h <- UM.unsafeRead info 0
    l <- UM.unsafeRead info 1
    UM.unsafeWrite q (h + l) x
    UM.unsafeWrite info 1 (l + 1)
{-# INLINE enqueueM #-}

type Parser a = C.ByteString -> Maybe (a, C.ByteString)

parseInt :: Parser Int
parseInt = C.readInt . C.dropWhile isSpace

parseInt2 :: Parser (Int, Int)
parseInt2 = runStateT $
    (,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)

parseInt3 :: Parser (Int, Int, Int)
parseInt3 = runStateT $
    (,,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)

parseInt4 :: Parser (Int, Int, Int, Int)
parseInt4 = runStateT $
    (,,,) <$> StateT (C.readInt . C.dropWhile isSpace)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)
        <*> StateT (C.readInt . B.unsafeTail)


-- AGC033 A problem
import Control.Monad

-- conversion from String to Int
toInt :: String -> Int
toInt x = read x :: Int

-- obtain [Int] from I/O
getInts :: IO [Int]
getInts = do
  x <- getLine
  let y = (map $ toInt) $ words x
  return y

-- mapping
sw :: Char -> Int
sw '.' = 1
sw '#' = 0

rowmap :: [Char] -> [Int]
rowmap [] = []
rowmap (x:xs) = [(sw x)] ++ (rowmap xs)

brdmap :: [[Char]] -> [[Int]]
brdmap [] = []
brdmap (x:xs) = [(rowmap x)] ++ (brdmap xs)

transpose :: [[a]] -> [[a]]
transpose ([]:_) = []
transpose xs = map head xs : transpose (map tail xs)

pilerow :: [Int] -> [Int] -> [Int]
pilerow [] [] = []
pilerow (x:xs) (y:ys) = [x*y] ++ (pilerow xs ys)

pilebrd :: [[Int]] -> [[Int]] -> [[Int]]
pilebrd [] [] = []
pilebrd (x:xs) (y:ys) = [(pilerow x y)] ++ (pilebrd xs ys)

dotrow :: Int -> [Int]
dotrow 0 = []
dotrow n = [1] ++ (dotrow (n-1))

shiftU :: [[Int]] -> Int -> [[Int]]
shiftU x n = (tail x) ++ [(dotrow n)]

shiftD :: [[Int]] -> Int -> [[Int]]
shiftD x n  = [(dotrow n)] ++ (init x)

shiftL :: [[Int]] -> Int -> [[Int]]
shiftL x n = transpose $ shiftU (transpose x) n

shiftR :: [[Int]] -> Int -> [[Int]]
shiftR x n = transpose $ shiftD (transpose x) n

turnbrd :: [[Int]] -> Int -> Int -> [[Int]]
turnbrd brd h w =
    pilebrd brd (pilebrd (shiftU brd w) (pilebrd (shiftD brd w) (pilebrd (shiftL brd h) (shiftR brd h))))

checkrow :: [Int] -> Int
checkrow [] = 0
checkrow (x:xs) = x + (checkrow xs)

checkbrd :: [[Int]] -> Int
checkbrd [] = 0
checkbrd (x:xs) = (checkrow x) + (checkbrd xs)

agc033a :: [[Int]] -> Int -> Int -> Int
agc033a brd h w =
    if checkbrd brd > 0 then 1 + (agc033a (turnbrd brd h w) h w) else 0

-- main function
main :: IO ()
main = do
  hnw <- getInts
  let h = head hnw :: Int
  let w = last hnw :: Int
  rawbrd <- replicateM h getLine
  let brd = brdmap rawbrd
  print (agc033a brd h w)


import Control.Monad
f s b w=map(\x->if fst x=='.' then minimum[let q=abs(snd x-z) in (q`div`w)+(q`mod`w)|z<-b] else 0)s
main=do
 [h,w]<-map read.words<$>getLine
 sr<-replicateM h getLine
 let s=zip (concat sr) [1..h*w]
     b=map snd$filter(\x->if fst x=='#' then True else False)s
 print$maximum$f s b w


import Control.Monad
main=do
 [h,w]<-map read.words<$>getLine
 sr<-replicateM h getLine
 let s=zip (concat sr) [(y,x)|y<-[1..h],x<-[1..w]]
     b=map snd$filter(\x->if fst x=='#' then True else False)s
 print$maximum$map(\x->if fst x=='.' then minimum[abs(x2-snd(snd x))+abs(y2-fst(snd x))|(y2,x2)<-b] else 0)s


{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs, PatternGuards,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}

import Data.Bits
import Data.List
import Data.Maybe
import Data.Tuple
import Data.Ord
import Data.Int
import Data.Word
import Data.Char
import Data.Function
import Data.STRef
import Data.IORef
import Data.Monoid
import Data.Functor
import System.IO
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.State.Strict
import Control.Monad.ST
import Control.Monad.ST.Lazy (strictToLazyST, lazyToStrictST)
import qualified Control.Monad.ST.Lazy as STL
-- import Control.Monad.ST.Safe
import Control.DeepSeq
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.ByteString.Builder as BSB
import Data.IntMap (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Attoparsec.ByteString.Char8 as Atto

main :: IO ()
main = do
  [h,w] <- map readInt . words <$> getLine
  as <- A.listArray ((1,1),(h,w))
    . take (h*w) . map (=='#') . filter (`elem` ".#") <$> getContents
     :: IO (UArray (Int,Int) Bool)
  print $ query h w as

query :: Int -> Int -> UArray (Int,Int) Bool -> Int
query h w as = (\(x,y,d) -> d) $ last $ force queue
  where
    initBlacks = map fst $ filter snd $ A.assocs as
    walk rest !checks _ | rest <= 0 = []
    walk rest !checks ((!x,!y,!d):xs)
      = filter (\(x,y,d) -> IS.notMember (x `shiftL` 11 .|. y) checks)
         neighbors
        ++ walk (rest-1) nextChecks xs
      where
        nextChecks = foldl' (flip IS.insert) checks
          $ map (\(x,y,d) -> x `shiftL` 11 .|. y) neighbors
        neighbors = (if x > 1 then ((x-1,y,d+1):) else id)
          $ (if x < h then ((x+1,y,d+1):) else id)
          $ (if y > 1 then ((x,y-1,d+1):) else id)
          $ (if y < w then ((x,y+1,d+1):) else id)
          $ []
    queue = map (\(x,y) ->(x,y,0)) initBlacks
      ++ walk (h*w)
      (IS.fromList $ map (\(x,y) -> x `shiftL` 11 .|. y) initBlacks) queue

#define IL(f) {-# INLINE f #-}; f

rInt :: StateT BSL.ByteString Maybe Int
IL(rInt) = StateT $ BSL.readInt . BSL.dropWhile (<'!')
rIntS :: StateT BS.ByteString Maybe Int
IL(rIntS) = StateT $ BS.readInt . BS.dropWhile (<'!')

-- unlessM, whenM :: (Monad m) => m Bool -> m () -> m ()
IL(whenM) = (. flip when) . (>>=)
IL(unlessM) = (. flip unless) . (>>=)

IL(wrA) = A.writeArray
IL(rdA) = A.readArray
IL(mdA) = \arr f !i -> do
  ai <- rdA arr i
  let fai = f ai
  wrA arr i fai
  return (ai,fai)
{-# INLINE mdA' #-}
mdA' = \arr f !i -> do
  !ai <- rdA arr i
  let !fai = f ai
  wrA arr i fai
  return (ai,fai)
IL(swapA) = \arr !i !j -> do
  ai <- rdA arr i
  wrA arr i =<< rdA arr j
  wrA arr j ai

#define D(f,r,d)\
  IL(f) :: Integral a=>a->d; f=fromIntegral;\
  IL(r) :: String->d; r=read
#define C(f,r,g,h,d) D(f,r,d);\
  g,h :: RealFrac a=>a->d; IL(g)=floor; IL(h)=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,h,a,m)\
  IL(f) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e);\
  f=A.newArray;\
  IL(g) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e);\
  g=A.newArray_;\
  IL(h) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> [e] -> m (a i e);\
  h=A.newListArray
#define C(a,m)
N(newIOA,newIOA_,newIOAL,IOArray,IO)
N(newSTA,newSTA_,newSTAL,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,newIOUAL,IOUArray,IO)
N(newSTUA,newSTUA_,newSTUAL,STUArray s,ST s)
#undef C
#undef N

#undef IL


{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs, PatternGuards,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}

import Data.Bits
import Data.List
import Data.Maybe
import Data.Tuple
import Data.Ord
import Data.Int
import Data.Word
import Data.Char
import Data.Function
import Data.STRef
import Data.IORef
import Data.Monoid
import Data.Functor
import System.IO
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.State.Strict
import Control.Monad.ST
import Control.Monad.ST.Lazy (strictToLazyST, lazyToStrictST)
import qualified Control.Monad.ST.Lazy as STL
-- import Control.Monad.ST.Safe
import Control.DeepSeq
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.ByteString.Builder as BSB
import Data.IntMap (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Attoparsec.ByteString.Char8 as Atto

main :: IO ()
main = do
  [h,w] <- map readInt . words <$> getLine
  as <- A.listArray ((1,1),(h,w))
    . take (h*w) . map (=='#') . filter (`elem` ".#") <$> getContents
     :: IO (UArray (Int,Int) Bool)
  print $ query h w as

query :: Int -> Int -> UArray (Int,Int) Bool -> Int
query h w as = (\(x,y,d) -> d) $ last queue
  where
    initBlacks = map fst $ filter snd $ A.assocs as
    walk rest checks _ | rest <= 0 = []
    walk rest checks ((!x,!y,!d):xs)
      = filter (\(x,y,d) -> IS.notMember (x `shiftL` 11 .|. y) checks)
         neighbors
        ++ walk (rest-1) nextChecks xs
      where
        nextChecks = foldl' (flip IS.insert) checks
          $ map (\(x,y,d) -> x `shiftL` 11 .|. y) neighbors
        neighbors = (if x > 1 then ((x-1,y,d+1):) else id)
          $ (if x < h then ((x+1,y,d+1):) else id)
          $ (if y > 1 then ((x,y-1,d+1):) else id)
          $ (if y < h then ((x,y+1,d+1):) else id)
          $ []
    queue = map (\(x,y) ->(x,y,0)) initBlacks ++ walk (h*w) IS.empty queue

#define IL(f) {-# INLINE f #-}; f

rInt :: StateT BSL.ByteString Maybe Int
IL(rInt) = StateT $ BSL.readInt . BSL.dropWhile (<'!')
rIntS :: StateT BS.ByteString Maybe Int
IL(rIntS) = StateT $ BS.readInt . BS.dropWhile (<'!')

-- unlessM, whenM :: (Monad m) => m Bool -> m () -> m ()
IL(whenM) = (. flip when) . (>>=)
IL(unlessM) = (. flip unless) . (>>=)

IL(wrA) = A.writeArray
IL(rdA) = A.readArray
IL(mdA) = \arr f !i -> do
  ai <- rdA arr i
  let fai = f ai
  wrA arr i fai
  return (ai,fai)
{-# INLINE mdA' #-}
mdA' = \arr f !i -> do
  !ai <- rdA arr i
  let !fai = f ai
  wrA arr i fai
  return (ai,fai)
IL(swapA) = \arr !i !j -> do
  ai <- rdA arr i
  wrA arr i =<< rdA arr j
  wrA arr j ai

#define D(f,r,d)\
  IL(f) :: Integral a=>a->d; f=fromIntegral;\
  IL(r) :: String->d; r=read
#define C(f,r,g,h,d) D(f,r,d);\
  g,h :: RealFrac a=>a->d; IL(g)=floor; IL(h)=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,h,a,m)\
  IL(f) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e);\
  f=A.newArray;\
  IL(g) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e);\
  g=A.newArray_;\
  IL(h) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> [e] -> m (a i e);\
  h=A.newListArray
#define C(a,m)
N(newIOA,newIOA_,newIOAL,IOArray,IO)
N(newSTA,newSTA_,newSTAL,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,newIOUAL,IOUArray,IO)
N(newSTUA,newSTUA_,newSTUAL,STUArray s,ST s)
#undef C
#undef N

#undef IL


{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs, PatternGuards,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}

import Data.Bits
import Data.List
import Data.Maybe
import Data.Tuple
import Data.Ord
import Data.Int
import Data.Word
import Data.Char
import Data.Function
import Data.STRef
import Data.IORef
import Data.Monoid
import Data.Functor
import System.IO
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.State.Strict
import Control.Monad.ST
import Control.Monad.ST.Lazy (strictToLazyST, lazyToStrictST)
import qualified Control.Monad.ST.Lazy as STL
-- import Control.Monad.ST.Safe
import Control.DeepSeq
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.ByteString.Builder as BSB
import Data.IntMap (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Attoparsec.ByteString.Char8 as Atto

main :: IO ()
main = do
  [h,w] <- map readInt . words <$> getLine
  as <- A.listArray ((1,1),(h,w))
    . take (h*w) . map (=='#') . filter (`elem` ".#") <$> getContents
     :: IO (UArray (Int,Int) Bool)
  print $ query h w as

query :: Int -> Int -> UArray (Int,Int) Bool -> Int
query h w as = undefined
  where
    initBlacks = map fst $ filter snd $ A.assocs as
    walk rest checks _ | rest <= 0 = []
    walk rest checks ((!x,!y,!d):xs)
      = filter (\(x,y,d) -> IS.notMember (x `shiftL` 11 .|. y) checks)
         neighbors
        ++ walk (rest-1) nextChecks xs
      where
        nextChecks = foldl' (flip IS.insert) checks
          $ map (\(x,y,d) -> x `shiftL` 11 .|. y) neighbors
        neighbors = (if x > 1 then ((x-1,y,d+1):) else id)
          $ (if x < h then ((x+1,y,d+1):) else id)
          $ (if y > 1 then ((x,y-1,d+1):) else id)
          $ (if y < h then ((x,y+1,d+1):) else id)
          $ []

#define IL(f) {-# INLINE f #-}; f

rInt :: StateT BSL.ByteString Maybe Int
IL(rInt) = StateT $ BSL.readInt . BSL.dropWhile (<'!')
rIntS :: StateT BS.ByteString Maybe Int
IL(rIntS) = StateT $ BS.readInt . BS.dropWhile (<'!')

-- unlessM, whenM :: (Monad m) => m Bool -> m () -> m ()
IL(whenM) = (. flip when) . (>>=)
IL(unlessM) = (. flip unless) . (>>=)

IL(wrA) = A.writeArray
IL(rdA) = A.readArray
IL(mdA) = \arr f !i -> do
  ai <- rdA arr i
  let fai = f ai
  wrA arr i fai
  return (ai,fai)
{-# INLINE mdA' #-}
mdA' = \arr f !i -> do
  !ai <- rdA arr i
  let !fai = f ai
  wrA arr i fai
  return (ai,fai)
IL(swapA) = \arr !i !j -> do
  ai <- rdA arr i
  wrA arr i =<< rdA arr j
  wrA arr j ai

#define D(f,r,d)\
  IL(f) :: Integral a=>a->d; f=fromIntegral;\
  IL(r) :: String->d; r=read
#define C(f,r,g,h,d) D(f,r,d);\
  g,h :: RealFrac a=>a->d; IL(g)=floor; IL(h)=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,h,a,m)\
  IL(f) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e);\
  f=A.newArray;\
  IL(g) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e);\
  g=A.newArray_;\
  IL(h) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> [e] -> m (a i e);\
  h=A.newListArray
#define C(a,m)
N(newIOA,newIOA_,newIOAL,IOArray,IO)
N(newSTA,newSTA_,newSTAL,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,newIOUAL,IOUArray,IO)
N(newSTUA,newSTUA_,newSTUAL,STUArray s,ST s)
#undef C
#undef N

#undef IL


import Control.Monad
import Data.List

main = do
  [h,w] <- map read . words <$> getLine
  as <- zip [1..] <$> replicateM h (fmap (zip [1..]) getLine)
  print $ paints (getPos as) (h,w) 0

getPos :: [(Int,[(Int,Char)])] -> [(Int,Int)]
getPos [] = []
getPos ((_,[]):zs) = getPos zs
getPos ((x,(y,'#'):ys):zs) = (x,y) : getPos ((x,ys):zs)
getPos ((x,_:ys):zs) = getPos ((x,ys):zs)
getPos (_:zs)              = getPos zs

paint (x,y) = [(x,y),(x+1,y),(x-1,y),(x,y+1),(x,y-1)]

paints as (h,w) acc = if length as == h*w then acc else paints as' (h,w) (acc+1)
  where
    as' = nub . filter p . concat $ map paint as
    p (x,y) = 1 <= x && x <= h && 1 <= y && y <= w


import Control.Monad
f s bx by=map(\x->if fst x=='.' then minimum[abs(x2-fst(snd x))+abs(y2-fst(snd x))|x2<-bx,y2<-by] else 1000)s
main=do
 [h,w]<-map read.words<$>getLine
 sr<-replicateM h getLine
 let s=zip (concat sr) [(x,y)|x<-[1..w],y<-[1..h]]
     b=filter(\x->if fst x=='#' then True else False)s
     bx=map fst$map snd$b
     by=map snd$map snd$b
 print$minimum$f s bx by


{-# LANGUAGE
  ScopedTypeVariables, BangPatterns, TupleSections, ExplicitForAll,
  LambdaCase, MultiWayIf, Unsafe, RecordWildCards, FlexibleContexts, CPP,
  NoMonomorphismRestriction, GADTs, PatternGuards,
  RankNTypes, EmptyDataDecls, EmptyCase, ViewPatterns #-}

import Data.Bits
import Data.List
import Data.Maybe
import Data.Tuple
import Data.Ord
import Data.Int
import Data.Word
import Data.Char
import Data.Function
import Data.STRef
import Data.IORef
import Data.Monoid
import Data.Functor
import System.IO
import Control.Arrow
import Control.Applicative
import Control.Monad
import Control.Monad.Primitive
import Control.Monad.State.Strict
import Control.Monad.ST
import Control.Monad.ST.Lazy (strictToLazyST, lazyToStrictST)
import qualified Control.Monad.ST.Lazy as STL
-- import Control.Monad.ST.Safe
import Control.DeepSeq
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.ByteString.Builder as BSB
import Data.IntMap (IntMap)
import qualified Data.IntMap.Strict as IMS
import qualified Data.IntMap.Lazy as IML
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import qualified Data.Array.IArray as A
import qualified Data.Array.MArray.Safe as A
import qualified Data.Array.MArray as A
import Data.Array (Array)
import Data.Array.Unboxed (UArray)
import Data.Array.IArray (IArray)
import Data.Array.MArray.Safe (MArray)
import Data.Array.IO.Safe (IOArray, IOUArray)
import Data.Array.ST.Safe (STArray, STUArray, runSTArray, runSTUArray)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Primitive.Mutable as VPM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Attoparsec.ByteString.Char8 as Atto

main :: IO ()
main = do
  [h,w] <- map readInt . words <$> getLine
  as <- A.listArray ((1,1),(h,w))
    . take (h*w) . map (=='#') . filter (`elem` ".#") <$> getContents
     :: IO (UArray (Int,Int) Bool)
  print $ query h w as

query :: Int -> Int -> UArray (Int,Int) Bool -> Int
query h w as = runST $ do
  vs <- A.thaw as :: ST s (STUArray s (Int,Int) Bool)
  let initBlack = map ((,0) . fst) $ filter snd $ A.assocs as
  let walk cnt _ | cnt == 0 = return []
      walk cnt (((!x,!y),!t):xs) = do
        let neighbors =
              (if x > 1 then ((x-1,y):) else id)
              $ (if x < h then ((x+1,y):) else id)
              $ (if y > 1 then ((x,y-1):) else id)
              $ (if y < w then ((x,y+1):) else id)
              $ []
        res <- map fst . filter (not . snd)
          <$> forM neighbors
               (\ !xy -> (xy,) . fst <$>
                 strictToLazyST (mdA' vs (const True) xy))
        (map (,t+1) res ++) <$> walk (cnt-1) xs
  res <- lazyToStrictST $ STL.fixST $ (\xs -> (initBlack++) <$> walk (h*w) xs)
  return $ snd $ last res

#define IL(f) {-# INLINE f #-}; f

rInt :: StateT BSL.ByteString Maybe Int
IL(rInt) = StateT $ BSL.readInt . BSL.dropWhile (<'!')
rIntS :: StateT BS.ByteString Maybe Int
IL(rIntS) = StateT $ BS.readInt . BS.dropWhile (<'!')

-- unlessM, whenM :: (Monad m) => m Bool -> m () -> m ()
IL(whenM) = (. flip when) . (>>=)
IL(unlessM) = (. flip unless) . (>>=)

IL(wrA) = A.writeArray
IL(rdA) = A.readArray
IL(mdA) = \arr f !i -> do
  ai <- rdA arr i
  let fai = f ai
  wrA arr i fai
  return (ai,fai)
{-# INLINE mdA' #-}
mdA' = \arr f !i -> do
  !ai <- rdA arr i
  let !fai = f ai
  wrA arr i fai
  return (ai,fai)
IL(swapA) = \arr !i !j -> do
  ai <- rdA arr i
  wrA arr i =<< rdA arr j
  wrA arr j ai

#define D(f,r,d)\
  IL(f) :: Integral a=>a->d; f=fromIntegral;\
  IL(r) :: String->d; r=read
#define C(f,r,g,h,d) D(f,r,d);\
  g,h :: RealFrac a=>a->d; IL(g)=floor; IL(h)=ceiling
C(_toInteger_,readInteger,floorInteger,ceilInteger,Integer)
C(toInt,readInt,floorInt,ceilInt,Int)
C(toI8,readI8,floorI8,ceilI8,Int8)
C(toI16,readI16,floorI16,ceilI16,Int16)
C(toI32,readI32,floorI32,ceilI32,Int32)
C(toI64,readI64,floorI64,ceilI64,Int64)
C(toWord,readWord,floorWord,ceilWord,Word)
C(toW8,readW8,floorW8,ceilW8,Word8)
C(toW16,readW16,floorW16,ceilW16,Word16)
C(toW32,readW32,floorW32,ceilW32,Word32)
C(toW64,readW64,floorW64,ceilW64,Word64)
D(toDouble,readDouble,Double)
D(toFloat,readFloat,Float)
#undef D
#undef C

#define N(f,g,h,a,m)\
  IL(f) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> e -> m (a i e);\
  f=A.newArray;\
  IL(g) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> m (a i e);\
  g=A.newArray_;\
  IL(h) :: forall e i s. (C(a,m)A.Ix i) => (i,i) -> [e] -> m (a i e);\
  h=A.newListArray
#define C(a,m)
N(newIOA,newIOA_,newIOAL,IOArray,IO)
N(newSTA,newSTA_,newSTAL,STArray s,ST s)
#undef C
#define C(a,m) MArray (a) e (m),
N(newIOUA,newIOUA_,newIOUAL,IOUArray,IO)
N(newSTUA,newSTUA_,newSTUAL,STUArray s,ST s)
#undef C
#undef N

#undef IL


import qualified Data.ByteString.Char8 as BS
import Data.Maybe
data SegmentTree m = Leaf m  | Node m (SegmentTree m) (SegmentTree m) Int
    deriving (Eq, Show)

val :: SegmentTree m -> m
val (Leaf v)     = v
val (Node v _ _ _) = v

update :: (Monoid m) => SegmentTree m  -> Int -> m -> SegmentTree m
update (Leaf v) _ x = Leaf x
update (Node v l r size)  i x
    | i < n'   =   Node (val left `mappend` val r) left r size
    | otherwise =   Node (val l `mappend` val right) l right size
    where n' = size `div` 2
          left = update l  i x
          right = update r (i-n') x

query :: (Monoid m) => SegmentTree m -> Int -> Int -> m

query (Leaf v) 0 1 = v
query (Node v l r size) a b
    | a >= b    = mempty
    | a == 0 && b == size   = v
    | b <= n'             = query l  a b
    | a >= n'                = query r  (a-n') (b-n')
    | otherwise             = query l  a n' `mappend` query r 0 (b-n')
    where n' = size `div` 2

resize :: Int -> Int -> Int
resize n m
    | m < n = resize n (2*m)
    | otherwise  = m

fromList :: Monoid m => [m] -> SegmentTree m
fromList xs =
    let n = length xs
        m = resize n 1
        plus = replicate (m-n) mempty
        xs' = xs ++ plus
    in fromList' xs' m

fromList' ::Monoid m => [m] -> Int ->SegmentTree m
fromList' _ 0 = Leaf mempty
fromList' [x] 1 = Leaf x
fromList' xs n = Node (val left `mappend` val right) left right n
    where n' = n `div` 2
          (xs1,xs2) = splitAt n' xs
          left = fromList'  xs1 n'
          right = fromList' xs2 (n-n')

get :: Monoid m => SegmentTree m -> Int -> m
get tree i= query tree i (i+1)

newtype Gcd = Gcd Int deriving (Eq,Ord,Read)

instance Show Gcd where
  show (Gcd x) = show x
instance Semigroup Gcd where
  Gcd x <> Gcd y = Gcd (gcd x y)

instance Monoid Gcd where
  mempty = Gcd 0

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine

main = do
  n <- read <$> getLine
  a <- map Gcd <$> getIntList
  let seg = fromList a
  print $ maximum $ [query seg 0 i <> query seg (i+1) n | i <- [0..n]]

Score : 300 points

Problem Statement

There are N integers, A_1, A_2, ..., A_N, written on the blackboard.

You will choose one of them and replace it with an integer of your choice between 1 and 10^9 (inclusive), possibly the same as the integer originally written.

Find the maximum possible greatest common divisor of the N integers on the blackboard after your move.

Constraints

All values in input are integers.

2 \leq N \leq 10^5

1 \leq A_i \leq 10^9

Output

Input is given from Standard Input in the following format:

N
A_1 A_2 ... A_N

Output

Print the maximum possible greatest common divisor of the N integers on the blackboard after your move.

Sample Input 1

3
7 6 8

Sample Output 1

2

If we replace 7 with 4, the greatest common divisor of the three integers on the blackboard will be 2, which is the maximum possible value.

Sample Input 2

3
12 15 18

Sample Output 2

6

Sample Input 3

2
1000000000 1000000000

Sample Output 3

1000000000

We can replace an integer with itself.


module Main where
import           Control.Monad
import           Data.Bits
import Data.Maybe
import qualified Data.ByteString.Char8 as BS
import Data.Monoid
data SegmentTree m = Empty | SegmentTree {node :: m,left :: SegmentTree m,right :: SegmentTree m} deriving (Show)

build :: Monoid m => Int -> SegmentTree m
build 0    = Empty
build 1    = SegmentTree mempty Empty Empty
build size = SegmentTree mempty (build newSize) (build newSize)
    where newSize = (size + 1) `div` 2

depth :: SegmentTree m -> Int
depth Empty = 0
depth tree  = (depth $ left tree) + 1

update :: Monoid m => SegmentTree m -> m -> Int -> SegmentTree m
update tree@(SegmentTree _ Empty Empty) _ _ = tree
update tree@(SegmentTree n l r) value idx =
    update' tree value idx (2 ^ (depth tree - 1))

update' :: Monoid m => SegmentTree m -> m -> Int -> Int -> SegmentTree m
update' tree@(SegmentTree n l r) value idx size
    | size == 1
    = SegmentTree value Empty Empty
    | idx <= newSize
    = let newNode = node (update' l value idx newSize) `mappend` node r
      in  SegmentTree newNode (update' l value idx newSize) r
    | otherwise
    = let newNode = node l
              `mappend` node (update' r value (idx - newSize) newSize)
      in  SegmentTree newNode l (update' r value (idx - newSize) newSize)
    where newSize = size `div` 2

query :: Monoid m => SegmentTree m -> Int -> Int -> m --[a,b)に対しての演算の結果
query tree = query' tree size where size = 2 ^ (depth tree-1)

query' :: Monoid m => SegmentTree m -> Int -> Int -> Int -> m

query' tree@(SegmentTree n l r) size a b
    | a == b    = mempty
    | a == 0 && b == size  =   n
    | b <= newSize   =   query' l newSize a b
    | a >= newSize  =   query' r newSize (a-newSize) (b-newSize)
    | otherwise     =   (query' l newSize a newSize) `mappend` (query' r newSize 0 (b-newSize+1))
    where newSize = size `div` 2

get :: Monoid m => SegmentTree m -> Int -> m
get tree idx = query tree idx (idx + 1)

initial :: Monoid m => [m] -> SegmentTree m
initial list = init' list 1

init' :: Monoid m => [m] -> Int -> SegmentTree m
init' []       idx = build (idx - 1)
init' (m : ms) idx = update (init' ms (idx + 1)) m idx

newtype Gcd = Gcd Integer deriving (Show,Eq,Ord,Read)

instance Monoid Gcd where
    mempty = Gcd 0
    Gcd x `mappend` Gcd y = Gcd (gcd x y)

toI :: Gcd -> Integer
toI (Gcd x) = x

tuplify2 (x:y:_) = (x,y)
tuplify2 _ = undefined

readInt = fst . fromJust . BS.readInteger
readIntTuple = tuplify2 . map readInt . BS.words
readIntList = map readInt . BS.words

getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine
getIntNList n = map readIntList <$> replicateM (fromIntegral n) BS.getLine
getIntMatrix = map readIntList . BS.lines <$> BS.getContents
getIntTuple = readIntTuple <$> BS.getLine
getIntNTuples n = map readIntTuple <$> replicateM (fromIntegral n) BS.getLine
getIntTuples = map readIntTuple . BS.lines <$> BS.getContents

solve :: [Integer] -> Integer
solve a =
    let seg = initial (map Gcd a) :: SegmentTree Gcd
    in maximum $ map toI [(query seg 0 i) `mappend` (query seg (i+1) (length a)) | i <- [0..length a -1]]

main :: IO ()
main = do
    getLine
    a <- getIntList
    print (solve a)
--    let seg = initial (map Gcd a) :: SegmentTree Gcd
--    print . show $ map toI [(query seg 0 i) `mappend` (query seg (i+1) (length a)) | i <- [1..length a -2]]
--    let seg = initial $ map Gcd [2,4,5,8]
--    print . show $ query seg 1 2
    --print . show $ seg
    return()


{-# LANGUAGE OverloadedStrings #-}
module Main where

import           Data.List
import           Control.Monad
import           Debug.Trace
import qualified Data.ByteString.Char8         as BC
import           Data.Maybe                     ( fromJust )
import qualified Data.Set                      as S
import qualified Data.IntMap.Strict            as IM
import qualified Data.Map.Strict               as M
import           Data.Char
import Data.Bits

readTuple2 :: IO (Int, Int)
readTuple2 = do
    [a, b] <- map (fst . fromJust . BC.readInt) . BC.words <$> BC.getLine
    return (a, b)

readTuple3 :: IO (Int, Int, Int)
readTuple3 = do
    [a, b, c] <- map (fst . fromJust . BC.readInt) . BC.words <$> BC.getLine
    return (a, b, c)

readInt :: IO Int
readInt = fst . fromJust . BC.readInt <$> BC.getLine

readInts :: IO [Int]
readInts = map (fst . fromJust . BC.readInt) . BC.words <$> BC.getLine

split :: (a -> Bool) -> [a] -> [[a]]
split f [] = []
split f as =
    let (fo, la) = span f as
        las      = case la of
            [] -> []
            xs -> split f $ tail xs
    in  case fo of
            [] -> las
            xs -> xs : las

solve :: Int -> [Int] -> Int
solve n xs = let
    lTor = IM.fromList $ zip [1..] $ scanl' gcd (head xs) (tail xs)
    rTol = IM.fromList $ zip [1..] $ scanr gcd (last xs) (init xs)
    getGe 1 = rTol IM.! 2
    getGe i
        | i >= n = lTor IM.! (i - 1)
        | otherwise = gcd (lTor IM.! (i - 1)) (rTol IM.! (i + 1))
    in
    maximum $ getGe <$> [1..n]

main = do
    n <- readInt
    xs <-  readInts
    print $ solve n xs


main=do
 n<-readLn;a<-map read.words<$>getLine
 print((maximum.map(\(a,b)->if(a==0||b==0)then(max a b)else(gcd a b)))(zip(reverse(f n (reverse a) 0))(f n a 0)))
  where f 0 _ _ =[]
        f n (b:a) 0 =0:(f(n-1)a b)
        f n (b:a) g =g:(f(n-1)a(gcd g b))


import qualified Data.ByteString.Char8 as B
import           Data.List             (inits, tails)
import           Data.Maybe            (fromJust)

main :: IO ()
main = do
  n <- readLn
  as <- getInts
  print $ solve n as

solve :: Int -> [Int] -> Int
solve _ = maximum . map calcGCD . slice

-- >>> slice "abc"
-- [("", "bc"), ("a", "c"), ("ab", "")]
slice :: [a] -> [([a], [a])]
slice as = [(xs, ys) | (xs, _:ys) <- zip (init (inits as)) (init (tails as)) ]

calcGCD :: ([Int], [Int]) -> Int
calcGCD ([], ys) = gcdAll ys
calcGCD (xs, []) = gcdAll xs
calcGCD (xs, ys) = gcd (gcdAll xs) (gcdAll ys)

gcdAll :: [Int] -> Int
gcdAll = foldr1 gcd

readInts :: B.ByteString -> [Int]
readInts = map (fst . fromJust . B.readInt) . B.words

getInts :: IO [Int]
getInts = readInts <$> B.getLine


import Control.Monad
import Data.List
main = do
    n <- readLn
    a <- map read . words <$> getLine
    let ml = take n (scanl (gcd) 0 a)
    let mr = drop 1 (scanr (gcd) 0 a)
    let m = zipWith (gcd) ml mr
    print (maximum m)


main = do
    n <- readLn
    xs <- map (read::String -> Int) . words <$> getLine
    print $ maximum (func n xs)

func :: Int -> [Int] -> [Int]
func n (x:xs) = if n > 0
                    then foldr1 gcd xs:(func (n-1) (xs++[x]))
                    else []


main = do
    n <- readLn
    xs <- map (read::String -> Int) . words <$> getLine
    print $ maximum (func n (xs++xs))

func :: Int -> [Int] -> [Int]
func n xs
    | n < (length xs)   = foldr1 gcd (take (n - 1) xs) : func n (tail xs)
    | otherwise = []


main :: IO ()
main = do
  _ <- getLine
  as <- map read . words <$> getLine
  print $ solve as

solve :: [Int] -> Int
solve as = maximum $ zipWith gcd ls rs
  where
    ls = scanl gcd 0 as
    rs = tail $ reverse $ scanl1 gcd $ reverse as


module Main where
import Data.List
import qualified Data.Vector as V

main :: IO()
main = do
  n <- (read <$> getLine) :: IO Int
  a <- (fmap read <$> words <$> getLine) :: IO [Int]
  let l = V.fromList $ scanl' gcd 0 a
  let r = V.fromList $ reverse $ scanl' gcd 0 (reverse a)

  --print $ foldl max 0 $
  --  fmap (\i-> gcd (l V.! i) (r V.! (i+1))) [0..(n-1)]

  --print $ maximum $
  --  zipWith gcd l r

  print $ foldl max 0 $
     [ gcd (l V.! i) (r V.! (i + 1)) | i <- [0 .. ((fromIntegral n) - 1)] ]


main :: IO ()
main = do
  n <- readLn :: IO Int
  a <- map read . words <$> getLine :: IO [Int]

  let
    x = init $ scanl gcd 0 a
    y = tail $ reverse $ scanl gcd 0 (reverse a)

  print $ maximum $ zipWith gcd x y


import           Data.List -- sort
import           Control.Monad -- replicateM

readInt = read <$> getLine :: IO Integer
arrayInt = map read . words <$> getLine :: IO [Integer]
writeln x = putStrLn $ unwords x :: IO ()

main = do
    n <- readInt
    a <- arrayInt
    let l = scanl' gcd 0 a
    let r = reverse $ scanl' gcd 0 (reverse a)

    print $ foldl' max 0
        [ gcd (l !! i) (r !! (i + 1)) | i <- [0 .. ((fromIntegral n) - 1)] ]


import Data.List
main :: IO()
main = do
  _ <- getLine
  a <- map read . words <$> getLine
  print $ slv a

slv :: [Integer] -> Integer
slv a | length a == 2 = maximum a
      | otherwise = proc (cycle a) (length a - 2) (length a) 0

proc :: [Integer] -> Int -> Int -> Integer -> Integer
proc _ _ 0 ret = ret
proc (a:as) len n ret = proc as len (n-1) (max ret gcds)
  where gcds = foldl (gcd) a (take len as)


--{-# LANGUAGE OverloadedStrings #-}
--{-# LANGUAGE OverloadedLists   #-}
{-# LANGUAGE BangPatterns      #-} --引数に!
{-# LANGUAGE MultiWayIf        #-}
{-# LANGUAGE TupleSections     #-}

import Data.Bits
import Data.Maybe (fromJust)
import Data.List
import qualified Data.Vector.Unboxed as V
import Control.Monad
import qualified Data.ByteString.Lazy.Char8 as B

type Ans = Int

solve :: Int -> [Int] -> Ans
solve n as = maximum $ sub 0
  where
    lgcd = V.fromList $ scanl1 gcd as
    rgcd = V.fromList $ scanr1 gcd as
    sub :: Int -> [Int]
    sub 0 = rgcd V.! 1 : (sub 1)
    sub i | i == n-1 = [lgcd V.! (n-2)]
          | otherwise = gcd (lgcd V.! (i-1)) (rgcd V.! (i+1)) : (sub (i+1))

readBInt :: B.ByteString -> Int
readBInt = fst . fromJust . B.readInt

main0 :: B.ByteString -> Ans
main0 cont =
   let remLines0 = map (map readBInt . B.words) (B.lines cont)
       [n]:remLines1 = remLines0
       as = head remLines1
       in solve n as

main :: IO ()
main = print . main0 =<< B.getContents


import Data.List
main :: IO()
main = do
  _ <- getLine
  a <- map read . words <$> getLine
  print $ slv a

slv :: [Integer] -> Integer
slv a | length a == 2 = maximum a
      | otherwise = proc a [] $ 0

proc :: [Integer] -> [Integer] -> Integer -> Integer
proc [] _ ret = ret
proc (a:aa:as) n ret = proc (aa:as) (a:n) (max gcds ret)
  where gcds = foldl (gcd) aa $ as ++ n
proc (a:as) (n:ns) ret = max ret $ foldl (gcd) n ns


--prewritten code: https://github.com/antma/algo
{-# LANGUAGE BangPatterns #-}
{-# Options_GHC -O2 #-}
import Data.ByteString.Builder
import Data.Monoid
import System.IO
import qualified Data.ByteString.Char8 as C
import Data.Char
import qualified Data.IntSet as S
import Data.List

ru, ri :: C.ByteString -> Int

ru = C.foldl' (\a c -> a * 10 - 48 + ord c) 0
ri s
  | C.head s == '-' = negate $ ru $ C.tail s
  | otherwise = ru s

solve :: [Int] -> Int
solve (n:b) = S.findMax s'
  where
    (x:y:t) = take n b
    (s', _) = foldl' (\ (st, g) !j -> (S.insert g $ S.map (gcd j) st, gcd g j)) (S.fromList [x, y], gcd x y) t

main :: IO ()
main = print . solve . map ri . C.words =<< C.getContents


import Data.Array

gcdlist'::Int->[Int]->Int
gcdlist' n [] = n
gcdlist' n (x:xs) = gcdlist' (gcd n x) xs

gcdlist::[Int]->Int
gcdlist ls = gcdlist' (head ls) (tail ls)

gen_ar::Int->[Int]->Array Int Int
gen_ar n ls = listArray (1,n) ls

gcd_dropping::Array Int Int -> Int -> Int
gcd_dropping ar i =gcdlist [ar!j |j <- ((filter (i/=)) (indices ar))]

solver::Int->[Int]->Int
solver n ls = maximum [gcd_dropping (gen_ar n ls) i |i<-[1..n]]

main::IO()
main=do
  n<-return.read=<<getLine
  ls<-return.map read.words=<<getLine
  print (solver n ls)


main = do
    [a,b,c] <- map read . words <$> getLine :: IO [Int]
    let d = div b a
    print $ if d < c then d else c

Score : 100 points

Problem Statement

Takahashi likes the sound when he buys a drink from a vending machine.

That sound can be heard by spending A yen (the currency of Japan) each time.

Takahashi has B yen. He will hear the sound as many times as he can with that money, but at most C times, as he would be satisfied at that time.

How many times will he hear the sound?

Constraints

All values in input are integers.

1 \leq A, B, C \leq 100

Input

Input is given from Standard Input in the following format:

A B C

Output

Print the number of times Takahashi will hear his favorite sound.

Sample Input 1

2 11 4

Sample Output 1

4

Since he has not less than 8 yen, he will hear the sound four times and be satisfied.

Sample Input 2

3 9 5

Sample Output 2

3

He may not be able to be satisfied.

Sample Input 3

100 1 10

Sample Output 3

0


main = do
    [a,b,c] <- map read . words <$> getLine
    print $ if (div b a) > c then c else div b a


{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad
import qualified Data.ByteString.Char8 as BS

main = do
    [a, b, c] :: [Int] <- map ( read . BS.unpack ) . BS.words <$> BS.getLine
    putStrLn $ show $ min c (b `div` a)


main = getLine >>= print.(\[a,b,c] -> min c (div b a)).map read.words


import Control.Applicative

main :: IO ()
main = do
   [a, b, c] <- map read . words <$> getLine
   putStrLn $ show (solve a b c)

solve :: Int -> Int -> Int -> Int
solve a b c = if (div b a) <= c then div b a else c


{-# LANGUAGE CPP #-}
module Main where

import qualified Data.Vector as V
import qualified Data.Map.Strict as M
import Control.Monad
import qualified Data.ByteString.Char8 as BS
import Data.Maybe

dump :: (Show a) => a -> IO()
#if __GLASGOW_HASKELL__ >= 850
dump x = print x
#else
dump _ = pure ()
#endif

readint :: IO Int
readint = (fst . fromJust . BS.readInt) <$> BS.getLine

readvec :: IO [Int]
readvec = (fmap (read . BS.unpack) . BS.words) <$> BS.getLine

newtype UF a = UF (M.Map a a) deriving (Show) -- Map node parent

makeuf :: Int -> UF Int
makeuf n = let m = M.fromList $ zip [0..n] [0..n]
                in UF m

union :: (Eq a, Ord a) => a -> a -> UF a -> UF a
union l r uf@(UF m) = let lp = find l uf
                          rp = find r uf
                      in if lp == rp
                         then uf
                         else if size l uf < size r uf
                              then UF $ M.update (const $ Just rp) lp m
                              else UF $ M.update (const $ Just lp) rp m

find :: (Eq a, Ord a) => a -> UF a -> a
find x uf@(UF m) = let px = m M.! x
                in if px == x
                   then px
                   else find px uf

size :: (Eq a, Ord a) => a -> UF a -> Int
size x (UF m) = M.size $ M.filter (\par -> par==x) m

main :: IO()
main = do
  undefined


main :: IO ()
main = do
  [a, b, c] <- map read . words <$> getLine
  print $ min (b `div` a) c


main = do
  [a,b,c] <- map read . words <$> getLine
  print $ (min c (b `quot` a) :: Int)


{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE RankNTypes #-}
import qualified Data.ByteString.Lazy.Char8 as B
import Data.Maybe
-- import Data.List
-- import qualified Data.Vector.Unboxed as VU
-- import qualified Data.Vector.Unboxed.Mutable as VUM
-- import Control.Monad
-- import Control.Monad.ST
-- import Debug.Trace
-- trace _ = id

solve :: Int -> Int -> Int -> Int
solve a b c = min c (b `div` a)

readBInt :: B.ByteString -> Int
readBInt = fst . fromJust . B.readInt

tmain :: B.ByteString -> Int
tmain cont =
  let remLines0 = map B.words (B.lines cont)
      [bs_a,bs_b,bs_c]:remLines1 = remLines0
      a = readBInt bs_a
      b = readBInt bs_b
      c = readBInt bs_c
  in solve a b c

outAnswer :: Int -> IO ()
outAnswer = putStrLn . show

main :: IO ()
main = outAnswer . tmain =<< B.getContents

-------------------------------------------------------------------------------

inp1 = "2 11 4\n"
inp2 = "3 9 5\n"
inp3 = "100 1 10\n"
tv1 = tmain $ B.pack inp1
tv2 = tmain $ B.pack inp2
tv3 = tmain $ B.pack inp3
test1 = tv1 == 4
test2 = tv2 == 3
test3 = tv3 == 0
alltest = test1 && test2 && test3


{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NumDecimals #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}

import Control.Applicative
import Control.Arrow
import Control.Monad
import Control.Monad.ST

import Data.Char
import Data.List
import Data.Maybe

import qualified Data.ByteString.Char8 as B

import Data.Array.ST.Safe
import Data.STRef

import Debug.Trace
import Text.Printf

readInt = readLn :: IO Int
readInts = map ( fst . fromJust . B.readInt ) . B.words <$> B.getLine
readNInts = readInt >>= flip replicateM readInt

which a b f = if f then a else b
mp [ a, b ] = ( a, b )

main = do
	[ a, b, c ] <- readInts
	print $ min c $ b `div` a


main :: IO ()
main = do
  [a, b, c] <- map read . words <$> getLine
  print $ solve a b c

solve :: Int -> Int -> Int -> Int
solve a b c = min (b `div` a) c


main :: IO ()
main = do
  [a,b,c] <- map read . words <$> getLine :: IO [Int]

  print $ min c (b `div` a)


-- 2 variables
main = do
  (x:y:z:xs) <- map read . words <$> getLine
  putStrLn . show $ solve x y z

solve :: Int -> Int -> Int -> Int
solve x y z = min (y `div` x) z


import Control.Monad
import Data.List
import Data.Bits
import Debug.Trace
import Data.Maybe
import qualified Data.ByteString.Char8 as C

main :: IO ()
main = do
  [a, b, c] <- readInts
  print $ solve a b c

solve :: Int -> Int -> Int -> Int
solve a b c = min (b `div` a) c

-- 以下ライブラリ

readInts :: IO [Int]
readInts = map (fst . fromJust . C.readInt) . C.words <$> C.getLine

readNInts :: Int -> IO [[Int]]
readNInts = flip replicateM readInts

readIntegers :: IO [Integer]
readIntegers = map (fst . fromJust . C.readInteger) . C.words <$> C.getLine

readNIntegers :: Int -> IO [[Integer]]
readNIntegers = flip replicateM readIntegers

getNLns :: Int -> IO [String]
getNLns = flip replicateM getLine


main = do
  [a,b,c] <- map read . words <$> getLine
  print $ min (div b a) c


main = do
    [a, b, c] <- map read . words <$> getLine
    print $ min c (b `div` a)


{-# LANGUAGE BangPatterns #-}
import Control.Monad
import Data.Maybe
import Debug.Trace
import Data.List
import qualified Data.Map.Strict as Map
import qualified Data.IntMap.Strict as IntMap
import qualified Data.Set as Set
import qualified Data.IntSet as IntSet
import Data.Functor
import Data.Array

main :: IO ()
main = do
  (a:b:c:_) <- fmap (map read . words) getLine :: IO [Int]
  print $ solve a b c

solve a b c = min c (b `div` a)


{-# LANGUAGE RecursiveDo        #-}
{-# LANGUAGE OverloadedStrings  #-}
{-# LANGUAGE NumericUnderscores #-}

import qualified Data.ByteString.Char8 as C8
import Data.List
import Data.Char

solve :: Int -> Int -> [Int] -> Int
solve d1 d2 [x, y   ] = d2
solve d1 d2 [x, y, z] = dn
  where a  = d1 + abs (z - x)
        b  = d2 + abs (z - y)
        dn = min a b
solve d1 d2 (x:y:z:h) = solve d2 dn (y:z:h)
  where a  = d1 + abs (z - x)
        b  = d2 + abs (z - y)
        dn = min a b

main :: IO ()
main = do
  _ <- getLine
  h@(h0:h1:hs) <- unfoldr (C8.readInt . C8.dropWhile isSpace) <$> C8.getLine
  print $ solve 0 (abs (h0 - h1)) h

Score : 100 points

Problem Statement

There are N stones, numbered 1, 2, \ldots, N.
For each i (1 \leq i \leq N), the height of Stone i is h_i.

There is a frog who is initially on Stone 1.
He will repeat the following action some number of times to reach Stone N:

If the frog is currently on Stone i, jump to Stone i + 1 or Stone i + 2. Here, a cost of |h_i - h_j| is incurred, where j is the stone to land on.

Find the minimum possible total cost incurred before the frog reaches Stone N.

Constraints

All values in input are integers.

2 \leq N \leq 10^5

1 \leq h_i \leq 10^4

Input

Input is given from Standard Input in the following format:

N
h_1 h_2 \ldots h_N

Output

Print the minimum possible total cost incurred.

Sample Input 1

4
10 30 40 20

Sample Output 1

30

If we follow the path 1 → 2 → 4, the total cost incurred would be |10 - 30| + |30 - 20| = 30.

Sample Input 2

2
10 10

Sample Output 2

0

If we follow the path 1 → 2, the total cost incurred would be |10 - 10| = 0.

Sample Input 3

6
30 10 60 10 60 50

Sample Output 3

40

If we follow the path 1 → 3 → 5 → 6, the total cost incurred would be |30 - 60| + |60 - 60| + |60 - 50| = 40.


{-# LANGUAGE BangPatterns        #-}
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE MultiWayIf          #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE ScopedTypeVariables #-}
import           Control.Monad.State
import qualified Data.ByteString.Char8 as BS
import           Data.Char
import           Data.List

main :: IO ()
main = do
  _ <- getLine
  (h:hs) <- readLnAsListWith unconsInt

  print $ solve h hs

solve :: Int -> [Int] -> Int
solve h hs = go hs h 0 20000
  where go [] _ a b       = min a b

        go [x] n a b      = let a' = a + (abs $ n - x)
                            in go [] x (min b a') b

        go (x:y:xs) n a b = let a' = a + (abs $ n - x)
                                b' = a + (abs $ n - y)
                            in go (y:xs) x (min b a') b'

unconsInt :: StateT BS.ByteString Maybe Int
unconsInt = StateT $ BS.readInt . BS.dropWhile isSpace

readLnAsListWith :: StateT BS.ByteString Maybe a -> IO [a]
readLnAsListWith !st = unfoldr (runStateT st) <$> BS.getLine


    {-# OPTIONS_GHC -O2 #-}
    {-# LANGUAGE BangPatterns #-}
    import qualified Control.Arrow         as Arrow
    import qualified Control.Monad         as Monad
    import qualified Data.Bits             as Bits
    import qualified Data.ByteString.Char8 as BSC8
    import qualified Data.Char             as Char
    import qualified Data.List             as List
    import qualified Data.Vector.Unboxed   as VU

    main :: IO ()
    main = do
        !n  <- readLn :: IO Int
        !xv <- getAN n -- VU.Vector Int
        print $ solver xv (n - 1)

    data FlogTreeF a
        = Flog !Int !(Maybe a)
    instance Functor FlogTreeF where
        fmap f (Flog x Nothing)  = Flog x Nothing
        fmap f (Flog x (Just y)) = Flog x (Just (f y))

    solver :: VU.Vector Int -> Int -> Int
    solver !xv = dyna phi psi
        where
            psi 0 = Flog (xv VU.! 0) Nothing
            psi i = Flog (xv VU.! i) (Just (i - 1))

            {-
            dp[i] := 足場iに到着したときの最小のコスト
            i-1 から来る場合 + そこからのコスト
            と
            i-2 から来る場合 + そこからのコスト
            のうち小さいものを選ぶ
            -}
            phi (Flog h Nothing)  = 0 -- 最初は0なので dp[0] = 0
            phi (Flog h (Just t)) = case sub t of
                Flog h' Nothing -> abs (h - h') -- dp[1] = |h - h'|最初のコスト
                Flog h' (Just t') -> case sub t' of
                    Flog h'' _ -> min f1 f2 -- dp[h] 一般の場合
                        where
                            f1 = extract t  + abs (h - h')  -- i - 1から来た場合のコスト extract t がdp[h-1]を表す
                            f2 = extract t' + abs (h - h'') -- i - 2から来た場合のコスト extract t'がdp[h-2]を表す

    -- * 入出力
    -- Int一文字入力
    getI :: BSC8.ByteString -> Maybe (Int, BSC8.ByteString)
    getI = fmap (Arrow.second BSC8.tail) . BSC8.readInt
    -- Vector Intによるn文字入力
    getAN :: Int -> IO (VU.Vector Int)
    getAN n = VU.unfoldrN n getI <$> BSC8.getLine

    -- ! 射
    newtype Fix f
        = InF { outF :: f (Fix f) }

    -- 補助関数
    pair :: (a -> b, a -> c) -> a -> (b, c)
    pair (f, g) x = (f x, g x)

    -- ! 下方射
    cata :: Functor f => (f a -> a) -> (Fix f -> a)
    cata phi = phi . fmap (cata phi) . outF
    -- ! 上方射
    ana  :: Functor f => (b -> f b) -> (b -> Fix f)
    ana psi = InF . fmap (ana psi) . psi
    -- ! 双方射
    hylo :: Functor f => (f b -> b) -> (a -> f a) -> (a -> b)
    hylo phi psi = cata phi . ana psi

    -- * 未来用データ(直和)
    data Fx f a x
        = Fx { unFx :: Either a (f x) }
    -- * 過去用データ（直積）
    data Hx f a x
        = Hx { unHx :: (a, f x) }

    -- * Fx f a は関手
    instance Functor f => Functor (Fx f a) where
        fmap f (Fx (Left x))  = Fx (Left x)
        fmap f (Fx (Right x)) = Fx (Right (fmap f x))
    -- * Hx f a は関手
    instance Functor f => Functor (Hx f a) where
        fmap f (Hx (x, y)) = Hx (x, fmap f y)

    -- * Fx f a の不動点
    newtype Free f a
        = Free { unFree :: Fix (Fx f a) }
    -- * Hx f a の不動点
    newtype CoFree f a
        = CoFree { unCoFree :: Fix (Hx f a) }

    -- * Free f は関手
    instance Functor f => Functor (Free f) where
        fmap f = Free . cata (InF . phi) . unFree
            where
                phi (Fx (Left a))  = Fx (Left (f a))
                phi (Fx (Right b)) = Fx (Right b)
    -- * CoFree f は関手
    instance Functor f => Functor (CoFree f) where
        fmap f = CoFree . ana (psi . outF) . unCoFree
            where
                psi (Hx (a, x)) = Hx (f a, x)

    -- * Free と CoFree の情報を出し入れする関数
    extract :: Functor f => CoFree f t -> t
    extract cf = case outF (unCoFree cf) of
        Hx (a, _) -> a

    sub :: Functor f => CoFree f a -> f (CoFree f a)
    sub cf = case outF (unCoFree cf) of
        Hx (_, b) -> fmap CoFree b

    inject :: Functor f => a -> Free f a
    inject = Free
            . InF
            . Fx
            . Left

    -- ! 時空射
    chrono :: Functor f => (f (CoFree f b) -> b) -> (a -> f (Free f a)) -> (a -> b)
    chrono phi psi = extract . hylo phi' psi' . inject
        where
            phi' = CoFree
                . InF
                . fmap unCoFree
                . Hx
                . pair (phi, id)
            psi' = uncurry either (psi, id)
                . unFx
                . fmap Free
                . outF
                . unFree

    -- ! dp射
    dyna :: Functor f => (f (CoFree f b) -> b) -> (a -> f a) -> (a -> b)
    dyna phi psi = chrono phi (fmap inject . psi)


import Control.Monad
import Data.Maybe
import qualified Data.ByteString.Char8 as BS
import Data.List
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM

readInt = fst . fromJust . BS.readInt
readIntList = map readInt . BS.words
getInt = readInt <$> BS.getLine
getIntList = readIntList <$> BS.getLine

main = do
    n <- getInt
    hs <- VU.fromList <$> getIntList
    dp <- VUM.replicate n 0
    VUM.write dp 0 0
    VUM.write dp 1 $ abs ((hs VU.! 1) - (hs VU.! 0))
    forM_ [2..n-1] $ \i -> do
        a <- VUM.read dp (i - 1)
        b <- VUM.read dp (i - 2)
        let da = abs $ (hs VU.! (i - 1)) - (hs VU.! i)
        let db = abs $ (hs VU.! (i - 2)) - (hs VU.! i)
        VUM.write dp i $ min (a + da) (b + db)
    ans <- VUM.read dp (n - 1)
    print ans


import qualified Data.ByteString.Char8 as BC
import Data.Maybe

readIntsLine :: IO [Int]
readIntsLine = map (fst . fromJust . BC.readInt) . BC.words <$> BC.getLine

calc :: (Int, Int) -> (Int, Int) -> Int -> Int
calc (pc2, pc1) (ph2, ph1) h = min c2 c1
  where c2 = pc2 + abs (ph2 - h)
        c1 = pc1 + abs (ph1 - h)

solve :: [Int] -> (Int, Int) -> (Int, Int) -> [Int]
solve [] _ _ = []
solve (h:hs) pcs@(pc2, pc1) phs@(ph2, ph1) = cost : next
  where cost = calc pcs phs h
        next = solve hs (pc1, cost) (ph1, h)

main :: IO ()
main = do
  getLine
  (h:hs) <- readIntsLine
  print . last $ solve hs (0, 0) (h, h)


{-# LANGUAGE ScopedTypeVariables #-}
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import qualified Data.ByteString.Char8 as BS
import Control.Monad
import Control.Applicative
import Data.Char

solve :: VU.Vector Int -> VU.Vector Int
solve hs =
  VU.create $ do
    table <- VUM.replicate (l+1) (10^5 :: Int)
    VUM.write table 0 0
    forM_ [1..l-1] $ \i ->
      if i==1 then
        VUM.write table i (h i 1)
      else do
        a1 <- VUM.read table (i-1)
        a2 <- VUM.read table (i-2)
        VUM.write table i $ min (a1 + h i 1) (a2 + h i 2)
    return table
  where
    l = VU.length hs
    h x n = abs $ (hs VU.! x) - (hs VU.! (x-n))

main = do
  n <- readLn :: IO Int
  (hs :: VU.Vector Int) <- VU.unfoldrN n (BS.readInt . BS.dropWhile isSpace) <$> BS.getLine
  print $ solve hs VU.! (n-1)


main = do
  getLine
  hs <- map read . words <$> getLine :: IO [Int]
  print $ dp hs [] []

dp :: [Int] -> [Int] -> [Int] -> Int
dp []  _ zs = head zs
dp (x:xs) [] _ = dp xs [x] [0]
dp (x:xs) [y] _ = dp xs [x,y] [abs (y-x),0]
dp (x:xs) (y1:y2:ys) (z1:z2:zs) =
  let
    m = min (z1 + abs (y1-x)) (z2 + abs (y2-x))
  in
    dp xs (x:y1:y2:ys) (m:z1:z2:zs)


import           Control.Monad
import qualified Data.ByteString.Char8       as BS
import           Data.Char
import           Data.Maybe
import qualified Data.Vector.Unboxed         as V
import qualified Data.Vector.Unboxed.Mutable as VM

readInt = fst . fromJust . BS.readInt
getInt = readInt <$> BS.getLine
getIntVec n = V.unfoldrN n (BS.readInt . BS.dropWhile isSpace) <$> BS.getLine

main = do
  n <- getInt
  h <- getIntVec n

  dp <- VM.new n
  VM.write dp 0 0
  VM.write dp 1 (abs (h V.! 0 - h V.! 1))
  forM_ [2..n-1] $ \i -> do
    c2 <- VM.read dp (i - 2)
    c1 <- VM.read dp (i - 1)
    let c2' = c2 + abs (h V.! i - h V.! (i - 2))
        c1' = c1 + abs (h V.! i - h V.! (i - 1))
    VM.write dp i (min c1' c2')

  ans <- VM.read dp (n-1)
  print ans


{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
module Main where

import Data.Char (isSpace)
import qualified Data.Vector.Unboxed as U
import qualified Data.ByteString.Char8 as C

type Parser a = C.ByteString -> Maybe (a, C.ByteString)

parseInt :: Parser Int
parseInt = C.readInt . C.dropWhile isSpace

getIntVec :: Int -> IO (U.Vector Int)
getIntVec n = U.unfoldrN n parseInt <$> C.getLine

----------------------------
pair (f, g) x = (f x, g x)
cross (f, g) (x, y) = (f x, g y)

newtype Fix f = In { out :: f (Fix f) }

newtype Cofree f a = Cf { unCf :: (a, f (Cofree f a)) }
extract :: Cofree f t -> t
extract = fst . unCf
sub :: Functor f => Cofree f a -> f (Cofree f a)
sub = snd . unCf

newtype Free f a = Fr { unFr :: Either a (f (Free f a)) }
inject :: a -> Free f a
inject = Fr . Left

-- catamorphism
cata :: Functor f => (f a -> a) -> Fix f -> a
cata phi = phi . fmap (cata phi) . out
-- anamorphism
ana :: Functor f => (a -> f a) -> a -> Fix f
ana psi = In . fmap (ana psi) . psi
-- hylomorphism
hylo :: Functor f => (f b -> b) -> (a -> f a) -> a -> b
hylo phi psi = cata phi . ana psi -- phi . fmap (hylo phi psi) . psi
-- metamorphism
meta :: Functor f => (f a -> a) -> (a -> f a) -> Fix f -> Fix f
meta phi psi = ana psi . cata phi -- In . fmap (meta phi psi) . out
-- paramorphism
para :: Functor f => (f (Fix f, t) -> t) -> Fix f -> t
para phi = phi . fmap (pair (id, para phi)) . out
-- apomorphism
apo :: Functor f => (t -> f (Either (Fix f) t)) -> t -> Fix f
apo psi = In . fmap (uncurry either (id, apo psi)) . psi
-- histomorphism
histo :: Functor f => (f (Cofree f t) -> t) -> Fix f -> t
histo phi = extract . cata (Cf . pair (phi, id))
-- futumorphism
futu :: Functor f => (t -> f (Free f t)) -> t -> Fix f
futu psi = ana (uncurry either (psi, id) . unFr) . inject
-- chronomorphism
chrono :: Functor f => (f (Cofree f b) -> b) -> (a -> f (Free f a)) -> a -> b
chrono phi psi = histo phi . futu psi
-- cochronomorphism
cochrono :: Functor f => (f (Cofree f t) -> t) -> (t -> f (Free f t)) -> Fix f -> Fix f
cochrono phi psi = futu psi . histo phi
-- zygomorphism
zygo :: Functor f => (f a -> a) -> (f (a, b) -> b) -> Fix f -> b
zygo f phi = snd . cata (pair (f . fmap fst, phi))
-- cozygomorphism
cozygo :: Functor f => (a -> f a) -> (b -> f (Either a b)) -> b -> Fix f
cozygo f psi = ana (uncurry either (fmap Left . f, psi)) . Right
-- dynamorphism
dyna :: Functor f => (f (Cofree f b) -> b) -> (a -> f a) -> a -> b
dyna f g = chrono f (fmap inject . g)
-- codynamorphism
codyna :: Functor f => (f b -> b) -> (a -> f (Free f a)) -> a -> b
codyna f g = chrono (f . fmap extract) g
-- mutumorphism
mutu :: Functor f => (a -> b) -> (f a -> a) -> Fix f -> b
mutu proj phi = proj . cata phi

foldn (c, f) 0 = c
foldn (c, f) n = f (foldn (c, f) (n-1))

paran (c, f) 0 = c
paran (c, f) n = f n (paran (c, f) (n-1))

---------------------------------------------------------

main :: IO ()
main = do
  !n <- readLn :: IO Int
  !hs <- getIntVec n
  print $ step (distrib hs)

data NonEmptyListF a = NonEmptyListF Int (Maybe a) deriving (Show, Functor)
type NonEmptyList = Fix NonEmptyListF
instance Show NonEmptyList where
  show (In (NonEmptyListF h Nothing)) = show h ++ ":[]"
  show (In (NonEmptyListF h (Just t))) = show h ++ ":" ++ show t

distrib vec = ana (psi vec) (U.length vec - 1)
psi vec = u
  where
    u 0 = NonEmptyListF (vec U.! 0) Nothing
    u i = NonEmptyListF (vec U.! i) (Just (i-1))

step :: NonEmptyList -> Int
step = histo phi
  where
    phi (NonEmptyListF h Nothing) = 0
    phi (NonEmptyListF h (Just t)) = case sub t of
      NonEmptyListF h' Nothing   -> abs (h-h')
      NonEmptyListF h' (Just t') -> case sub t' of
        NonEmptyListF h'' _ -> min f1 f2
          where
            f1 = extract t  + abs (h-h')
            f2 = extract t' + abs (h-h'')


{-# OPTIONS_GHC -O2 #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE BangPatterns #-}
module Main where

import Data.Char (isSpace)
import qualified Data.Vector.Unboxed as U
import qualified Data.ByteString.Char8 as C

type Parser a = C.ByteString -> Maybe (a, C.ByteString)

parseInt :: Parser Int
parseInt = C.readInt . C.dropWhile isSpace

getIntVec :: Int -> IO (U.Vector Int)
getIntVec n = U.unfoldrN n parseInt <$> C.getLine

paran2 :: (Eq a, Num a) => (t, t, a -> t -> t -> t) -> a -> t
paran2 (c, d, f) = u
  where
    u 0 = c
    u 1 = d
    u n = f n (u (n-2)) (u (n-1))

---------------------------------------------------------

main :: IO ()
main = do
  !n <- readLn :: IO Int
  !hs <- getIntVec n
  print $ step hs (n-1)

step :: U.Vector Int -> Int -> Int
step vec = fst . paran2 (c, d, f)
  where
    c = (0, vec U.! 0)
    d = (abs (h1-h), h) where (h1, h) = (vec U.! 0, vec U.! 1)
    f !n (!c2, !h2) (!c1, !h1) = (min c2' c1', h)
      where
        h = vec U.! n
        (!c2', !c1') = (c2+abs(h2-h), c1+abs(h1-h))


{-# LANGUAGE BangPatterns #-}
import Control.Arrow
import Data.Int
import Data.Foldable
import qualified Data.Vector.Unboxed as VU
import qualified Data.ByteString.Char8 as B

solve :: Int -> VU.Vector Int16 -> Int
solve n hs = fst dp
 where
  -- dp[i]: minimal cost of moving from 1st to i-th place
  dp :: (Int, Int)
  dp = VU.ifoldl'
    ( \(!dp1, !dp2) !i !v -> if i == 0
      then (0, dp1)
      else if i == 1
        then (dp1 + abs (fromIntegral $ v - hs VU.! 0), dp1)
        else
          ( min (dp1 + abs (fromIntegral $ v - hs VU.! (i - 1)))
                (dp2 + abs (fromIntegral $ v - hs VU.! (i - 2)))
          , dp1
          )
    )
    (-1, -1)
    hs

main = do
  let readInt :: Integral a => B.ByteString -> Maybe (a, B.ByteString)
      readInt = fmap (first fromIntegral . second B.tail) . B.readInt

  n  <- (\vec -> (vec VU.! 0)) . VU.unfoldrN 1 readInt <$> B.getLine
  hs <- VU.unfoldrN n readInt <$> B.getLine
  print $ solve n hs


main = interact $ show.helper.(map read).words

helper (x:xs)= fonk xs

fonk [x] = 0
fonk (x:y:[]) = abs(x-y)
fonk (x:ys@(y:zs@(z:_))) = min ((fonk ys) + abs(x-y)) ((fonk zs) + abs(z-y))