नॉनोग्राम लाइन ब्रूट-फोर्स सॉल्विंग


25

पृष्ठभूमि

नॉनोग्राम , जिसे पिक्रोस या ग्रिडलर्स के रूप में भी जाना जाता है, एक पहेली है जहां उद्देश्य यह निर्धारित करना है कि प्रत्येक पंक्ति पर लगातार रंगीन कोशिकाओं की संख्या का उपयोग करके 2 डी ग्रिड पर प्रत्येक सेल को रंगीन या खाली छोड़ दिया जाना चाहिए।

निम्नलिखित समाधान के साथ एक उदाहरण नॉनोग्राम पहेली है।

समस्या यह है कि कुछ व्यावसायिक नॉनोग्राम गेम्स / मोबाइल ऐप में ऐसी पहेलियां होती हैं जो हाथ से हल करने योग्य नहीं होती हैं (जैसे कई समाधान होते हैं, या गहरी बैकट्रैकिंग की आवश्यकता होती है)। हालांकि, वे खिलाड़ी को कुछ जीवन भी प्रदान करते हैं, जहां एक जीवन खो जाता है जब आप एक सेल को रंगने की कोशिश करते हैं जिसका सही उत्तर रिक्त है । तो अब उन बुरा "पहेली" को पाटने का समय है!

कार्य को सरल बनाने के लिए, इसके सुराग के साथ सिर्फ एक पंक्ति की कल्पना करें और कुछ नहीं:

3 7 | _ _ _ _ _  _ _ _ _ _  _ _ _ _ _

[3,7]सुराग हैं, और लाइन की लंबाई 15 कोशिकाओं है। चूंकि इसके कई संभावित समाधान हैं, हमें इस लाइन को पूरी तरह से हल करने के लिए कुछ जीवन को जोखिम में डालने की आवश्यकता है (अर्थात सभी रंगीन कोशिकाओं को निर्धारित करें)।

चुनौती

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

ध्यान दें कि आप हमेशा रंगीन कोशिकाओं का अनुमान लगाते हैं । वास्तविक खेलों में, खाली कोशिकाओं (या तो सही या गलत) का अनुमान लगाने से आपके जीवन पर कोई प्रभाव नहीं पड़ता है, इसलिए आप इस तरह से पहेली को "हल" नहीं कर सकते हैं।

इसके अलावा, आप यह मान सकते हैं कि इनपुट हमेशा एक वैध नॉनोग्राम रेखा का प्रतिनिधित्व करता है, इसलिए आपको किसी चीज़ के बारे में चिंता करने की आवश्यकता नहीं है [6], 5

व्याख्या

आइए पहले कुछ सरल उदाहरण देखें।

[1,2], 5

इस लाइन के लिए तीन संभावनाएं हैं ( Oएक रंगीन सेल है, .एक खाली है):

O . O O .
O . . O O
. O . O O

यदि हम रंग 0 सेल करने की कोशिश करते हैं (बाएं से 0-आधारित सूचकांक), तो निम्न में से एक होता है:

  • सेल सही ढंग से रंगीन है। अब हमारे पास दो संभावनाएं हैं, और हम पूरी तरह से लाइन को हल करने के लिए सेल 2 और सेल 4 के बीच चयन कर सकते हैं। किसी भी मामले में, हम सबसे खराब स्थिति में एक जीवन खो देंगे।
  • सेल खाली है, और हम एक जीवन खो देते हैं। इस मामले में, हमने पहले ही इस रेखा के लिए अद्वितीय समाधान की पहचान कर ली है, इसलिए हम 1 जीवन खो चुके हैं।

इसलिए, [1,2], 51 का उत्तर है।

[5], 10

द्विआधारी खोज? नहीं।

सबसे स्पष्ट पहली पसंद 4 या 5 है, जो रिक्त होने पर (1 जीवन की लागत पर) एक संभावना को प्रकट करेगी। मान लीजिए कि हमने पहले 4 को चुना। यदि सेल 4 वास्तव में रंगीन है, तो हम इसे बाईं ओर बढ़ाते हैं, अर्थात 3, 2, 1 और 0 का प्रयास करें जब तक कि एक जीवन खो नहीं जाता है (या सेल 0 रंगीन है, तो हम कोई भी जीवन नहीं बिताते हैं)। जब भी कोई जीवन खो जाता है, तो हम समाधान को विशिष्ट रूप से निर्धारित कर सकते हैं, जैसे कि अगर हम कुछ ऐसा देखते हैं:

_ _ X O O _ _ _ _ _

तो हम पहले से ही जवाब पता है:

. . . O O O O O . .

इसलिए, का उत्तर [5], 10भी 1 है।

[3,7], 15

सेल 11 से शुरू करें, जो खाली होने पर, निम्न समाधान को तुरंत प्रकट करेगा।

O O O . O O O O O O O X . . .

फिर 12 का प्रयास करें, जो खाली होने पर, दो संभावनाएं देता है जिन्हें 1 अतिरिक्त जीवन की कीमत पर हल किया जा सकता है।

O O O . . O O O O O O O X . .
. O O O . O O O O O O O X . .

अब प्रयास करें 2. यदि खाली है, तो यह तीन संभावनाओं की ओर जाता है जिसे [1,2], 5उदाहरण के समान हल किया जा सकता है ।

. . X O O O . O O O O O O O .
. . X O O O . . O O O O O O O
. . X . O O O . O O O O O O O

यदि आप इस तरीके से जोखिम कम से कम रखते हैं, तो आप अधिकतम के साथ किसी भी समाधान तक पहुंच सकते हैं। 2 जीवन बिताया।

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

[1,2] 5 => 1
[2] 5 => 2
[1] 5 => 4
[] 5 => 0
[5] 10 => 1
[2,1,5] 10 => 0
[2,4] 10 => 2
[6] 15 => 2
[5] 15 => 2
[4] 15 => 3
[3,7] 15 => 2
[3,4] 15 => 3
[2,2,4] 15 => 4
[1,1,1,1,1,1,1] 15 => 2

[2,1,1,3,1] 15 => 3
[1,1,1,2,1] 15 => 5

पिछले दो मामलों के लिए, इष्टतम रणनीति न्यूनतम रिक्त स्थान से नहीं गुजर रही है, लेकिन बस बाएं से दाएं (या दाएं से बाएं) जा रही है। इसे इंगित करने के लिए @crashoz को धन्यवाद।

नियम

मानक नियम लागू होते हैं। बाइट्स में सबसे कम वैध जमाव जीतता है।

इनाम

यदि कोई बहुपद-कालिक एल्गोरिथ्म (शुद्धता के प्रमाण के साथ) के साथ आता है, तो मैं इस तरह के समाधान के लिए +100 इनाम देगा।


के लिए इरादा उत्पादन क्या है [6], 5?
लीक नून

जब आप एक अनुमान लगाते हैं, तो क्या आपको यह अनुमान लगाना होगा कि सेल काला है, या आप काले या सफेद का अनुमान लगा सकते हैं?
feersum

@LeakyNun यह एक अमान्य रेखा है। आप मान सकते हैं कि इनपुट हमेशा एक वैध नॉनोग्राम लाइन है।
बब्लर

@ फैर्सम आप हमेशा रंगीन कोशिकाओं का अनुमान लगाते हैं। वास्तविक खेलों में, एक खाली सेल (या तो सही या गलत) का अनुमान लगाने से आपके जीवन पर कोई प्रभाव नहीं पड़ता है, इसलिए आपको इसके साथ कोई प्रतिक्रिया नहीं मिल सकती है।
बब्लर

शानदार चुनौती
एनरिको बोरबा

जवाबों:


19

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

f=->l,n,s=n-l.sum-l.size+1{*a,b=l;b&&s>0?(a[0]?1+f[a,n-b-2,s-1]:(n.to_f/b).ceil-1):0}

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

व्याख्या

l=[l1,l2,...,lx]xn

lx
nlx
nlx1+f(l,nlx)
1+f(l~,nlx2)l~l

f(l,n)={0,if 1xli+x1nnlx1if x=11+max{f(l,nlx)f(l~,nlx2),otherwise

यहां एक उदाहरण _अज्ञात है, Xएक ज्ञात स्थान है, Oएक ज्ञात रंगीन सेल है और Lजीवन खो गया है

[2,2,4] 15                  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
(1) -> [2,2,4] 11           _ _ _ _ _ _ _ _ _ _ _ L X X X
    (1) -> [2,2,4] 7        _ _ _ _ _ _ _ L X X X L X X X
        0                   X X X L X X X L X X X L X X X
    (2) -> [2,2] 5          _ _ _ _ _ X O O O O L L X X X
        0                   O O X O O X O O O O L L X X X 
(2) -> [2,2] 9              _ _ _ _ _ _ _ _ _ X O O O O L
    (1) -> [2,2] 7          _ _ _ _ _ _ _ L X X O O O O L
        (1) -> [2,2] 5      _ _ _ _ _ L X L X X O O O O L
            0               O O X O O L X L X X O O O O L
        (2) -> [2] 3        _ _ _ X O O L L X X O O O O L
            1               O O L X O O L L X X O O O O L               
    (2) -> [2] 5            _ _ _ _ _ X O O L X O O O O L
        2                   O O L L X X O O L X O O O O L

यह एक द्विआधारी पेड़ बनाता है, खोए हुए जीवन की संख्या प्राप्त करने के लिए, हमें बस पेड़ की अधिकतम ऊंचाई की गणना करने की आवश्यकता है। हालाँकि यह इसे बनाता है क्योंकि हम सभी शाखाओं का मूल्यांकन करते हैं। हम बेहतर कर सकते हैं।O(2n)

चलो एक लागत समारोह को परिभाषित हमें "का चयन करें" हर कदम पर सही शाखा में मदद मिलेगी।h

h(l,n)=n1xlix+1

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

परिभाषा के अनुसार , हमारे पास h

h(l,nlx)=nlx1xlix+1=(n1xlix+1)lx=h(l,n)lx

और,

h(l~,nlx2)=nlx21x1li(x1)+1=(n1xlix+1)1=h(l,n)1

फिर,

h(l,n)={0,if 1xli+x1nnlx,if x=1max{h(l,nlx)+lxh(l~,nlx2)+1,otherwise

हम सबसे खराब स्थिति प्राप्त करने के लिए प्रत्येक चरण में को अधिकतम करना चाहते हैं ताकि चलो पुनरावृत्ति में दो अभिव्यक्तियों के बीच अंतर की जांच करेंh

[h(l,nlx)+lx][h(l~,nlx2)+1]=nlxn1xlix+1+lx[nlx21x1li(x1)+1+1]=2

[h(l,nlx)+lx][h(l~,nlx2)+1]=2[h(l,nlx)+lx][h(l~,nlx2)+1]<0[h(l,nlx)+lx]<[h(l~,nlx2)+1]
इसलिए द्वितीय भाव हमेशा अधिकतम होता है, हम पहले वाले को हटा सकते हैं

h(l,n)={0,if 1xli+x1nnlx,if x=1h(l~,nlx2)+1otherwise

अंत में की यह पुनरावर्ती परिभाषा हमें दिखाती है कि फ़ंक्शन में विकल्प (2) हमेशा सबसे खराब स्थिति है (अधिकतम संभावनाओं की संख्या दे रहा है अर्थात अधिकतम )hfh

f(l,n)={0,if 1xli+x1nnlx1if x=11+f(l~,nlx2),otherwise

हर कदम हम को कम से कम 3 से कम करते हैं और अब एक एकल पुनरावर्ती कॉल है, जटिलताnO(n)


2
PPCG, अविश्वसनीय पहली पोस्ट में आपका स्वागत है!
कोल

1
@cole यह उनकी पहली पोस्ट नहीं है, लेकिन यह निश्चित रूप से अविश्वसनीय है! बहुत चतुर दृष्टिकोण +1
श्री एक्सकोडर

1
अद्भुत कार्य। मैं इनाम 2 दिन बाद दूंगा, अगर किसी को तब तक कोई गंभीर तार्किक दोष नहीं मिलता है।
बब्बलर

2

पायथन, 303 289 बाइट्स

लंबे समय में पहला गोल्फ, इसलिए बहुत अधिक वसा हो सकता है। ( 14 बाइट्स-मूल्य खोजने के लिए धन्यवाद जो किंग ।)

फंक्शन एफ सभी संभावित व्यवस्थाओं को उत्पन्न करता है (हालांकि हमेशा पहले चरित्र के रूप में एक रिक्त के साथ, लेकिन जब तक हम इसे कहते हैं, तब तक यह ठीक है जब तक हम 1 से लंबाई बढ़ाते हैं)। फ़ंक्शन जी रिक्त स्थान को कम से कम संख्या और पुनरावृत्ति के साथ चुनता है। समारोह एच उन्हें एक साथ रखता है।

f=lambda l,n:["."*i+"X"*l[0]+c for i in range(1,n-l[0]+1)for c in f(l[1:],n-i-l[0])]if l else["."*n]
def g(q,n):O,X=min([[[p[:i]+p[i+1:]for p in q if p[i]==u]for u in".X"]for i in range(n)],key=lambda x:len(x[0]));return(len(q)>1)*1and max(1+g(O,n-1),g(X,n-1))
h=lambda l,n:g(f(l,n+1),n+1)

सभी उदाहरण ठीक चलते हैं:

>>> h([3,7],15)
2
>>> h([3,4],15)
3
>>> h([1,1,1,2,1],15)
6


1
आप वापस जाने के लिए अनुमति दी जाती है Falseके लिए 0? यदि हां, तो आप बदल सकते हैं (len(q)>1)*1andकरने के लिए len(q)>1and। आप लौटने की अनुमति नहीं कर रहे हैं Falseके लिए 0है, तो उस करते हैं, लेकिन परिवर्तन g(f(l,n+1),n+1)करने के लिए 1*g(f(l,n+1),n+1)है और यह अभी भी एक बाइट बचाने
Zachary

1
इससे भी बेहतर: मामले में बदलने की Falseअनुमति नहीं है , इसे बदलने के लिए0g(f(l,n+1),n+1)1*g(f(l,n+1),n+1)+g(f(l,n+1),n+1)
Zacharý

2
इसके अलावा, आपको h=अपने बाइट की गिनती गिनने की जरूरत नहीं है
Zacharý

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.