1D होपिंग एरे भूलभुलैया


17

वी टावर से प्रेरित और 2 डी भूलभुलैया माइनस 1 डी से संबंधित है

परिचय

आपका कार्य निर्दिष्ट नियमों का पालन करते हुए एक सरणी भूलभुलैया से बाहर निकलने के लिए सबसे छोटा रास्ता खोजना है।

चुनौती

एक -1 डी सरणी एक साथ n तत्वों से बना एक उलझन के रूप में माना जा सकता है n अंक, जहां सूचकांक के साथ बिंदु कश्मीर के साथ अंक से जुड़ा है कश्मीर + एक [ कश्मीर ] और कश्मीर - एक [ कश्मीर में वन-वे ढंग से]। दूसरे शब्दों में, आप आगे या पीछे वास्तव में कूद कर सकते हैं एक [ कश्मीर सूचकांक के साथ बिंदु से] कदमों कश्मीर । सरणी के सीमा के बाहर एक सूचकांक के साथ अंक भूलभुलैया के बाहर माना जाता है।

इसे समझने के लिए, निम्नलिखित सरणी पर विचार करें,

[0,8,5,9,4,1,1,1,2,1,2]

यदि हम अभी ५ वें तत्व पर हैं, क्योंकि तत्व ४ है, तो हम ९वें तत्व से ४ कदम आगे, या १ तत्व के पीछे ४ कदम आगे बढ़ सकते हैं। यदि हम उत्तरार्द्ध करते हैं, तो हम तत्व 0 के साथ समाप्त होते हैं, जो इंगित करता है कि आगे की चाल संभव नहीं है। यदि हम पूर्व करते हैं, चूंकि 9 वां तत्व 2 है, तो हम 11 वें तत्व की आशा कर सकते हैं, जो फिर से 2 है, और फिर हम फिर से "13 वें तत्व" की आशा कर सकते हैं, जो सीमा से बाहर है। सरणी और भूलभुलैया के लिए एक निकास माना जाता है।

इसलिए यदि हम बीच में तत्व से शुरू करते हैं, भूलभुलैया से बाहर निकलने का एक तरीका 1 कदम पीछे, 4 कदम आगे, 2 कदम आगे और फिर 2 कदम आगे बढ़ रहा है, जिसे सरणी के रूप में व्यक्त किया जा सकता है [-1,4,2,2]। वैकल्पिक रूप से आप इसे उस सरणी के साथ व्यक्त कर सकते हैं [4,8,10,12]जो सभी मध्यवर्ती और अंतिम बिंदुओं के शून्य-आधारित सूचकांक को रिकॉर्ड करती है (1-आधारित सूचकांक भी ठीक है), या बस संकेत [-1,1,1,1],।

कम-इंडेक्स अंत से भूलभुलैया को बचाना भी ठीक है।

पहले नोटेशन का उपयोग करना और एक ही तत्व से शुरू [1,1,1,2,2]करना भी एक समाधान है लेकिन यह इष्टतम नहीं है क्योंकि 4 के बजाय 5 चरण हैं।

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

सरलता के लिए, सरणी में तत्वों की संख्या हमेशा एक विषम संख्या होती है और हम हमेशा बीच में तत्व से शुरू करते हैं।

परीक्षण के मामलों

परीक्षण के मामले आउटपुट के विभिन्न रूपों को दर्शाते हैं, लेकिन आप इन तक सीमित नहीं हैं।

Input
Output

[0,8,5,9,4,1,1,1,2,1,2]
[-1,4,2,2]

[2,3,7,1,2,0,2,8,9]
[2,9] (or [2,-5] or [[2,9],[2,-5]])

[0,1,2,2,3,4,4,4,3,2,2,3,0]
[1,-1,1,1]

[0,1,2,2,4,4,6,6,6,6,6,4,2,1,2,2,0]
[]

ऐनक

  • आप एक समारोह या एक पूर्ण कार्यक्रम लिख सकते हैं।

  • सरणी में केवल nonnegative पूर्णांक होते हैं।

  • आप किसी भी मानक फॉर्म के माध्यम से इनपुट और आउटपुट ले सकते हैं , लेकिन कृपया अपने उत्तर में निर्दिष्ट करें कि आप किस फॉर्म का उपयोग कर रहे हैं।

  • यह , सबसे कम संख्या में बाइट्स जीतती हैं।

  • हमेशा की तरह, डिफ़ॉल्ट कमियां यहां लागू होती हैं।


क्या यह एक नेस्टेड सरणी का उत्पादन करने के लिए ठीक है, भले ही जवाब अनोखा हो? (उदाहरण के लिए [0,8,5,9,4,1,1,1,2,1,2], आउटपुट [[-1,4,2,2]])
बब्बलर

@ बबलर हां, आप नेस्टेड ऐरे को आउटपुट कर सकते हैं।
वीजुन झोउ

क्या रिवर्स ऑर्डर में भागने के रास्ते को वापस करना ठीक है। इसके [1,1,1,-1]बजाय [-1,1,1,1]?
टन हास्पेल

@ टोनहॉस्पेल हां, बस अपने उत्तर में ऐसा ही कहें।
वीजुन झोउ

टेस्ट केस 2 गलत लगता है, क्या आप इसे समझा सकते हैं?
edc65

जवाबों:


3

जावास्क्रिप्ट (ईएस 6), 117 बाइट्स

यदि कोई समाधान मौजूद नहीं है, तो 0-अनुक्रमित मध्यवर्ती और अंतिम बिंदुओं की एक सरणी, या एक खाली सरणी देता है।

a=>(g=(x,p,d=a[x])=>1/d?[d,-d].map(d=>p.includes(X=x+d)||g(X,[...p,X])):o=o==''|o[p.length]?p:o)(a.length>>1,o=[])&&o

इसे ऑनलाइन आज़माएं!

टिप्पणी की गई

a =>                              // given the maze a[]
  (g = (                          // g = recursive function taking:
    x,                            //   x = current position
    p,                            //   p[] = list of visited cells
    d = a[x]                      //   d = value of current cell
  ) =>                            //
    1 / d ?                       // if d is defined:
      [d, -d].map(d =>            //   for d and -d:
        p.includes(X = x + d) ||  //     if the cell at X = x + d was not yet visited,
        g(X, [...p, X])           //     do a recursive call to g() at this position
      )                           //   end of map()
    :                             // else:
      o =                         //   update o:
        o == '' |                 //     if o was empty
        o[p.length] ?             //     or p is shorter than o:
          p                       //       set o to p
        :                         //     else:
          o                       //       let o unchanged
  )(a.length >> 1, o = [])        // initial call to g(), starting in the middle
  && o                            // return o

3

हस्क , 22 बाइट्स

ḟȯ¬€ŀ¹FS+o*!¹⌈½L¹ṁπṡ1ŀ

यदि कोई समाधान मौजूद नहीं है, तो संकेतों की सूची, या एक खाली सूची लौटाता है। इसे ऑनलाइन आज़माएं!

व्याख्या

यह एक ब्रूट-फोर्स सॉल्यूशन है जो -1,0,1बढ़ती लंबाई की सूचियों की जांच करता है , और पहले वाले को रिटर्न देता है जिसके परिणामस्वरूप सरणी से बाहर कूद जाता है। चूंकि यह न्यूनतम लंबाई का है, इसमें 0s शामिल नहीं होंगे।

ḟȯ¬€ŀ¹FS+o*!¹⌈½L¹ṁπṡ1ŀ  Implicit input, say A = [0,1,1]
                     ŀ  Indices of A: [1,2,3]
                 ṁ      Map over them and concatenate:
                  π      Cartesian power
                   ṡ1    of the symmetric range [-1,0,1].
                        Result is B = [[-1],[0],[1],[-1,-1],...,[1,1,1]]
ḟ                       Find the first element of B that satisfies this:
                         Argument is a list, say C = [1,-1].
      F                  Reduce C from the left
             ⌈½L¹        using ceil(length(A)/2) as the initial value
       S+o*!¹            with this function:
                          Arguments are an index of A, say I = 2, and a sign, say S = 1.
           !¹             The element of A at I: 1
         o*               Multiply by S: 1
       S+                 Add to I: 2
                         At the end of the reduction, we have a number I, here 2.
   €ŀ¹                   Is it an element of the indices of A: Yes.
 ȯ¬                      Negate: No.
                        The result is the shortest list C for which I is outside of A.

2

पायथन 3 , 195 188 179 बाइट्स

def f(a):
 v=len(a);x,*s={v//2},[v//2]
 while all(v>b>-1for*c,b in s)*s:s=[x.add(u)or c+[b,u]for*c,b in s for u in[b+a[b],b-a[b]]if{u}-x]
 return[b[1:]for b in s if not-1<b[-1]<v]

इसे ऑनलाइन आज़माएं!

संपादित करें:

  • 9 बाइट्स सहेजे गए all(..)and s => all(..)*s, if u not in x => if{u}-x
    पूर्व के कारनामे boolean * list == int * list, बाद वाले सेट अंतर का उपयोग करते हैं (खाली सेट भी मिथ्या है)।

आउटपुट स्वरूप: मध्यवर्ती और अंतिम बिंदुओं के शून्य-आधारित सूचक के रूप में दिए गए सभी इष्टतम उत्तरों का नेस्टेड सरणी।

उदाहरण के लिए f([0,8,5,9,4,1,1,1,2,1,2]) == [[4, 8, 10, 12]]:।

एल्गोरिथ्म सरल बीएफएस है। पहले से ही आने वाले सूचकांकों को छोड़कर, वें पुनरावृत्ति पर sसभी संभव- iगति के पथ रिकॉर्ड करता है i। ध्यान दें कि विस्तारित स्टार नोटेशन का उपयोग (एब) किया जाता है क्योंकि दोहराया सरणी का उपयोग महंगा है। मैंने पाया कि इस तरह के संकेतन को कुछ व्हाट्सएप भी कम कर सकते हैं यदि सही तरीके से उपयोग किया जाए।

मैंने उपरोक्त समाधान से एक पुनरावर्ती (लेकिन अब) संस्करण बनाया है। दोनों s andऔरor s की जरूरत है, अन्यथा यह काम नहीं करता।

पायथन 3 , 210 बाइट्स

lambda a:[b[1:]for b in g(a,[[len(a)//2]],{len(a)//2})if not-1<b[-1]<len(a)]
g=lambda a,s,x:s and all(-1<b<len(a)for*c,b in s)and g(a,[x.add(u)or c+[b,u]for*c,b in s for u in[b+a[b],b-a[b]]if u not in x],x)or s

इसे ऑनलाइन आज़माएं!


2

हास्केल , 207 202 बाइट्स

5 बाइट्स बीएमओ के लिए धन्यवाद बचा लिया ।

l=length
x!p|i<-h p,d<-x!!i=[p++[x]|x<-[(-d,i-d),(d,i+d)],x`notElem`p]
x?p|i<-h p=i<0||i>=l x
h=snd.last
x#[]=[]
x#p|l(x%p)<1=x#(p>>=(x!))|1>0=x%p
(%)=filter.(?)
f x=(tail.map fst)<$>x#[[(0,l x`div`2)]]

इसे ऑनलाइन आज़माएं!

यह एक ऐसा फंक्शन है, जो एक सूची लेता है Int एक पैरामीटर रूप में और उन रास्तों की एक सूची देता है जहां प्रत्येक पथ सरणी से बाहर निकलने के लिए उठाए गए सापेक्ष कूद की सूची है।

अनगोल्ड संस्करण:

move :: [Int] -> [(Int, Int)] -> [Path]
move xs path = map(\x->path++[x]) $ filter (\s -> s`notElem`path) $ [(-delta, i-delta), (delta, i+delta)]
  where (_,i) = last path
        delta = xs!!i :: Int

outside :: [Int] -> Path -> Bool
outside xs paths = i < 0 || i >= length xs
  where (_,i) = last paths

shortest' :: [Path] -> [Int] -> [Path]
shortest' paths xs | null paths       = []
                   | not (null ready) = ready
                   | otherwise        = shortest' paths' xs
                   where ready  = filter (outside xs) paths
                         paths' = concatMap (move xs) paths

shortest xs = map tail $ map (map fst) $ shortest' [[(0,length xs`div`2)]] xs

2

सी (जीसीसी) , 269 बाइट्स

#define A n){for(printf("%d,",n);i^l[i];i=l[i])printf("%d,",x[i]);break;}if(!u[n]){u[n]=x[m]=n;l[m++]=i;
#define M calloc(r,sizeof(s))
*x,*u,*l,s,m=1,i,j,n,w;main(r,v)char**v;{s=r-1;x=M;u=M;l=M;for(*x=1+s/2;i<m;i++){j=x[i];if(w=atoi(v[j])){n=j+w;if(s<A}n=j-w;if(1>A}}}}

इसे ऑनलाइन आज़माएं!

शुरू में एक पुनरावर्ती बैकट्रैकिंग खोज की कोशिश की, क्योंकि mainपुनरावृत्ति के लिए उपयोग करना हमेशा मजेदार होता है। अंत में हालांकि एक सीधी गैर-पुनरावर्ती चौड़ाई-पहली खोज को छोटा किया जा सकता था, जो कि यह संस्करण है। यह प्रोग्राम इनपुट सरणी को कमांड लाइन के तर्कों के रूप में लेता है, जिसमें कोई ब्रेस नहीं है, उदाहरण 0 8 5 9 4 1 1 1 2 1 2के लिए पहले दिए गए उदाहरण के लिए। इस कार्यक्रम के की एक सूची में लिए आउटपुट दिया जाता है 1-अनुक्रमित , अल्पविराम-सीमांकित सरणी सूचकांकों की सूची को रिवर्स ऑर्डर में, अंतिम, आउट-ऑफ-बाउंड्स / 'एस्केप' सूचकांक से शुरू करता है और इंटरमीडिएट सूचकांकों के माध्यम से वापस काम करता है (यह आउटपुट नहीं करता है केंद्र, सूचकांक शुरू)। कार्यक्रम सरणी के चारों ओर ब्रेसिज़ का उत्पादन नहीं करता है और एक अनुगामी अल्पविराम छोड़ देता है क्योंकि अलग हैprintfकथन बहुत सारे वर्ण लेते हैं। उदाहरण के लिए ऊपर दिए गए पहले परीक्षण उदाहरण से संबंधित आउटपुट है 13,11,9,5,

यदि सरणी भूलभुलैया से कोई भागने का मार्ग नहीं है, तो प्रोग्राम कुछ भी आउटपुट नहीं करता है।

Degolfed और समझाया गया यह नीचे है (पठनीयता के लिए कुछ परिवर्तनों के साथ भारी रूप से विकृत):

int *x, *u, *l, s, m = 1, i, j, n, w;                        //Declare all the state we'll need
int main(r, v) char** v;{                            
    s = r - 1;                                               //s is our actual array size, since v[0] is the program name.
    x = calloc(r, sizeof(int));                              //x is an array that will form our BFS queue. Since it is a BFS we've no need to visit any elements more than once (first visit will have been on a shortest route to it), so the amount of space we have here should suffice.
    u = calloc(r, sizeof(int));                              //u is an array that will be used to flag when an array index has been visited; only reason it's int* is for ease of declaration
    l = calloc(r, sizeof(int));                              //l is an array that will be used parallel to x and stores backpointers in the form of indexes into x, which will be used to construct the actual path once it is found.
    x[0] = 1 + (s/2);                                        //Init the first element in the queue to our center index of the array, adding one because of the program name in v/argv.
    for(; i < m; i++) {                                      //m is the number of elements in our BFS queue. It starts at 1 and grows during iteration; if this loop terminates before finding a path there is none.
        j = x[i];                                            //Current index in the array we are examining
        if (w = atoi(v[j])) {                                //Set w to be the actual array value at the current index (and check that it's nonzero since if it isn't we can't get anywhere from here)
            n = j + w;                                       //Try a move in the positive direction
            if (n > s) {                                     //If the move escapes the array
                for(printf("%d,", n); i ^ l[i]; i = l[i]) {  //Print the location escaped to and then loop back through the backpointers to reconstruct the path. The only backpointer that will point to its own queue index is the starting one, so terminate there.
                    printf("%d,", x[i]);                     //Print each intermediate array index
                }
                break;                                       //Then break the outer for loop and exit.
            }
            if(!u[n]) {                                      //If the jump didn't take us out of the array and we haven't visited where it goes to, add it to the queue.
                u[n] = x[m] = n;                             //m is the current tail of the queue, so put this new location there. Since we're 1-indexed and if n was zero we'd have escaped, we know it isn't so can use it to mark this index as visited also.
                l[m++] = i;                                  //Also set the backpointer for this new queue element to point back to the current index, then increment the tail of the queue.
            }
            n = j - w;                                       //Now the backwards move
            if (n < 1) {                                     //Repeat analogous to the forward case.
                for(printf("%d,", n); i ^ l[i]; i = l[i]) {
                    printf("%d,", x[i]);
                }
                break;
            }
            if (!u[n]) {
                u[n] = x[m] = n;
                l[m++] = i;
            }
        }
    }
}

गोल्फ सी कोड के लिए हमेशा की तरह, संकलन आउटपुट में चेतावनी और नोट्स की एक अनुकूल दीवार शामिल होगी।



1

पर्ल 5 , -ए: 73 बाइट्स

(पुरानी शैली गिनती: 75 बाइट्स, +1के लिए aऔर +1जगह के लिए -//द्वारा -/$/और का उपयोग कर $`के लिए $')

#!/usr/bin/perl -a
use 5.10.0;
@;=$#F/2;$v{$^H=$_}//=push@;,map$'+$_*($F[$^H]//1/!say$').$".$',-//,1for@

STDIN उदा पर एक पंक्ति के रूप में इनपुट सरणी दें 0 8 5 9 4 1 1 1 2 1 2

प्रारंभ बिंदु सहित रिवर्स ऑर्डर में विज़िट किए गए पदों को प्रिंट करता है, फिर क्रैश करता है

अगर कोई समाधान नहीं है तो प्रिंट कुछ भी नहीं

इसे ऑनलाइन आज़माएं!


1

रूबी , 102 बाइट्स

->a{b=[[a.size>>1]];b.map{|x|(v=a[w=x[0]])&&w>=0?[w-v,w+v].map{|j|x.index(j)?0:b<<[j]+x}:(break p x)}}

इसे ऑनलाइन आज़माएं!

एक सरणी के रूप में इनपुट भूलभुलैया बनाता है, निकास पथ को रिवर्स से प्रिंट करके, प्रारंभ से बाहर बिंदु (समावेशी) तक आउटपुट करता है। अगर कुछ बचता नहीं है तो प्रिंट करता है।

यह दृष्टिकोण पथों के इतिहास को संग्रहीत करते हुए एक अस्थायी सरणी के माध्यम से मैप करने के लिए मैप विधि का दुरुपयोग करता है, जो कि उड़ान पर लगातार बढ़ाया जाता है जब भी लेने के लिए एक और संभव कदम होता है।

सिद्धांत रूप में, मैं return xइसके बजाय का उपयोग करके एक और बाइट बचा सकता था break p x, लेकिन इसका मतलब यह होगा कि मेरा मिथ्या मूल्य सभी राक्षसी बकवास के बराबर हैb । शायद, यह बहुत अधिक होगा, यहां तक ​​कि आउटपुट के अनुमत लचीलेपन पर विचार करते हुए ...

पूर्वाभ्यास

->a{
  b=[[a.size>>1]] #Initialize an array of paths with our starting point index
  b.map{|x|       #Iterate through this array
    (v=a[w=x[0]]) #w is the current point in the path, v is its array value
    &&w>=0        #Ruby's support for negative indexing costs us 6 bytes :(
    ?             #If we are still within the bounds of the maze
      [w-v,w+v].map{|j| #Try moving in both directions
        x.index(j)? #If we have been there before, or stuck on zero
        0         #This is a dead-end, just assign a throwaway value
        :b<<[j]+x #Otherwise push the elongated path on top of our iterator
      } 
    :(break p x)  #Escaped! Exit the loop and report the path
  }  
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.