एन-क्वीन-एंड-इक्विन क्वीन


21

एक अच्छी तरह से ज्ञात एन-क्वीन समस्या का एक प्रकार है जिसमें क्वीन और नाइट शामिल हैं और कहा जाता है कि "काफी अधिक कठिन" 1 । समस्या कथन इस प्रकार है:

आपको एक समान संख्या में शूरवीरों और रानियों को शतरंज की चौकी पर रखना होगा, ताकि कोई टुकड़ा किसी अन्य टुकड़े पर हमला न करे। टुकड़ों की अधिकतम संख्या क्या है जो आप बोर्ड पर रख सकते हैं, और आप इसे कितने अलग-अलग तरीकों से कर सकते हैं?

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

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

ध्यान दें कि:

  • कार्यक्रमों के अनुक्रम को एक ही बोर्ड को दो बार वापस नहीं करना चाहिए, आकार n की समस्या के लिए सभी संभावित समाधानों को कवर करना होगा और अंततः समाप्त करना होगा (कोई आउटपुट नहीं)।
  • आप या तो दो मान वापस कर सकते हैं, एक लौटा सकते हैं और दूसरे को प्रिंट कर सकते हैं, या दो रिटर्न मान प्रिंट कर सकते हैं।
  • हालाँकि , यदि आप बोर्ड और अगले प्रोग्राम दोनों को प्रिंट करते हैं, तो बोर्ड को अगले प्रोग्राम का हिस्सा नहीं माना जाना चाहिए (मैं टिप्पणी में बोर्ड को प्रिंट करने की सलाह दूंगा, या दोनों मानक आउटपुट और त्रुटि धाराओं का उपयोग करूंगा)।
  • प्रोग्राम-ए-ए-रिटर्न-वैल्यू स्ट्रिंग होना चाहिए, न कि क्लोजर।

बोर्ड का प्रारूप

  • एक बोर्ड आकार n का एक वर्ग है ।
  • एक बोर्ड सेल खाली हो सकता है, एक रानी या एक नाइट।
  • आपको प्रत्येक प्रकार की कोशिकाओं के लिए अलग-अलग मानों का चयन करना होगा (यानी आप बोर्ड को प्रिंट करते समय क्यू, एन के अलावा अन्य प्रतीकों का उपयोग कर सकते हैं)।
  • आप एक गैर स्ट्रिंग बोर्ड वापस करते हैं, यह एक होना चाहिए आदेश दिया के संग्रह एन 2 बोर्ड के मूल्यों (जैसे मैट्रिक्स, वेक्टर या पंक्ति / स्तंभ-प्रमुख क्रम में सूची, ...)।
  • यदि आप बोर्ड को प्रिंट करते हैं, तो आप या तो इसे मुद्रित कर सकते हैं, या एक पंक्ति के रूप में। उदाहरण के लिए, आकार 4 का एक समाधान बोर्ड निम्नानुसार मुद्रित किया जा सकता है (रिक्त स्थान की आवश्यकता नहीं है; आपके विवेक पर प्रतीक):

    Q - - -
    - - - -
    - - - -
    - - N -
    

    यदि आप ऐसा महसूस करते हैं, तो आप आउटपुट भी कर सकते हैं:

    ♛ · · ·
    · · · ·
    · · · ·
    · · ♞ ·
    

    ... लेकिन यह पर्याप्त है:

    Q-------------N-
    

    इससे कोई फर्क नहीं पड़ता कि आप पंक्ति-प्रमुख या स्तंभ-प्रमुख क्रम में कोशिकाओं के माध्यम से पुनरावृति करते हैं, क्योंकि सममित समाधान हैं। उदाहरण के लिए, n = 4 के लिए समाधान हैं:

    Q------N--------
    Q----------N----
    Q------------N--
    Q-------------N-
    -Q----------N---
    -Q------------N-
    -Q-------------N
    --Q---------N---
    --Q----------N--
    --Q------------N
    ---QN-----------
    ---Q----N-------
    ---Q---------N--
    ---Q----------N-
    ---NQ-----------
    ----Q------N----
    ----Q----------N
    N------Q--------
    -------QN-------
    -------Q----N---
    ---N----Q-------
    -------NQ-------
    --------Q------N
    N----------Q----
    ----N------Q----
    -----------QN---
    -N----------Q---
    --N---------Q---
    -------N----Q---
    -----------NQ---
    N------------Q--
    --N----------Q--
    ---N---------Q--
    N-------------Q-
    -N------------Q-
    ---N----------Q-
    -N-------------Q
    --N------------Q
    ----N----------Q
    --------N------Q
    

आप मेट्रिसेस के रूप में n = 5 के लिए समाधान भी देख सकते हैं ; बोर्डों में शामिल हैं #, qऔर nप्रतीक, जो विभिन्न प्रकार की खाली कोशिकाएं हैं (नीचे मेरा उत्तर देखें)। मैं n = 6 के लिए 2836 बोर्डों की गणना करता हूं , जैसे कि स्लिफ़र के उत्तर में (मैंने बाइट की गिनती को कम करते समय एक बग पेश किया, लेकिन यह अब तय हो गया है)।

मेरे कोड में एक नहीं बल्कि दो बग ढूंढने के लिए स्लिफ़र को बहुत धन्यवाद।

स्कोर

बाइट्स में सबसे छोटा कोड जीत जाता है।

हम पहले कार्यक्रम के आकार को मापते हैं, जो एन स्वीकार करता है ।


क्वीर और शूरवीर , रोजर केडब्ल्यू हुई द्वारा (सावधान! एक समाधान शामिल है)


4
हो सकता है कि आपको इस पर एक इनाम देना चाहिए। ईमानदारी से, समस्या क्वीन भाग के बिना काफी कठिन है।
mbomb007 21

क्या हम क्वींस और नाइट्स को खाली करने के लिए क्यू, एन और - के अलावा किसी भी प्रतीक का उपयोग कर सकते हैं और खाली है, जब तक कि वे अलग हैं?
१६:५० पर घातक

@Fatalize हाँ, यकीन है कि
coredump

1
@ मेरे काम का मतलब है कि मैं फंक्शन की सामग्री को पढ़ रहा हूं। और मैं इसे "हां" के रूप में ले सकता हूं, आपको अपने स्वयं के स्रोत कोड और / या फ़ंक्शन सामग्री को पढ़ने की अनुमति है। (मेरा समाधान इस पर निर्भर करता है, इसलिए ...)
wizzwizz4

1
@coredump यदि मैं चुनौती को सही ढंग से समझता हूं, तो n = 6 के लिए आपके संदर्भ समाधान में अमान्य प्रविष्टियाँ हैं (जैसे -------------------------N--------Q-कि अमान्य है क्योंकि अधिक टुकड़े जोड़े जा सकते हैं :) Q--------N---------------N--------Q-
स्लिफ़र

जवाबों:


2

ग्रूवी, 515 बाइट्स

X=0;Y="N="+args[0]+";M=N*N;S=[];def f(b,i,j,v){(i..<j).findAll{k->!(0..<M).any{l->w=b[l];r=(k.intdiv(N)-l.intdiv(N)).abs();c=(k%N-l%N).abs();s=v+w;w>0&&(k==l||(r==0||c==0||r==c?s<4:r<3&&c<3&&s>2))}}.collect{a=b.clone();a[it]=v;[it,a]}};def r(b,q,n){f(b,q,M,1).each{i->f(i[1],n,M,2).each{j->if(f(j[1],0,M,1).any{f(it[1],0,M,2)}){r(j[1],i[0],j[0])}else{S.add(j[1])}}}};r(new int[M],0,0);if(x<S.size()){sprintf('//%s%cX=%d;Y=%c%s%c;print(Eval.xy(X,Y,Y))',S[x].toString(),10,x+1,34,y,34)}else{''}";print(Eval.xy(X,Y,Y))

परिक्षण

N कमांड लाइन तर्क के रूप में प्रदान करें :

groovy qak.groovy 4

आउटपुट की पहली पंक्ति हमेशा एक टिप्पणी (0 = खाली, 1 = रानी, ​​2 = नाइट) के रूप में एक समाधान होती है, इसके बाद दूसरी पंक्ति में कोड होता है:

//[1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0]
X=1;Y="N=4;M=N*N;S=[];def f(b,i,j,v){(i..<j).findAll{k->!(0..<M).any{l->w=b[l];r=(k.intdiv(N)-l.intdiv(N)).abs();c=(k%N-l%N).abs();s=v+w;w>0&&(k==l||(r==0||c==0||r==c?s<4:r<3&&c<3&&s>2))}}.collect{a=b.clone();a[it]=v;[it,a]}};def r(b,q,n){f(b,q,M,1).each{i->f(i[1],n,M,2).each{j->if(f(j[1],0,M,1).any{f(it[1],0,M,2)}){r(j[1],i[0],j[0])}else{S.add(j[1])}}}};r(new int[M],0,0);if(x<S.size()){sprintf('//%s%cX=%d;Y=%c%s%c;print(Eval.xy(X,Y,Y))',S[x].toString(),10,x+1,34,y,34)}else{''}";print(Eval.xy(X,Y,Y))

निम्न स्क्रिप्ट का उपयोग स्वचालित परीक्षण के लिए किया जा सकता है ( फिर से तर्क के रूप में एन प्रदान करें):

#!/bin/bash
set -e
test -n "$1"
groovy qak.groovy "$1" > t
while test -s t; do
    head -n1 t
    groovy t > t2
    mv t2 t
done

क्योंकि मैंने समाधान को यथासंभव छोटा बनाने की कोशिश की, यह बहुत धीमा है (विवरण के लिए नीचे देखें)। मैंने इस संस्करण के साथ केवल n = 4 का परीक्षण किया, यह देखने के लिए कि क्या क्वालीफिकेशन काम करता है।

परिणाम

n = 4: 40 समाधान ( परिवर्तित प्रारूप )
n = 5: 172 समाधान ( परिवर्तित प्रारूप )
n = 6: 2836 समाधान ( परिवर्तित प्रारूप) )

कलन विधि

यह समाधान का एक छोटा सा अनगढ़ा हुआ गैर-क्वीन संस्करण है:

N=args[0] as int
M=N*N
S=[]

/**
 * Generate a list of valid posibilities to place a new piece.
 * @param b Starting board.
 * @param i Start of the index range to check (inclusive).
 * @param j End of the index range to check (exclusive).
 * @param v Value of the new piece (1=queen, 2=knight).
 * @return A pair with the index of the new piece and a corresponding board for each possibility.
 */
def f(b,i,j,v){
    (i..<j).findAll{k->
        !(0..<M).any{l->
            w=b[l]
            r=(k.intdiv(N)-l.intdiv(N)).abs()
            c=(k%N-l%N).abs()
            s=v+w
            w>0&&(k==l||(r==0||c==0||r==c?s<4:r<3&&c<3&&s>2))
        }
    }.collect{
        a=b.clone();a[it]=v;[it,a]
    }
}

/**
 * Recursively look for solutions.
 * @param b Starting board.
 * @param q Start of the index range to check for queens.
 * @param n Start of the index range to check for knights.
 */
def r(b,q,n){
    f(b,q,M,1).each{i->
        f(i[1],n,M,2).each{j->
            if(f(j[1],0,M,1).any{f(it[1],0,M,2)}){
                r(j[1],i[0],j[0])
            }else{
                S.add(j[1])
            }
        }
    }
}

r(new int[M],0,0)
S.each{println(it)}

Quineification

कोड आकार को कम रखने के लिए मैंने यहां बहुत ही सरल दृष्टिकोण का उपयोग किया।

X=0;Y="...";print(Eval.xy(X,Y,Y))

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

संशोधित कोड समाधान से की ओर इशारा किया प्रिंट एक्स , बढ़ जाती है एक्स और स्वयं की प्रतिलिपि संलग्न कर देता है:

//[...]
X=1;Y="...";print(Eval.xy(X,Y,Y))

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


अच्छा जवाब, अच्छी नौकरी।
coredump

6

आम लिस्प, 737

आत्म जवाब

(lambda(n &aux(d 1))#2=(catch'$(let((s(* n n))(c d))(labels((R(w % @ b ! &aux r h v a)(loop for u from % below s do(setf h(mod u n)v(floor u n)a #4=(aref b u))(when(< 0(logand a w)4)(and(= 6 w)!(throw'! t))(let((b(copy-seq b))(o 5))(loop for(K D)on'(-1 -2 -1 2 1 -2 1 2)for y =(+ K v)for x =(+(or D -1)h)for u =(and(< -1 y n)(< -1 x n)(+(* y n)x))if u do #1=(if(< #4#4)(setf #4#(logand #4#o(if(= w o)3 0)))))(#8=dotimes(y N)(#8#(x N)(let((u(+(* y n)x))(o 6))(if(or(= x h)(= y v)(=(abs(- h x))(abs(- v y))))#1#))))(setf #4#w r(or(cond((= w 5)(R 6 @ U b !))((R 5 @ U b())t)((catch'!(R 5 0 0 b t))t)(t(and(=(decf c)0)(incf d)(or(format t"~%(lambda(&aux(n ~A)(d ~A))~%~S)"n d'#2#)(throw'$ B)))t))r)))))r))(R 5 0 0(fill(make-array s)3)())))))

उदाहरण

REPL में उपरोक्त पेस्ट करें, जो एक फ़ंक्शन ऑब्जेक्ट लौटाता है:

#<FUNCTION (LAMBDA (N &AUX (D 1))) {1006D1010B}>

इसे कॉल करें (स्टार अंतिम रिटर्न वैल्यू के लिए बाध्य है):

QN> (funcall * 4)

यह मानक आउटपुट के लिए निम्नलिखित प्रिंट करता है:

(lambda(&aux(n 4)(d 2))
#1=(CATCH '$
 (LET ((S (* N N)) (C D))
   (LABELS ((R (W % @ B ! &AUX R H V A)
              (LOOP FOR U FROM % BELOW S
                    DO (SETF H (MOD U N)
                             V (FLOOR U N)
                             A #2=(AREF B U)) (WHEN (< 0 (LOGAND A W) 4)
                                                (AND (= 6 W) !
                                                     (THROW '! T))
                                                (LET ((B (COPY-SEQ B))
                                                      (O 5))
                                                  (LOOP FOR (K D) ON '(-1
                                                                       -2
                                                                       -1 2
                                                                       1 -2
                                                                       1 2)
                                                        FOR Y = (+ K V)
                                                        FOR X = (+
                                                                 (OR D -1)
                                                                 H)
                                                        FOR U = (AND
                                                                 (< -1 Y N)
                                                                 (< -1 X N)
                                                                 (+ (* Y N)
                                                                    X))
                                                        IF U
                                                        DO #3=(IF (< #2# 4)
                                                                  (SETF #2#
                                                                          (LOGAND
                                                                           #2#
                                                                           O
                                                                           (IF (=
                                                                                W
                                                                                O)
                                                                               3
                                                                               0)))))
                                                  (DOTIMES (Y N)
                                                    (DOTIMES (X N)
                                                      (LET ((U
                                                             (+ (* Y N) X))
                                                            (O 6))
                                                        (IF (OR (= X H)
                                                                (= Y V)
                                                                (=
                                                                 (ABS
                                                                  (- H X))
                                                                 (ABS
                                                                  (- V
                                                                     Y))))
                                                            #3#))))
                                                  (SETF #2# W
                                                        R
                                                          (OR
                                                           (COND
                                                            ((= W 5)
                                                             (R 6 @ U B !))
                                                            ((R 5 @ U B
                                                                NIL)
                                                             T)
                                                            ((CATCH '!
                                                               (R 5 0 0 B
                                                                  T))
                                                             T)
                                                            (T
                                                             (AND
                                                              (= (DECF C)
                                                                 0)
                                                              (INCF D)
                                                              (OR
                                                               (FORMAT T
                                                                       "~%(lambda(&aux(n ~A)(d ~A))~%~S)"
                                                                       N D
                                                                       '#1#)
                                                               (THROW '$
                                                                 B)))
                                                             T))
                                                           R)))))
              R))
     (R 5 0 0 (FILL (MAKE-ARRAY S) 3) NIL)))))

इस फ़ंक्शन द्वारा लौटाया गया मान भी है:

#(5 0 0 0 0 0 0 6 0 0 0 2 0 2 0 0)

... जो एक सरणी शाब्दिक है। नंबर 5 रानियों का प्रतिनिधित्व करता है, 6 शूरवीरों के लिए है और कुछ भी एक खाली सेल के लिए खड़ा है, सिवाय आंतरिक रूप से संग्रहीत अधिक informations हैं। यदि हम दिए गए फ़ंक्शन को उत्तर में कॉपी-पेस्ट करते हैं, तो हम एक नया फ़ंक्शन प्राप्त करते हैं।

#<FUNCTION (LAMBDA (&AUX (N 4) (D 2))) {100819148B}>

और हम इसे बिना तर्क के कह सकते हैं:

QN> (funcall * )

यह कॉल एक नया समाधान #(5 0 0 0 0 0 0 2 0 0 0 6 0 0 2 0)और किसी अन्य फ़ंक्शन का स्रोत (यहां नहीं दिखाया गया) देता है। मूल कार्य या अंतिम उत्पन्न के मामले में कोई हल नहीं निकलता है, कुछ भी मुद्रित नहीं होता है और कुछ भी वापस नहीं किया जाता है।

आंतरिक मूल्य

|----------+--------+---------+--------+-----------------|
|          | Binary | Decimal | Symbol | Meaning         |
|----------+--------+---------+--------+-----------------|
| Empty    |    000 |       0 | -      | safe for none   |
|          |    001 |       1 | q      | safe for queen  |
|          |    010 |       2 | n      | safe for knight |
|          |    011 |       3 | #      | safe for both   |
|----------+--------+---------+--------+-----------------|
| Occupied |    101 |       5 | Q      | a queen         |
|          |    110 |       6 | K      | a knight        |
|----------+--------+---------+--------+-----------------|

मैं बहुत कम समाधान उत्पन्न करता था। अब, मैं प्रचार करता हूं कि रानी के लिए और स्वतंत्र रूप से कौन सी सेल सुरक्षित है। उदाहरण के लिए, यहाँ सुंदर मुद्रण के साथ n = 5 के लिए एक आउटपुट है:

Q - - - - 
- - - n N 
- q - n n 
- # n - n 
- n # # - 

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

अधिक सटीक रूप से, यहां निम्नलिखित समाधान (बाएं से दाएं) के लिए अग्रणी बोर्डों का अनुक्रम है, जहां विभिन्न मूल्यों से मुक्त कोशिकाओं को धीरे-धीरे विवश किया जाता है:

# # # # # #     q - - - q #     - - - - - #     - - - - - #     - - - - - n
# # # # # #     - - Q - - -     - - Q - - -     - - Q - - -     - - Q - - -
# # # # # #     q - - - q #     q - - - - -     Q - - - - -     Q - - - - -
# # # # # #     - q - q - #     - q - - - n     - - - - - n     - - - - - n
# # # # # #     # # - # # -     n n - n N -     - - - n N -     - - - - N -
# # # # # #     # # - # # #     # # - n n n     - # - - n n     - n - - n N

गैर-रानी दृष्टिकोण

Ungolfed, टिप्पणी संस्करण

(defun queens-and-knights
    (n    ; size of problem
     fn   ; function called for each solution

     ;; AUX parameters are like LET* bindings but shorter.
     &aux
       ;; total number of cells in a board
       (s (* n n)))

  (labels
      ;; Define recursive function R
      ((R (w      ; what piece to place: 5=queen, 6=knight 
           %      ; min position for piece of type W
           @      ; min position for the other kind of piece
           b      ; current board
           !      ; T iff we are in "check" mode (see below)
           &aux  
           r      ; result of this function: will be "true" iff we can
                  ; place at least one piece of type W on the board b
           h      ; current horizontal position 
           v      ; current vertical position
           a      ; current piece at position (h,v)
           )

         (loop
            ;; only consider position U starting from position %,
            ;; because any other position below % was already visited
            ;; at a higher level of recursion (e.g. the second queen
            ;; we place is being placed in a recursive call, and we
            ;; don't visit position before the first queen).
            for u from % below s

            do
              (setf h (mod u n)         ; Intialize H, V and A
                    v (floor u n)       ; 
                    a (aref b u))       ; 

            ;; Apply an AND mask to current value A in the board
            ;; with the type of chess piece W. In order to consider
            ;; position U as "safe", the result of the bitwise AND
            ;; must be below 4 (empty cell) and non-null.
              (when (< 0 (logand a w) 4)

                ;; WE FOUND A SAFE PLACE TO PUT PIECE W

                (when (and ! (= 6 w))
                  ;; In "check" mode, when we place a knight, we knwo
                  ;; that the check is successful. In other words, it
                  ;; is possible to place an additional queen and
                  ;; knight in some board up the call stack. Instead
                  ;; of updating the board we can directly exit from
                  ;; here (that gave a major speed improvement since
                  ;; we do this a lot). Here we do a non-local exit to
                  ;; the catch named "!".
                  (throw '! t))

                ;; We make a copy of current board b and bind it to the
                ;; same symbol b. This allocates a lot of memory
                ;; compared to the previous approach where I used a
                ;; single board and an "undo" list, but it is shorter
                ;; both in code size and in runtime.
                (let ((b (copy-seq b)))

                  ;; Propagate knights' constraints
                  (loop
                     ;; O is the other kind of piece, i.e. queen here
                     ;; because be propagate knights. This is used as
                     ;; a mask to remove knights pieces as possible
                     ;; choices.
                     with o = 5

                     ;; The list below is arranged so that two
                     ;; consecutive numbers form a knight-move. The ON
                     ;; iteration keyword descend sublist by sublist,
                     ;; i.e. (-1 -2), (-2 -1), (-1 2), ..., (2 NIL). We
                     ;; destructure each list being iterated as (K D),
                     ;; and when D is NIL, we use value -1.
                     for (K D) on '(-1 -2 -1 2 1 -2 1 2)

                     ;; Compute position X, Y and index U in board,
                     ;; while checking that the position is inside the
                     ;; board.
                     for y = (+ K v)
                     for x = (+ (or D -1) h)
                     for u = (and (< -1 y n)
                                  (< -1 x n)
                                  (+(* y n)x))

                     ;; if U is a valid position...
                     if u
                     do
                     ;; The reader variable #1# is affected to the
                     ;; following expression and reused below for
                     ;; queens. That's why the expression is not
                     ;; specific to knights. The trick here is to
                     ;; use the symbols with different lexical
                     ;; bindings.
                       #1=(when (< (aref b u) 4) ; empty?
                            (setf (aref b u)

                                  (logand
                                   ;; Bitwise AND of current value ...
                                   (aref b u)

                                   ;; ... with o: position U is not a
                                   ;; safe place for W (inverse of O)
                                   ;; anymore, because if we put a W
                                   ;; there, it would attack our
                                   ;; current cell (H,V).
                                   o

                                   ;; ... and with zero (unsafe for
                                   ;; all) if our piece W is also a
                                   ;; knight (resp. queen). Indeed, we
                                   ;; cannot put anything at position
                                   ;; U because we are attacking it.
                                   (if (= w o) 3 0)))))

                  ;; Propagate queens' constraints
                  (dotimes (y N)
                    (dotimes (x N)
                      (let ((u(+(* y n)x))(o 6))
                        (if (or (= x h)
                                (= y v)
                                (= (abs(- h x)) (abs(- v y))))

                            ;; Same code as above #1=(if ...)
                            #1#))))

                  (setf
                   ;; Place piece
                   (aref b u) w

                   ;; Set result value
                   r (or (cond
                           ;; Queen? Try to place a Knight and maybe
                           ;; other queens. The result is true only if
                           ;; the recursive call is.
                           ((= w 5) (R 6 @ U b !))

                           ;; Not a queen, so all below concern   
                           ;; knights: we always return T because
                           ;; we found a safe position.
                           ;; But we still need to know if
                           ;; board B is an actual solution and 
                           ;; call FN if it is.
                           ;; ------------------------------------

                           ;; Can be place a queen too? then current
                           ;; board is not a solution.
                           ((R 5 @ U b()) t)

                           ;; Try to place a queen and a knight
                           ;; without constraining the min positions
                           ;; (% and @); this is the "check" mode that
                           ;; is represented by the last argument to
                           ;; R, set to T here. If it throws true,
                           ;; then board B is a duplicate of a
                           ;; previous one, except that it is missing
                           ;; pieces due to constraints % and @. The
                           ;; "check" mode is a fix to a bug where we
                           ;; reported as solutions boards where there
                           ;; was still room for other pieces.
                           ((catch'!(R 5 0 0 b t)) t)

                           ;; Default case: we could not add one more
                           ;; layer of pieces, and so current board B
                           ;; is a solution. Call function FN.
                           (t (funcall fn b) t))

                         ;; R keeps being true if it already was for
                         ;; another position.
                         r)))))

         ;; Return result R
         r))

    ;; Start search with a queen and an empty board.
    (R 5 0 0 (fill (make-array s) 3)  nil)))

डुप्लिकेट और बग्स

मेरे पहले समाधान ने डुप्लिकेट समाधानों का उत्पादन किया। इसे हल करने के लिए, मैंने रानियों और शूरवीरों के लिए दो काउंटर शुरू किए। क्वीन्स (सम्मान शूरवीरों) के लिए काउंटर बोर्ड में पहली स्थिति का ट्रैक रखते हैं जहां एक रानी (सम्मान शूरवीर) मौजूद है: मैं केवल न्यूनतम स्थान का पालन करने वाले पदों पर एक रानी (शूरवीर) जोड़ता हूं।

यह विधियां मुझे उन समाधानों को फिर से देखने से रोकती हैं जो पहले से ही पुनरावृत्तियों में पाए गए थे, क्योंकि मैं एक बढ़ती हुई रानी (सम्मान नाइट) स्थिति के साथ पुनरावृति करता हूं।

हालांकि, स्लिफ़र ने देखा कि ऐसे समाधान थे जिनके लिए रानियों और शूरवीरों के लिए जगह हो सकती है, जो नियमों के खिलाफ है। थोड़ी देर के लिए हालांकि मुझे एक सामान्य खोज पर वापस लौटना पड़ा और डुप्लिकेट को रोकने के लिए सभी ज्ञात समाधानों को संग्रहीत करना पड़ा, जो बहुत महंगा (बाइट्स और मेमोरी उपयोग दोनों के संदर्भ में) महसूस हुआ।

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

टेस्ट

|---+---------+------------+--------------|
| N |  boards |    seconds |        bytes |
|---+---------+------------+--------------|
| 3 |       0 |          0 |        32768 |
| 4 |      40 |          0 |       360416 |
| 5 |     172 |          0 |      3440016 |
| 6 |    2836 |   0.085907 |     61251584 |
| 7 |   23876 |   1.265178 |    869666288 |
| 8 |  383586 |  24.991300 |  17235142848 |
| 9 | 6064506 | 524.982987 | 359952648832 |
|---+---------+------------+--------------|

Quine-वर्गीकरण

मेरे पास लगातार विचार करने के लिए अलग-अलग विचार थे। सबसे आसान शायद यह है कि स्ट्रिंग्स की एक सूची के रूप में सभी समाधानों को पहले उत्पन्न करें और क्रमिक quines लिखें जो प्रत्येक पीढ़ी में उस सूची से पॉप करते हैं। हालाँकि यह वर्तमान दृष्टिकोण से कम नहीं लग रहा था। वैकल्पिक रूप से, मैंने एक कस्टम स्टैक के साथ पुनरावर्ती कोड को फिर से लिखने और सभी राज्य चर को डंप करने की कोशिश की, जब भी मुझे कोई समाधान मिलता है; लक्ष्य यह है कि अगले चरण को वर्तमान कदम की निरंतरता के रूप में संसाधित किया जा सकता है। शायद यह स्टैक आधारित भाषा के लिए बेहतर अनुकूल होगा। वर्तमान एक काफी सरल है और आम लिस्प रीडर चर पर भरोसा करते हैं, जो हमेशा उपयोग करने में मजेदार होते हैं।

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