এন-কুইন-ও-অক্সাইন কুইন


21

এন-কুইনস নামক সমস্যার একটি বৈকল্পিক রয়েছে যা কুইনস এবং নাইটদের সাথে জড়িত এবং বলা হয় "যথেষ্ট বেশি কঠিন" 1 । সমস্যার বিবৃতিটি নিম্নরূপ:

আপনাকে অবশ্যই সমান সংখ্যক নাইট ♞ এবং কুইনস board একটি দাবাবোর্ডে রাখতে হবে যাতে কোনও টুকরো অন্য কোনও টুকরো আক্রমণ করে না। আপনি বোর্ডে সর্বাধিক সংখ্যক টুকরো রাখতে পারেন এবং আপনি এটি কতগুলি ভিন্ন উপায়ে করতে পারেন?

এই সালে চ্যালেঞ্জ, আপনি একটি ইনপুট দেওয়া হবে এন 3 এবং 32 মধ্যে (একটি উপায় যে আপনার ভাষার জন্য সবচেয়ে উপযুক্ত মধ্যে)। প্রদত্ত এন এর জন্য উপরের সমস্যার শূন্য বা আরও সমাধান হতে পারে। যদি সেখানে কোন সমাধান হয়, তাহলে আপনি অবশ্যই আউটপুট / রিটার্ন কিছুই ( শূন্য , খালি স্ট্রিং , মিথ্যা , ...)। অন্যথায়, আপনাকে অবশ্যই দুটি ফলাফল দিতে হবে:

  1. আকার এন এর জন্য একটি সমাধান বোর্ড (নীচে দেখুন) যেখানে কোনও টুকরো আক্রান্ত না হয়ে রানী বা একটি নাইট দাবা টুকরো যুক্ত করা সম্ভব নয়। রাণী এবং নাইটের সমান সংখ্যা থাকতে হবে
  2. একটি প্রোগ্রাম উৎস রান কোনো ইনপুট গ্রহণ করে এবং দেয় (ঝ) হতে অন্য সমাধান (অথবা কিছুই একই আকারের জন্য) এন (২) পরবর্তী সমাধান জন্য অন্য প্রোগ্রাম হিসাবে, একই বিন্যাসে, পাশাপাশি (ইত্যাদি ...)।

মনে রাখবেন যে:

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

বোর্ড ফর্ম্যাট

  • একটি বোর্ড আকারের একটি বর্গ হয় এন
  • একটি বোর্ড সেল খালি, একটি রানী বা একটি নাইট হতে পারে।
  • আপনার অবশ্যই প্রতিটি ধরণের কক্ষের জন্য পৃথক মান নির্বাচন করতে হবে (যেমন বোর্ড প্রিন্ট করার সময় আপনি Q, N এর চেয়ে অন্য চিহ্নগুলি ব্যবহার করতে পারেন)।
  • যদি আপনি একটি স্ট্রিং বোর্ডকে ফেরত দেন তবে এটি অবশ্যই বোর্ডের এন 2 টি মানগুলির একটি অর্ডারকৃত সংগ্রহ (যেমন ম্যাট্রিক্স, ভেক্টর বা সারি / কলাম-প্রধান ক্রমের তালিকা, ...) হওয়া উচিত।
  • আপনি যদি বোর্ডটি মুদ্রণ করেন তবে আপনি এটি স্কোয়ারযুক্ত, বা একটি লাইন হিসাবে মুদ্রণ করতে পারেন। উদাহরণস্বরূপ, 4 আকারের একটি সমাধান বোর্ড নিম্নরূপে মুদ্রণ করা যেতে পারে (শূন্যস্থানগুলির প্রয়োজন হয় না; আপনার বিবেচনার ভিত্তিতে চিহ্নগুলি):

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

    যদি আপনি এটি অনুভব করেন তবে আপনি আউটপুটও করতে পারেন:

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

    ... তবে এটি যথেষ্ট:

    Q-------------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
    

আপনি ম্যাট্রিক হিসাবে এন = 5 এর সমাধানগুলিও দেখতে পারেন ; বোর্ড রয়েছে #, qএবং nপ্রতীক, যা বিভিন্ন ধরণের খালি কোষ হয় (নীচের আমার উত্তর দেখুন)। স্লেফারের উত্তরে যেমন আমি এন = 6 এর জন্য 2836 বোর্ড গণনা করি (বাইট গণনা হ্রাস করার সময় আমি একটি বাগ প্রবর্তন করেছি, তবে এটি এখন ঠিক করা হয়েছে)।

স্লেফারকে আমার কোডে দুটি নয়, দুটি বাগ খুঁজে পাওয়ার জন্য অনেক ধন্যবাদ।

স্কোর

বাইট জিতে সংক্ষিপ্ত কোড।

আমরা প্রথম প্রোগ্রামটির আকার পরিমাপ করি, যা এন গ্রহণ করে ।


কুইনস এবং নাইটস , রজার কে ডাব্লু হুই দ্বারা (সাবধান! একটি সমাধান রয়েছে)


4
সম্ভবত আপনি এই উপর একটি অনুগ্রহ করা উচিত। সত্যি বলতে, সমস্যাটি কুইন পার্ট ব্যতীত যথেষ্ট শক্ত।
mbomb007

আমরা কিউ, এন এবং - ব্যতীত অন্য কোনও চিহ্ন ব্যবহার করতে পারি কুইনস এবং নাইটগুলি বোঝাতে এবং খালি, যতক্ষণ না সেগুলি আলাদা?
ফ্যাটালাইজ করুন

@ ফ্যাটালাইজ হ্যাঁ, নিশ্চিত
coredump

1
@ কর্ড্প্প মানে ফাংশনের বিষয়বস্তু পড়া meant এবং আমি এটি "হ্যাঁ, আপনাকে নিজের উত্স কোড এবং / অথবা ফাংশন সামগ্রীগুলি পড়ার অনুমতি দেওয়া হয়েছে" হিসাবে গ্রহণ করব। (আমার সমাধান এটির উপর নির্ভর করে, তাই ...)
wizzwizz4

1
@ কর্ড্প্প যদি আমি চ্যালেঞ্জটি সঠিকভাবে বুঝতে পারি তবে 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))

পরীক্ষামূলক

কমান্ড লাইন আর্গুমেন্ট হিসাবে এন সরবরাহ করুন :

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

যেহেতু আমি সমাধানটি যতটা সম্ভব ছোট করার চেষ্টা করেছি, এটি খুব ধীরে (বিশদগুলির জন্য নীচে দেখুন)। আমি এই সংস্করণটির সাথে কেবল এন = 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))

ভেরিয়েবল এক্স পরবর্তী মুদ্রণের জন্য সমাধানটির সূচক ধারণ করে। ওয়াইয়ের উপরের অ্যালগরিদমের একটি পরিবর্তিত অনুলিপি রয়েছে, যা সমস্ত সমাধান গণনা করতে ব্যবহার করা হয় এবং তারপরে কেবলমাত্র একটি নির্বাচন করুন, এটি এতো ধীর হওয়ার কারণ। এই সমাধানটির সুবিধাটি হ'ল এটির জন্য অতিরিক্ত অতিরিক্ত কোডের প্রয়োজন হয় না। সঞ্চিত কোড ওয়াই সাহায্যে কার্যকর Eval (একটি সত্য quine প্রয়োজন হয় না) বর্গ।

পরিবর্তিত কোডটি এক্স দ্বারা নির্দেশিত সমাধানটি মুদ্রণ করে , এক্স বাড়িয়ে তোলে এবং নিজের একটি অনুলিপি যুক্ত করে:

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

আমি দ্বিতীয় ধাপের কোড হিসাবে সমস্ত সমাধান আউটপুট দেওয়ার চেষ্টা করেছি, তবে এন = 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)())))))

উদাহরণ

আরপিএলে উপরেরটি আটকান, যা কোনও ফাংশন অবজেক্টটি দেয়:

#<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 নাইটদের জন্য এবং অন্য যে কোনও কিছু খালি ঘরটির জন্য দাঁড়ায়, অভ্যন্তরীণভাবে আরও বেশি তথ্য সঞ্চিত থাকে except যদি আমরা প্রত্যাবর্তিত ফাংশনটি অনুলিপি করে রাখি তবে আমরা একটি নতুন ফাংশন পাই।

#<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        |
|----------+--------+---------+--------+-----------------|

আমি খুব কম সমাধান উত্পন্ন করতে ব্যবহৃত। এখন, আমি প্রচার করি যে কোন কক্ষটি রানী এবং নাইটের জন্য নিরাপদ, স্বাধীনভাবে। উদাহরণস্বরূপ, চমত্কার-প্রিন্টিং সহ এখানে এন = 5 এর আউটপুট রয়েছে:

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

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

আরও স্পষ্টভাবে, এখানে নীচের সমাধানের দিকে পরিচালিত বোর্ডগুলির ক্রম রয়েছে (বাম থেকে ডানে), যেখানে বিনামূল্যে কোষগুলি ধীরে ধীরে বিভিন্ন মান দ্বারা সীমাবদ্ধ থাকে:

# # # # # #     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

নন-কুইন অ্যাপ্রোচ

অবহেলিত, মন্তব্য করা সংস্করণ

(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-ification

একের পর এক কুইন বানানোর জন্য আমার আলাদা ধারণা ছিল। সহজতমটি হ'ল সম্ভবত স্ট্রিংগুলির তালিকা হিসাবে সমস্ত সমাধান তৈরি করা এবং প্রতিটি প্রজন্মের সেই তালিকা থেকে পপ করা ক্রমিক ক্রয়গুলি লিখুন। তবে এটি বর্তমান পদ্ধতির চেয়ে কম বলে মনে হয় নি। বিকল্পভাবে, আমি একটি কাস্টম স্ট্যাকের সাহায্যে পুনরাবৃত্ত কোডটি পুনরায় লেখার চেষ্টা করেছি এবং প্রতিবার কোনও সমাধান পেলে সমস্ত রাজ্যের ভেরিয়েবলগুলি ডাম্প করেছিলাম; লক্ষ্যটি হ'ল পরবর্তী পদক্ষেপটি বর্তমান পদক্ষেপের ধারাবাহিকতা হিসাবে প্রক্রিয়া করা যায়। সম্ভবত এটি স্ট্যাক ভিত্তিক ভাষার জন্য আরও উপযুক্ত। বর্তমানেরটি বেশ সহজ এবং সাধারণ লিপ্প রিডার ভেরিয়েবলগুলির উপর নির্ভর করে যা সর্বদা ব্যবহারে মজাদার।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.