एक अस्सी-कला गैर-प्रतिच्छेदन पथ उत्पन्न करें


18

दिए गए 2 पूर्णांक इनपुट क्षेत्र के आकार का प्रतिनिधित्व करते हैं, xऔर y, क्षेत्र के माध्यम से एक पथ का उत्पादन करते हैं।

उदाहरण के लिए आउटपुट 5, 4:

#    
#    
# ###
### #

पूरा मैदान 5 बाय 4 है, और मैदान को पार करते हुए हैशमार्क से बना एक रास्ता है।

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

रास्तों के नियम हैं:

  • हैशमार्क से बना है

  • हर हैश केवल 2 अन्य हैश से जुड़ा होता है (अर्थात रास्ता अपने आप से अलग नहीं होता है और न ही चलता है)

गैर-हैश रिक्त स्थान को किसी अन्य वर्ण से भरा जा सकता है, लेकिन यह सुसंगत होना चाहिए (अर्थात सभी स्थान, सभी अवधियाँ, आदि)

उदाहरण:

2, 2

##
 #

3, 4

##
 ##
  #
  #

5, 5

#####
    #
    #
    #
    #

6, 5

## ###
 # # #
## # #
# ## #
###  #

7, 9

#######
      #
####  #
#  #  #
#  #  #
#  #  #
#  ####
#
#######

इस तरह का रास्ता स्व-परहेज रैंडम वॉक के समान है, हालांकि यह एक सच्चे SAW के विपरीत खुद के लिए आसन्न नहीं हो सकता है।

पथ निरंतरता और पथ स्पर्श दोनों को विकर्णों के बिना परिभाषित किया गया है।


RBX.Lua आउटपुट स्वरूप मान्य है? ;)
devRicher

क्या यह सही है कि जब तक हर वैध रास्ते को चुने जाने की सकारात्मक संभावना है, तब तक संभावना वितरण मनमाना है?
मृग

@devRicher हाँ
Rɪᴋᴇʀ

@flawr हाँ, यह सही है
Raw

जवाबों:


11

MATLAB, 316 305 300 293 बाइट्स

function P=f(a,b);z(a,b)=0;P=z;c=@(X)conv2(+X,[0,1,0;1,1,1;0,1,0],'s');B=1;while B;P=z;P(1)=1;for K=1:a*b;S=z;S(a,b)=1;for L=2:a*b;S(~S&c(S)&~P)=L;end;[i,j]=find(S&c(P==K));if i;r=randi(nnz(i));else;break;end;P(i(r),j(r))=K+1;if P(a,b);break;end;end;B=any(any(c(P>0)>3));end;P(P>0)=35;P=[P,'']

धन्यवाद @LuisMendo विभिन्न सुझावों के लिए और बाइट्स का एक गुच्छा =)

इसे ऑनलाइन आज़माएं! (वारंटी के बिना: ध्यान दें कि ऑक्टेव पर चलने के लिए इसे समायोजित करने के लिए कुछ समायोजन की आवश्यकता थी: सबसे पहले मुझे हटाने की आवश्यकता थीfunction कीवर्ड और मूल्यों को हार्डकोड , दूसरी बात: रिक्त स्थान Matlab की तरह सही तरीके से मुद्रित नहीं होते हैं। ऑक्टेव के दृढ़ संकल्प आदेशों की जाँच करें, जो अलग तरह से कार्य कर सकते हैं

इनपुट के लिए उदाहरण आउटपुट (7,10)(पहले से ही काफी समय लग सकता है):

#         
#         
##        
 ##       
  #   ### 
  #   # ##
  #####  #

व्याख्या

यह वांछित 4-कनेक्टिविटी के साथ ऊपर से नीचे दाएं बाएं से क्रमिक रूप से पथ उत्पन्न करता है, और फिर उन मापदंडों को अस्वीकार करने के लिए अस्वीकृति नमूनाकरण का उपयोग करता है जो मानदंड का उल्लंघन करते हैं जो आपके पास सहायक भागों नहीं हो सकते।

function P=f(a,b);
z(a,b)=0;                                 % a matrix of zeros of the size of th efield
P=z;                                    
c=@(X)conv2(+X,[0,1,0;1,1,1;0,1,0],'s');  % our convolution function, we always convolute with the same 4-neighbourhood kernel
B=1;
while B;                                  % while we reject, we generate paths:
    P=z;
    P(1)=1;                               % P is our path, we place the first seed
    for K=1:a*b;                          % in this loop we generate the all shortest paths (flood fill) from the bottom right, withot crossing the path to see what fiels are reachable from the bottom left
        S=z;
        S(a,b)=1;                         % seed on the bottom left
        for L=2:a*b;
            S(~S&c(S)&~P)=L;              % update flood front
        end;
        [i,j]=find(S&c(P==K));            % find a neighbour of the current end of the path, that is also reachable from the bottom left
        if i;                             % if we found some choose a random one
            r=randi(nnz(i));
        else;
            break;                        % otherwise restart (might not be necessary, but I'm too tired to think about it properly=)
        end;
        P(i(r),j(r))=K+1;                 % update the end of the current path
        if P(a,b);                        % if we finished, stop continuing this path
            break;
        end;
    end;
    B=any(any(c(P>0)>3));                 % check if we actually have a valid path
end;
P(P>0)=35;                                % format the path nicely
P=[P,''];

ओह और हमेशा की तरह:

बातचीत सफलता की कुंजी है।


19

Befunge, 344 बाइट्स

&v>>>#p_:63p:43g`\!+v>/*53g+\01g:2%2*1-\2/!*63g+\0\:v
 40$ v++!\`g14:p35:\<^2\-1*2%2p10::%4+g00:\g36\g35-1_v
#11^$_83p73v >1+:41g`!#v_$,1+:43g`!#v_@>->2>+00p+141^_
<p1^     vp< ^,g+7g36:<<<<1+55p36:<<<< ^1?0^#7g36g35*
8&p|!++!%9#2g+7g10\*!-g38g10!-g37:g00!!*<>3^
443>:!#v_>>1-::3%1-:53g+00p\3/1-:63g+01p^
^>^>>$#<"#"53g63g7+p41g53g-43g63g-+!#^_

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

जैसा कि उनके MATLAB उत्तर में @flawr का उल्लेख किया गया है, यदि फ़ील्ड का आकार किसी भी गैर-तुच्छ आकार का है तो इसमें कुछ समय लग सकता है। वास्तव में यह एक ऐसी स्थिति में पहुंचना काफी आसान है, जहां वास्तव में इसके खत्म होने का इंतजार करने की कोशिश करने लायक नहीं है, क्योंकि आप समय के अंत तक इंतजार करने की काफी संभावना रखते हैं।

ऐसा क्यों होता है, यह समझने के लिए, यह प्रोग्राम को देखने में मददगार है क्योंकि यह बेफुज के कई "विज़ुअल डीबगर्स" में से एक में निष्पादित हो रहा है। चूंकि डेटा और कोड Befunge में समान हैं, इसलिए आपको समय के साथ बदलाव के साथ मार्ग देखने को मिलेगा। उदाहरण के लिए, यहां एक छोटा एनीमेशन दिखाया गया है जिसमें धीमे रास्ते पर चलने वाला भाग कैसा दिख सकता है।

पथ निर्माण को दिखाने वाला एनिमेशन खुद को एक कोने में फंस गया है

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

नीचे पंक्ति: यदि यह एक लंबा समय लगता है, तो संभवतः निष्पादन को समाप्त करना और फिर से शुरू करना एक अच्छा विचार है।

व्याख्या

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

यह स्टैक को संभावित निर्देशांक के साथ आबाद करके काम करता है जिसे हम अनुसरण करना चाहते हैं। फिर हम स्टैक से एक सेट खींचते हैं और जांचते हैं कि क्या यह उपयुक्त है (यानी सीमा में और मौजूदा पथ के साथ अतिव्यापी नहीं)। एक बार जब हमें एक अच्छा स्थान मिल जाता है, तो हम #उस स्थान पर प्लेफील्ड में लिखते हैं , और उन विवरणों को स्टैक में जोड़ते हैं, जिन्हें हमें बाद में पीछे करने की आवश्यकता होती है।

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

यह वह कोड है जो हाइलाइट किए गए विभिन्न घटक भागों के साथ दिखता है:

निष्पादन पथ के साथ स्रोत कोड हाइलाइट किया गया

*क्षेत्र की चौड़ाई और ऊंचाई पढ़ें, और 0एक बैक मार्कर स्थान के बजाय संभावित मार्ग को इंगित करने के लिए एक प्रकार मार्कर के साथ प्रारंभ निर्देशांक को धक्का दें ।
*बैकट्रैकिंग स्थानों (एक 1प्रकार के मार्कर द्वारा इंगित ) के लिए जांचें जो एक साधारण pकमांड के साथ वापस किए जाते हैं, क्योंकि वे प्लेफील्ड में वापस स्पेस लिखने के लिए आवश्यक सटीक प्रारूप में संग्रहीत होते हैं।
*जांचें कि क्या निर्देशांक अभी भी प्लेफील्ड के अंदर हैं। यदि वे सीमा से बाहर हैं, तो उन्हें अगले संभावित निर्देशांक की कोशिश करने के लिए स्टैक और लूप से छोड़ दें।
*यदि वे सीमा में हैं, तो स्टैक से अगले दो मान प्राप्त करें, जो पिछले चरण का स्थान है (इसके बाद होने वाले परीक्षण में आवश्यक)।
*जांचें कि क्या निर्देशांक पथ के मौजूदा खंड के संपर्क में आने वाले हैं। पिछले चरण के स्थान को स्पष्ट रूप से इस चेक से अनदेखा किया गया है।
*यदि सभी परीक्षण सफल होते हैं, #तो प्लेफील्ड में लिखें , और जांचें कि क्या हम गंतव्य स्थान पर पहुंच गए हैं।
*अगर हमारे पास है, तो अंतिम रास्ता लिखें, *और बाहर निकलें।
*अन्यथा 1बाद में बैकट्रैकिंग के लिए एक प्रकार के मार्कर के साथ स्टैक पर निर्देशांक को सहेजें ।
*यह एक यादृच्छिक संख्या गणना के साथ बाधित है जिसे हम जल्द ही लेने जा रहे हैं।
*चार संभावित गंतव्यों को धक्का दें जो वर्तमान स्थान से पहुंचा जा सकता है। यादृच्छिक संख्या उस क्रम को निर्धारित करती है जिसमें वे धकेल दिए जाते हैं और इस प्रकार वे आदेश का पालन किया जाएगा।
* मुख्य लूप की शुरुआत में वापस लपेटें और स्टैक पर अगले मानों को संसाधित करें।


2
पवित्र गाय। स्पष्टीकरण?
R

@EasterlyIrk इनाम के लिए धन्यवाद। अत्यन्त सराहनीय।
जेम्स होल्डरनेस

खुशी है कि यह उपयोगी था!
R

2

QBasic, 259 बाइट्स

मुझे यकीन है कि प्यार GOTOएस

RANDOMIZE TIMER
INPUT w,h
DO
CLS
x=1
y=1
REDIM a(w+3,h+3)
2a(x+1,y+1)=1
LOCATE y,x
?"#"
d=INT(RND*4)
m=1AND d
x=x+m*(d-2)
y=y-d*m+m+d-1
c=a(x,y+1)+a(x+2,y+1)+a(x+1,y)+a(x+1,y+2)=1
IF(x=w)*c*(y=h)GOTO 9
IF(x*y-1)*x*y*c*(x<=w)*(y<=h)GOTO 2
LOOP
9LOCATE y,x
?"#"

मूल रणनीति: प्रत्येक चरण पर, #वर्तमान स्थान पर प्रिंट करें और यादृच्छिक दिशा में आगे बढ़ें। a0s और 1s की एक सरणी ट्रैक रखती है कि हम कहाँ हैं। यदि कदम कानूनी है और हमें अंतिम बिंदु पर ले जाता है, GOTO 9तो लूप से बाहर निकलने और अंतिम प्रिंट करने के लिए #। और, यदि यह कदम कानूनी है, तो एक और कदम उठाएं। और, स्क्रीन को साफ़ करें और शुरू करें (एक बैकग्राउंड एल्गोरिथ्म कोडिंग की तुलना में बहुत अधिक गोल्फर!)।

QB64 में मेरे लैपटॉप पर परीक्षण किया गया, यह आम तौर पर 9, 9पांच सेकंड या उससे कम समय के लिए परिणाम देता है। रन 10, 10तीन और 45 सेकंड के बीच कहीं भी ले गए। सैद्धांतिक रूप से, सभी कानूनी रास्तों में गैर-शून्य संभावना होती है, लेकिन बड़े वक्रों वाले मार्ग की संभावना गायब हो जाती है। मैंने कभी-कभी एक या दो छोटे वक्रों के साथ पथ देखे हैं, हालांकि:

नमूना पथ

अनुरोध पर उपलब्ध अनप्लग्ड संस्करण और / या गहराई विवरण।


2

आर, 225 बाइट्स

function(x,y){library(igraph);a=matrix(rep(" ",x*y),c(y,x));g=make_lattice(c(y,x));w=runif(ecount(g));for (i in 1:2){v=shortest_paths(g,1,x*y,weights=w)$vpath[[1]];w[]=1;w[E(g)[v%--%v]]=0;};a[v]="#";cat(rbind(a,"\n"),sep="")}

स्पष्टीकरण:

हम एक नियमित (जाली) उत्पन्न करते हैं [x * y] किनारों पर रैंडम वेगेट्स के साथ अप्रत्यक्ष ग्राफ तो हम शुरू से अंत तक सबसे छोटा रास्ता पाते हैं। हालाँकि उत्पन्न पथ में ऐसी कोशिकाएँ हो सकती हैं जिनमें उदाहरण के लिए दो से अधिक निगबोर हों:

#
#
####
  ##
  #
  ###

इसलिए हमें दो बार सबसे छोटा पथ एल्गोरिथम लागू करना चाहिए। दूसरी बार में हम सभी वेट को 1 पर सेट करते हैं, सिवाय उन लोगों के जो मौजूदा पाया पथ में 0 पर सेट हैं;

परिणाम

#
#
### 
  # 
  #
  ###

Ungolfed:

function(x,y){
    library(igraph);#igraph library should be installed
    a=matrix(rep(" ",x*y),c(y,x));#ASCII representation of the graph
    g=make_lattice(c(y,x));# regular graph
    w=runif(ecount(g));#weights
    for (i in 1:2){
        #find vertices that are in the path
        v=shortest_paths(g,1,x*y,weights=w)$vpath[[1]];
        #set all weights to 1 except those that are in the current found path that set to 0
        w[]=1;
        w[E(g)[v%--%v]]=0;
    }
    a[v]="#";
    cat(rbind(a,"\n"),sep="")
}

1

जावास्क्रिप्ट (ईएस 7), 333 331 330 329 324 318 312 बाइट्स

f=
(h,w,c=[...Array(h)].map(_=>Array(w).fill` `),g=a=>{for(z of b=[[[h-1,w-1]]])a.map(([x,y])=>b.every(([[i,j]])=>i-x|j-y)&(z[0][0]-x)**2+(z[0][1]-y)**2<2&&b.push([[x,y],...z]));return b.find(([[x,y]])=>!x&!y)||g([...a,[h,w].map(n=>Math.random()*n|0)])})=>g([]).map(([x,y])=>c[x][y]=`#`)&&c.map(a=>a.join``).join`
`
Height: <input type=number min=1 id=h>Width: <input type=number min=1 id=w><input type=button value="Generate!" onclick=o.textContent=f(+h.value,+w.value)><pre id=o>

विस्तार: #किसी सरणी में बेतरतीब ढंग से रखा जाता है जब तक कि एक मार्ग को पहले-पहले खोज का उपयोग करके फ़ील्ड के माध्यम से नहीं पाया जाता है; पहला, और इसलिए सबसे छोटा, ऐसा रास्ता फिर आउटपुट है; यह इस बात की गारंटी देता है कि रास्ता खुद को नहीं काटता है। ध्यान दें कि विशेष रूप से बड़े क्षेत्रों के लिए एक पथ मिलने से पहले JS इंजन के स्टैक से अधिक संभव है। Ungolfed:

function r(n) {
    return Math.floor(Math.random() * n);
}
function f(h, w) {
    var a = []; // array of placed #s
    var b; // breadth-first search results
    var c;
    do {
        a.push([r(h), r(w)]); // place a # randomly
        b = [[[h - 1, w - 1]]]; // start from bottom right corner
        for (z of b) // breadth-first search
            for ([x, y] of a) // find possible next steps
                if (!b.some(([[i, j]]) => i == x && j == y))
                    if ((z[0][0] - x) ** 2 + (z[0][1] - y) ** 2 < 2)
                        if (x || y)
                            b.push([[x, y], ...z]); // add to search
                        else if (!c)
                            c = [[x, y], ...z]; // found path
    } while (!c);
    a = [...Array(h)].map(() => Array(w).fill(' '));
    for ([x, y] of c) // convert path to output
        a[x][y] = '#';
    return a.map(b => b.join('')).join('\n');
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.