একটি ইঁদুর ধাঁধা নির্মাণ প্রোগ্রাম


15

আপনাকে একটি গবেষণা সহায়ক হিসাবে নিয়োগ দেওয়া হয়েছে, এবং একটি ছোট প্রোগ্রাম তৈরি করতে বলা হয়েছে যা ইঁদুর ম্যাজগুলি তৈরি করবে। ইঁদুর বাক্সটি সর্বদা 62x22 থাকে এবং ইঁদুরের প্রবেশদ্বার (ক) এবং প্রস্থান (এ) থাকে, (ইনপুট 1) এর মতো:

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

আপনার প্রোগ্রামটি অবশ্যই ইঁদুরের জন্য একটি পথ রেখে ব্লক (#) দিয়ে বাক্সটি পূরণ করবে (আউটপুট 1):

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

এটি আপনার সহজেই মনে হয়! আপনি একটি ছোট প্রোগ্রাম লিখতে শুরু, আত্মবিশ্বাস পূর্ণ। তবে, অধ্যক্ষ বিজ্ঞানী একটি নতুন ধারণা পেয়েছেন - তিনি একই সময়ে দুটি ধাঁধাটি ভুলত্রুটি চালানোর জন্য চান। ডাঃ রতনশনার্টার ব্যাখ্যা করেছেন যে তাদের আলাদা দরজা এবং বিভিন্ন প্রস্থান রয়েছে (ইনপুট ২):

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

ইঁদুরগুলি ক্রস চৌরাস্তা দিয়ে সোজা সরানোর প্রশিক্ষণ দেওয়া হয়েছে তবে টি-ছেদগুলি তাদের আশাহীনভাবে বিভ্রান্ত করে ফেলেছে এবং পরীক্ষাকে অকার্যকর করবে। আপনি যখন আপনার নতুন জটিল কাজটি শুরু করেন যখন ভাল চিকিত্সক একটি চূড়ান্ত প্রয়োজনীয়তার ব্যাখ্যা দেয়: ইঁদুর একে অপরের প্রতি বর্বর হয় তাই যদি তারা একে অপরকে দেখতে পায় তবে একটি ইঁদুরের লড়াই শুরু হবে এবং আপনি উভয়ই নীতিশাস্ত্র বোর্ডের সামনে থাকবেন। আপনি এখন উপলব্ধি করেছেন যে আপনার প্রোগ্রামটি এমন একটি গোলকধাঁধা আউটপুট করা উচিত (আউটপুট 2):

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

ইঁদুর বি চৌরাস্তা পৌঁছানোর সময়, ইঁদুর এ থেকে বেরিয়ে যাওয়ার জন্য করিডোরের উপর দিয়ে ভ্রমণ করবে এবং ইঁদুরের লড়াই এড়ানো যাবে।

নিয়মাবলী:

  • আপনার প্রোগ্রামটিতে (এসটিডিএন বা ফাইল) উপরের মতো একটি ইনপুট পড়তে হবে এবং আউটপুট (এসটিডিআউট বা ফাইল) অনেকগুলি স্থান বাদে একই ডেটা এখন হ্যাশ (#) হবে। আপনি ইনপুট স্ট্রিংয়ের ;পরিবর্তে কোনও একক অক্ষর (যেমন ) প্রতিস্থাপন করতে পারেন \nতবে আউটপুট স্ট্রিংয়ের জন্য এখনও \nঅক্ষর প্রয়োজন । আপডেট

  • একটি ইঁদুরের পথ অবশ্যই একটি অক্ষরের প্রস্থ প্রশস্ত হতে হবে, ক্রস ছেদগুলি ব্যতীত (প্রতিটি স্থানের শূন্য বা দুটি অर्थোগোনালি সংলগ্ন #অক্ষর থাকতে হবে)। প্রতিটি ইঁদুরের অবশ্যই ক্রস চৌরাস্তা বাদে একটি স্পষ্ট একক পথ থাকতে হবে। কোনও টি-ছেদ দেওয়ার অনুমতি নেই।

  • ইঁদুরগুলি একই সাথে প্রকাশিত হয় এবং একটি স্থির হারে চলে যায়। কখনই দুটি বা ততোধিক ইঁদুর একে অপরকে দেখতে না পারা ( #এর মধ্যে আরও একটি অক্ষর ছাড়াই একই কলামে বা সারিতে থাকবে)।

  • যদি কোনও সমাধান সম্ভব না হয় (যেমন সংলগ্ন প্রবেশ পয়েন্ট), মুদ্রণ করুন Impossible\nএবং প্রস্থান করুন।

  • প্রবেশদ্বার এবং প্রস্থানগুলি যে কোনও দিকে থাকতে পারে, তবে সেগুলি কখনও কোণে থাকবে না।

  • (যেমন: একটি মিলেছে অনুপ্রবেশ করে প্রস্থান সংলগ্ন হন ##aA##), ইঁদুর সরাসরি থেকে যেতে পারে না aকরার A। গোলকধাঁধার জায়গার অভ্যন্তরে অবশ্যই একটি ছোট 2 স্পেস করিডোর বিভাগ থাকতে হবে।

  • যে পালাটিতে ইঁদুর তার প্রস্থান পয়েন্টে পৌঁছায় (বা তার পরে যে কোনও সময়), অন্য ইঁদুরের কাছে এটি আর দেখা যায় না।

  • আপনার প্রোগ্রামটি 26 ইঁদুর পর্যন্ত 1, 2 এর জন্য ম্যাজগুলি গণনা করার জন্য ডিজাইন করা যেতে পারে।

  • স্ট্যান্ডার্ড লুফোলগুলি অনুমোদিত নয়।

স্কোর:

আপনার সমাধান সহ, গোলকধাঁধা (এন) আপনার প্রোগ্রামটি কতটা ইঁদুর সমাধান করতে পারে তা মনোনীত করুন। আপনার স্কোরটি এই কোড এন দ্বারা বিভক্ত বাইটগুলিতে আপনার কোডের দৈর্ঘ্য is

দয়া করে আপনার উত্তরে একটি নমুনা আউটপুট অন্তর্ভুক্ত করুন যাতে আমরা দেখতে পারি যে আপনার প্রোগ্রামটি কী উত্পাদন করে।


সম্ভাব্য ইনপুট শুধুমাত্র এক, এ, বি, বি এর অবস্থানের পার্থক্য?
xnor

2 ইঁদুর সংস্করণের জন্য, হ্যাঁ। যদি আপনার প্রোগ্রামটি 3 টি ইঁদুরের জন্য ডিজাইন করা থাকে তবে আপনাকে এ, বি, সি, এ, বি, সি এর সমস্ত সম্ভাব্য অবস্থানগুলি মোকাবেলা করতে হবে।
লজিক নাইট

ইঁদুরগুলি কেবল টি এর অনুভূমিক অংশের সাথে চলতে থাকলে কি টি ছেদ করার অনুমতি রয়েছে?
orp

না, এই ইঁদুরগুলি সহজেই বিভ্রান্ত হয়। কেবল সরল পথ, কনুই বাঁক এবং ক্রস রাস্তার অনুমতি রয়েছে।
লজিক নাইট

@ কারপেট পাইথন কি কোনও প্রবেশদ্বার / প্রস্থানটি কিছুর ধাঁধার কিনার সাথে যে কোনও জায়গায় থাকতে পারে? তারা সংলগ্ন হতে পারে?
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এখনও এই করিডোরের মধ্যে থাকবে। আমি কিছু অনুপস্থিত করছি?
ব্রেইনস্টিল

@ ব্রেনস্টিল হ্যাঁ, এটি সঠিক। আমার উত্তর অবৈধ। আমি আগে নিজেকে লক্ষ্য করেছিলাম যে আমার "সময়ের সাথে পিছনের দিকে" পাশাপাশি (অন্যান্য ইঁদুরের পথগুলি অতিক্রম করার পরে) সংঘর্ষগুলিও পরীক্ষা করা দরকার, তবে কোনও কারণে আমি সিদ্ধান্ত নিয়েছিলাম যে এটির দরকার নেই। : পি
হুজুল

@ ব্রেনস্টিল আমি বিশ্বাস করি যে আমি এখন এই বাগটি ঠিক করেছি।
হুজুল

1

হাস্কেল, 1 ইঁদুর, 681 টি অক্ষর

কেবলমাত্র একটি ইঁদুর দিয়ে সমস্যাটি তুচ্ছভাবে সমাধান করা যেতে পারে ma এই কোডটি ইঁদুরের সংখ্যার জন্যও "কাজ করে" তবে একাধিক ইঁদুর এবং পাথের মধ্যে মিথস্ক্রিয়ায় যে কোনও বাধা রয়েছে তা অনুসরণ করে না ।

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 ইঁদুরের একটি উত্তর, যা প্রশ্ন অনুসারে অনুমোদিত।
Hjulle

ঠিক আছে আমার দোষ। কেবল 1 ইঁদুরের জন্য এটি আলাদা চ্যালেঞ্জের কথা চিন্তা করে। আমি আমার পূর্ববর্তী মন্তব্যগুলি মুছতে চলেছি
edc65
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.