चूहा भूलभुलैया बनाने का कार्यक्रम


15

आपको एक शोध सहायक के रूप में काम पर रखा गया है, और एक छोटा सा कार्यक्रम बनाने के लिए कहा गया है जो चूहे के मांस का निर्माण करेगा। चूहा बॉक्स हमेशा 62x22 है और चूहे के लिए एक प्रवेश द्वार (ए) और निकास (ए) है, इस तरह (इनपुट 1):

#######a######################################################
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#################################################A############

आपके प्रोग्राम को चूहे के लिए पथ (#) के साथ बॉक्स को भरना होगा, इस तरह (आउटपुट 1):

#######a######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
#######                                           ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
################################################# ############
#################################################A############

यह आसान है आपको लगता है! आप आत्मविश्वास से भरे एक छोटे से कार्यक्रम को लिखना शुरू करते हैं। हालांकि, प्रिंसिपल साइंटिस्ट का एक नया विचार है - वह दो चूहों को एक ही समय में भूलभुलैया नेविगेट करना चाहता है। डॉ। रतनशॉंटर बताते हैं कि उनके अलग-अलग दरवाजे और अलग-अलग निकास हैं (इनपुट 2):

#b#####a######################################################
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            #
#                                                            B
#                                                            #
#################################################A############

चूहों को क्रॉस चौराहों के माध्यम से सीधे स्थानांतरित करने के लिए प्रशिक्षित किया गया है लेकिन टी-चौराहे उन्हें निराशाजनक रूप से भ्रमित करते हैं और प्रयोग को अमान्य कर देंगे। आप अपने नए अधिक जटिल कार्य को शुरू करते हैं जब अच्छे डॉक्टर एक अंतिम आवश्यकता बताते हैं: चूहे एक-दूसरे के लिए बड़े होते हैं, इसलिए यदि वे एक-दूसरे को किसी भी बिंदु पर देखते हैं, तो एक चूहा लड़ाई खत्म हो जाएगी और आप दोनों नैतिकता बोर्ड से पहले होंगे। अब आप महसूस करते हैं कि आपके प्रोग्राम को कुछ इस तरह से एक आउटपुट का उत्पादन करना चाहिए (आउटपुट 2):

#b#####a######################################################
# ##### ######################################################
# ##### ######################################################
# ##### #######################################           ####
# ##### ####################################### ######### ####
# #####                                           ####### ####
# ############################################# # ####### ####
# ############################################# # ####### ####
# ############################################# # ####### ####
# ############################################# # ####### ####
#                                               # ####### ####
################################################# ####### ####
################################################# ####### ####
################################################# ####### ####
################################################# ####### ####
################################################# ####### ####
################################################# ####### ####
################################################# ####### ####
################################################# ####### ####
################################################# #######    B
################################################# ############
#################################################A############

जब तक चूहा बी चौराहे पर पहुंचता है, तब तक चूहा A से बाहर निकलने के लिए गलियारे से नीचे उतर जाएगा और चूहे की लड़ाई से बचा जा सकेगा।

नियम:

  • आपके प्रोग्राम को ऊपर दिए गए इनपुट (STDIN या फ़ाइल) में पढ़ना चाहिए, और कई स्थानों को छोड़कर समान डेटा (STDOUT या फ़ाइल) एक ही डेटा अब हैश (#) होगा। आप इनपुट स्ट्रिंग के ;बजाय किसी भी एकल वर्ण (जैसे ) को प्रतिस्थापित कर सकते हैं, \nलेकिन आउटपुट स्ट्रिंग के लिए अभी भी \nवर्णों की आवश्यकता होती है। UPDATED

  • एक चूहा पथ एक चौराहा चौड़ा होना चाहिए, सिवाय क्रॉस चौराहों के (हर स्थान पर शून्य या दो orthogonally आसन्न #वर्ण होना चाहिए )। क्रॉस चौराहों को छोड़कर प्रत्येक चूहे के पास एक स्पष्ट एकल रास्ता होना चाहिए। किसी भी टी-चौराहों की अनुमति नहीं है।

  • चूहों को एक साथ जारी किया जाता है और एक स्थिर दर पर स्थानांतरित किया जाता है। किसी भी समय में दो या दो से अधिक चूहों को एक-दूसरे को नहीं देखना चाहिए ( #बीच में एक से अधिक वर्णों के बिना एक ही स्तंभ या पंक्ति में हो)।

  • यदि कोई समाधान संभव नहीं है (जैसे आसन्न प्रवेश बिंदु), प्रिंट Impossible\nऔर बाहर निकलें।

  • प्रवेश और निकास किसी भी तरफ हो सकते हैं, हालांकि वे कोनों पर कभी नहीं होंगे।

  • (जैसे: एक मिलान प्रवेश और निकास के लिए आसन्न हैं ##aA##), चूहे सीधे से नहीं जा सकते aकरने के लिए A। भूलभुलैया क्षेत्र के अंदर एक छोटा 2 अंतरिक्ष गलियारा अनुभाग होना चाहिए।

  • मोड़ पर जहां एक चूहा अपने निकास बिंदु (या उसके बाद किसी भी समय) तक पहुंचता है, यह अब अन्य चूहों को दिखाई नहीं देता है।

  • आपका कार्यक्रम 26 चूहों तक 1, 2 के लिए mazes की गणना करने के लिए डिज़ाइन किया जा सकता है।

  • मानक खामियों को अस्वीकार कर दिया जाता है।

स्कोर:

अपने समाधान के साथ, अपने कार्यक्रम को कितने भूलभुलैया प्रति भूलभुलैया (एन) को हल कर सकते हैं। आपका अंक इस संख्या N से विभाजित बाइट्स में आपकी कोड लंबाई है।

कृपया अपने उत्तर में एक नमूना आउटपुट शामिल करें ताकि हम देख सकें कि आपका कार्यक्रम क्या पैदा करता है।


क्या संभावित आदानों में एकमात्र अंतर A, A, b, B के स्थानों का है?
xnor

2 चूहे संस्करण के लिए, हाँ। यदि आपका कार्यक्रम 3 चूहों तक के लिए डिज़ाइन किया गया है, तो आपको ए, बी, सी, ए, बी, सी के सभी संभावित स्थानों के साथ सामना करना होगा।
लॉजिक नाइट

क्या टी चौराहों को अनुमति दी जाती है यदि चूहा केवल टी के क्षैतिज भाग के साथ चलेगा?
orlp

नहीं, ये चूहे आसानी से भ्रमित हो जाते हैं। केवल सीधे रास्ते, कोहनी मोड़, और क्रॉस सड़कों की अनुमति है।
लॉजिक नाइट

@CarpetPython क्या कोई प्रवेश / निकास भूलभुलैया के किनारे कहीं भी हो सकता है? क्या वे आसन्न हो सकते हैं?
orlp

जवाबों:


2

हास्केल, 26 चूहे ?, ~ 5000 बाइट्स

सैद्धांतिक रूप से, यह कोड किसी भी संख्या में चूहों के लिए काम करना चाहिए, लेकिन मैं कोई वारंटी नहीं देता हूं कि यह ब्रह्मांड की गर्मी से पहले ही समाप्त हो जाएगा। यह एक बैकग्राउंडिंग एल्गोरिथ्म पर आधारित है जो पहले सीधे रास्ते पर जाने की कोशिश करता है, और फिर पथ स्विच करता है अगर पथ काम नहीं करता है। पथ की लंबाई और चूहों की संख्या के संबंध में विकल्पों की संख्या घातीय है।

मैंने इसे अभी तक गोल्फ के लिए परेशान नहीं किया है, क्योंकि यह बहुत बड़ा है, और जब से मैं इसे पहले से तेज करना चाहता हूं।

{-# LANGUAGE FlexibleContexts #-}
module Main (main) where

import Control.Lens
import Control.Monad
import Data.Char
import Data.Function
import Data.List
import Data.Maybe

type Pos = (Int,Int)
type Path = [Pos]
type Maze = String
type Input = [(Pos,Char)]
type MazeState = [(Path,Path)]

type ChoiceMonad a = [a]


instance (Num a, Num b) => Num (a,b) where
  (x,y)+(x',y')=(x+x',y+y')
  (x,y)-(x',y')=(x-x',y-y')
  fromInteger n = (fromInteger n,fromInteger n)


parseMaze :: Maze -> Input
parseMaze maze = maze ^@.. inner . filtered (`notElem` "# ")

inner :: IndexedTraversal' Pos Maze Char
inner = lined <.> traversed

main :: IO ()
main = do
    maze <- readFile "Sample2.in"
    putStrLn $ solveAndShow maze

fillMaze :: Maze -> Maze
fillMaze = inner.filtered(==' ').~'#'

updateMaze :: Path -> Maze -> Maze
updateMaze path = inner.indices (`elem` path).filtered(=='#') .~ ' '

isDone :: MazeState -> Bool
isDone = all (null . snd)

showMaze :: Maze -> MazeState -> Maze
showMaze maze path = updateMaze (fst =<< path) $ fillMaze maze

showSolution :: Maze -> ChoiceMonad MazeState -> String
showSolution _    []    = "Impossible"
showSolution maze (x:_) = showMaze maze x


stopCondition :: ChoiceMonad MazeState ->  Bool
stopCondition x = not $ null x || isDone (head x)

solveAndShow :: Maze -> String
solveAndShow maze = showSolution maze . solve $ mazeToState maze

solve :: ChoiceMonad MazeState -> ChoiceMonad MazeState
solve = fromJust . find (not.stopCondition) . iterate fullStep

mazeToState :: Maze -> ChoiceMonad MazeState
mazeToState maze = do
    let startsEnds = paths $ parseMaze maze
        return $ startsEnds & traverse.both %~ (:[])


fullStep :: ChoiceMonad MazeState -> ChoiceMonad MazeState
fullStep = (>>= stepAll)

stepAll :: MazeState -> ChoiceMonad MazeState
stepAll input = do
    pths <- mapM goStep input
    guard $ iall (checkVisible pths) $ map fst pths
    return $ pths
  where
    goStep :: (Path,Path) -> ChoiceMonad (Path,Path)
    goStep (curr:rest,[]) = return (curr:curr:rest,[])
    goStep (curr:these,end:ends)
       | distance curr end == 1 = return (end:curr:these,ends)

       | curr == end = goStep (curr:these,ends)
    goStep (path,end) = do
      next <- twoSteps (head end) path
      prev <- twoSteps next end
      return $ (next:path,prev:end)
    inMaze = inMazeWith input

    twoSteps :: Pos -> Path -> ChoiceMonad Pos
    twoSteps goal path = do
      next <- oneStep goal path inMaze
      guard $ not.null $ oneStep goal (next:path) (\x -> x==next || inMaze x)
      return next

checkVisible :: MazeState -> Int -> Path -> Bool
checkVisible _    _ [] = True
checkVisible pths i xs@(x:_) = checkBack && checkNow
  where
    nBack = 1 + visibleBackwards xs
    --checkBack = none (any (==x).take nBack .fst) pths
    checkBack = hasn't (folded.indices (/=i)._1.taking nBack folded.filtered (==x)) pths
    checkNow  = inone (\i' (x':_,_) -> (i/=i') && (==x') `any` take nBack xs ) pths

-- How long have you stayed on a line
visibleBackwards :: Path -> Int
visibleBackwards as = length . takeWhile ((==headDiff as) .headDiff). filter ((>=2).length) $ tails as
      where headDiff (a:a1:_) = a-a1
            headDiff x        = error $ "Bug: Too short list " ++ show x


inMazeWith :: [(Path, Path)] -> Pos -> Bool
inMazeWith = flip elem . concatMap (\x->snd x ++ fst x)

oneStep :: MonadPlus m => Pos -> Path -> (Pos -> Bool)  -> m Pos
oneStep end (curr:prev:_) inMaze =
  if distance curr end <= 1
     then return end
     else do
    let distance' :: Pos -> Double
        distance' x = fromIntegral (distance x end) + if curr - prev == x - curr then 0 else 0.4
    next <- msum . map return $ sortBy (compare`on`distance') $ neighbors curr

    -- Don't go back
    guard $ next /= prev

    -- Stay in bounds
    guard $ isInBounds next

    let dir = (next - curr)
    let lr = neighbors next \\ [curr,next+dir,end]

    -- If next is blocked, check that the one after that is free
    if inMaze next
      then do
        guard $ not . (\x->(x/=end)&&inMaze x) $ next + dir
        -- Both sides should be blocked as well
        guard $ (==2). length . filter inMaze $ lr
      else do
        -- No neighbors if empty
        guard $ null . filter inMaze $ lr

    -- All neighbors of 'curr', including 'next'
    let neigh' = filter (\i -> inMaze i || i == next) $ neighbors curr
        -- should be an even number
        guard $ even $ length neigh'

    return next
oneStep _ [start] _ = return $ inBounds start
oneStep _ _ _ = error "Too short path given"


toBounds :: (Num a, Eq a) => (a,a) -> a -> a
toBounds (low, high) x
    | x == low  = x + 1
    | x == high = x - 1
    | otherwise = x

distance :: Pos -> Pos -> Int
distance (x1,y1) (x2,y2) = abs(x1-x2)+abs(y1-y2)

-- Moves a pos to the closest one inside the bounds
inBounds :: Pos -> Pos
inBounds = bimap (toBounds (0,21)) (toBounds (0,61))

isInBounds :: Pos -> Bool
isInBounds x = x == inBounds x

neighbors :: Pos -> [Pos]
neighbors pos = [ pos & l %~ p| l <- [_1,_2], p <- [succ,pred]]

paths :: Input -> [(Pos,Pos)]
paths pos = flip unfoldr 'a' $ \x ->
  do (y,_) <- find ((==x).snd) pos
     (z,_) <- find ((==toUpper x).snd) pos
     return ((y,z),succ x)

नमूना उत्पादन, 6 चूहों:

##c###B#####b#######C#######F######################f##########
##   #       #       #######                        ##########
####  ######## ###############################################
#####          ###############################################
##############################################################
##############################################################
##############################################################
##############################################################
##############################################################
##############################################################
##############################################################
##############################################################
##############################################################
##############################################################
#############       ##########################################
############# #####  #########################################
D             #    #     #####################################
##############  ## ##### #####################################
#########      #                 #############################
######### ###### # ##### ####### #############################
####      #      #     # #######                        ######
####E######a##########e#d##############################A######

2
जब bचौराहे पर जाता है eऔर b, क्या वह नहीं दिखता है e? bवहाँ पर लग रहा है t = 11, जो eअभी भी उस गलियारे में रखा जाएगा । क्या मैं कुछ भूल रहा हूँ?
ब्रेनसैट

@BrainSteel हाँ, यह सही है। मेरा उत्तर अमान्य है। मैंने पहले खुद को नोट किया कि मुझे "समय में पीछे" टकरावों के लिए जांच करने की आवश्यकता थी (साथ ही अन्य चूहों के रास्ते पार करने के बाद), लेकिन किसी कारण से मैंने फैसला किया कि इसकी आवश्यकता नहीं थी। : पी
हज़ुले

@BrainSteel मुझे विश्वास है कि मैंने अब उस बग को ठीक कर लिया है।
हज़ुलले

1

हास्केल, 1 चूहा, 681 वर्ण

समस्या को केवल एक चूहे के साथ सभी माज़ों के लिए तुच्छ रूप से हल किया जा सकता है। यह कोड चूहों की किसी भी संख्या के लिए "काम" भी करता है, लेकिन बीच में किसी भी बाधा का पालन नहीं करता है कई चूहों और रास्तों के ।

module Main where
import Control.Lens
import Data.List(unfoldr,find)
import Data.Char(toUpper)
parse=(^@..lined<.>folded.filtered(`notElem`"# "))
main=interact$do i<-(naive=<<).rats.parse;(lined<.>traversed).filtered(==' ').indices (`notElem`i).~'#'
    naive(start,(ex,ey))=start':unfoldr go start' where
     start'=bnds start
     (ex',ey')=bnds(ex,ey)
     go(x,y)
      |(x,y)==(ex',ey')=Nothing
      |x== ex'=ok(x,y`t`ey')
      |otherwise=ok(x`t`ex',y)
     ok z=Just(z,z)
     t x y=if x>y then x-1 else x+1
    bnd(l,h)x |x==l=x+1 |x==h=x-1 |True=x
    bnds=bimap(bnd(0,21))(bnd(0,61))
    rats pos=(`unfoldr`'a')$ \x->
  do (y,_)<-find((==x).snd)pos
     (z,_)<-find((==toUpper x).snd)pos
     return((y,z),succ x)

नमूना उत्पादन:

#######a######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
####### ######################################################
#######                                           ############
#################################################A############

मैं कई चूहों का समर्थन करने की योजना बना रहा हूं, इसलिए मैंने जेनेरिक कोड लिखा, लेकिन मुझे अभी तक इसके लिए एक अच्छा एल्गोरिथ्म नहीं मिला है।

  • parse सभी प्रवेश द्वारों की सूची निकालता है और उनके निर्देशांक के साथ बाहर निकलता है
  • rats वह सूची लेता है और प्रत्येक चूहे के लिए निर्देशांक के जोड़े में परिवर्तित करता है।
  • bnds एक किनारे पर एक समन्वय लेता है और इसे भूलभुलैया के अंदर निकटतम समन्वय के लिए ले जाता है।
  • naive एक शुरुआत और समाप्ति की स्थिति लेता है और उनके बीच एक सरल मार्ग देता है।
  • main फिर सभी सफेद स्थान को '#' के साथ एक पथ में नहीं बदलता है

@ edc65 "... कई चूहों के बीच बाधा "। यह सिर्फ 1 चूहे के लिए एक उत्तर है, जिसे प्रश्न के अनुसार अनुमति दी जाती है।
हज़ुलले

ठीक है मेरी गलती। सिर्फ 1 चूहे के लिए यह सोचना एक अलग चुनौती है। मैं अपनी पिछली टिप्पणियों को हटाने जा रहा हूं
edc65
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.