import System.IO import Data.Set (Set) import qualified Data.Set as Set import Data.Char (ord,chr) type Pos = (Int,Int) ppinsert :: Char -> [Pos] -> ([String],Int,Int) -> [String] ppinsert _ [] (b,_,_) = b ppinsert id ((x,y):xs) d@(b,minx,miny) = nbrd where nextid | id == '#' = '#' | id == 'H' = '1' | otherwise = chr $ (ord id)+1 (brows,(orow:arows)) = splitAt (y-miny) $ ppinsert nextid xs d (bchars,(_:achars)) = splitAt (x-minx) orow nrow = bchars ++ [id] ++ achars nbrd = brows ++ [nrow] ++ arows ppp :: Char -> [Pos] -> String ppp h l = concat $ reverse $ ppinsert h l (start,minx,miny) where (x,y) = unzip l minx = min (-10) (minimum x) miny = min (-5) (minimum y) maxx = max 10 (maximum x) maxy = max 5 (maximum y) srow = replicate (-minx) '.' ++ "s" ++ replicate maxx '.' ++ "\n" brow = replicate (-minx) '.' ++ "." ++ replicate maxx '.' ++ "\n" start = replicate (-miny) brow ++ [srow] ++ replicate maxy brow parseMove :: String -> [Pos] parseMove s = replicate n dv where d = head s n = read (drop 2 s) :: Int dv = case d of 'U' -> (0,1) 'R' -> (1,0) 'D' -> (0,-1) 'L' -> (-1,0) parseMoves :: String -> [Pos] parseMoves = concat . map parseMove . lines dragTail :: [Pos] -> [Pos] dragTail [t] = [t] dragTail l@( h@(hx,hy) : (nx,ny) : xs) | dx > 1 = (h : dragTail ((nx+1 ,ny+dyu) : xs)) | dy > 1 = (h : dragTail ((nx+dxu,ny+1 ) : xs)) | dx < -1 = (h : dragTail ((nx-1 ,ny+dyu) : xs)) | dy < -1 = (h : dragTail ((nx+dxu,ny-1 ) : xs)) | otherwise = l where (dx,dy) = (hx-nx,hy-ny) (dxu,dyu) = (signum dx,signum dy) sim :: (Set Pos,[Pos]) -> Pos -> (Set Pos,[Pos]) sim (s,((hx,hy):t)) (dx,dy) = (ns,nl) -- trace (ppp 'H' nl) where nh = (hx+dx,hy+dy) nl = dragTail (nh:t) ns = Set.insert (last nl) s handler :: String -> String handler s = (show $ Set.size trail2) ++ "\n" ++ (show $ Set.size trail10) ++ "\n" where moves = parseMoves s start2 = (Set.empty,[(0,0),(0,0)]) start10 = (Set.empty,replicate 10 (0,0)) (trail2,_) = foldl sim start2 $ moves (trail10,_) = foldl sim start10 $ moves main :: IO () main = do interact handler