Kraliçe-ve-at nalı


21

İyi bilinen bir varyantı vardır kraliçe ve şövalyeler içerir ve olduğu söylenir sorunu N-kraliçelerini "önemli ölçüde zor" 1 . Sorun ifadesi aşağıdaki gibidir:

Bir satranç tahtasına eşit sayıda şövalye ♞ ve kraliçe ♛ koymalısınız, öyle ki hiçbir parça başka bir parçaya saldırmaz. Tahtaya bu kadar yerleştirebileceğiniz maksimum parça sayısı nedir ve kaç farklı şekilde yapabilirsiniz?

Bu ise meydan, bir giriş verilecektir n (Diliniz için en uygun bir şekilde) 3 ile 32 arasında. Belirli bir n için yukarıdaki soruna sıfır veya daha fazla çözüm olabilir. Çözüm yoksa, hiçbir şey vermemelisiniz / döndürmelisiniz ( nil , boş dize , yanlış , ...). Aksi takdirde, iki sonuç vermelisiniz:

  1. Herhangi bir parça saldırı altında olmadan bir kraliçe veya şövalye satranç taşının eklenmesinin mümkün olmadığı n büyüklüğü için bir çözüm tahtası (aşağıya bakınız) . Eşit sayıda kraliçe ve şövalye olmalı .
  2. Hiçbir girdiyi kabul etmeyen ve (i) aynı boyutta n için aynı formatta başka bir çözüm (veya hiçbir şey ) ve aynı zamanda (ii) bir sonraki çözüm için başka bir program (ve benzeri ) veren çalıştırılacak bir programın kaynağı ...).

Bunu not et:

  • Programların sırası, iki kez aynı tahta dönmek asla boy sorununa yönelik olası tüm çözümleri kapsamalıdır n ve sonunda sonlandırmalıdır (çıktı üretmeden).
  • İki değeri döndürebilir, birini döndürebilir ve diğerini yazdırabilir veya iki dönüş değerini yazdırabilirsiniz.
  • Ancak , hem kartı hem de sonraki programı yazdırırsanız, kart sonraki programın bir parçası olarak düşünülmemelidir (panoyu yorumda yazdırmanızı veya standart çıktı ve hata akışlarını kullanmanızı öneririm).
  • Dönüş olarak bir program değeri, bir kapatma değil bir dize olmalıdır.

Tahta biçimi

  • Bir tahta n büyüklüğünde bir karedir .
  • Bir tahta hücresi boş, bir kraliçe veya bir şövalye olabilir.
  • Her hücre türü için ayrı değerler seçmelisiniz (örneğin, kartı yazdırırken Q, N dışındaki simgeleri kullanabilirsiniz).
  • Yaylı olmayan bir yazı tahtası döndürürseniz , n 2’nin sipariş verilen bir koleksiyonu olmalıdır. kurulu değerler (örn matris, vektör veya satır / sütun-majör sırayla liste, ...).
  • Tahtayı yazdırırsanız, kareyi ya da bir çizgi olarak yazdırabilirsiniz. Örneğin, 4 boyutunda bir çözüm kartı aşağıdaki şekilde basılabilir (boşluklar gerekli değildir; takdirinize bağlı semboller):

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

    Eğer öyle hissediyorsanız, şunu da yazdırabilirsiniz:

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

    ... ama bu yeterli:

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

    Simetrik çözümler olduğundan, satır büyüklüğü veya sütun büyüklüğü düzenindeki hücreler arasında yineleme yapıp yapmamanız önemli değildir. Örneğin, n = 4 için çözümler şunlardır:

    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
    

Ayrıca n = 5 çözümlerine matris olarak bakabilirsiniz ; panoları içeren #, qve nfarklı türde boş hücreleri olan semboller, (benim cevap aşağıya bakınız). N = 6 için 2836 kartı sayıyorum Sleafar yanıtında olduğu gibi, (bayt sayısını azaltarak zaman bir hata tanıttı, ama şimdi sabittir).

Kodumda bir değil iki hata bulduğum için Sleafar'a çok teşekkürler.

Gol

Bayt cinsinden en kısa kod kazanır.

Biz ilk programın boyutunu kabul eden bir ölçü n .


1 . Roger ve KW Hui tarafından Queens ve Knights (dikkat! Bir çözüm içerir)


4
Belki de buna bir ödül vermelisin. Dürüst olmak gerekirse, sorun kıskacın kısmı olmadan da zor.
mbomb007

Kraliçeleri ve Şövalyeleri belirtmek için ve belirgin oldukları sürece boş bırakmak için Q, N ve - dışında herhangi bir sembol kullanabilir miyiz?
Nis'i

@Fatalize Evet, elbette
coredump

1
@ coredump İşlevin içeriğini okumak istemiştim. Ve bunu "evet, kendi kaynak kodunuzu ve / veya işlev içeriğinizi okumanıza izin veriliyor" olarak kabul edeceğim. (Benim çözümüm buna güveniyor, bu yüzden ...)
wizzwizz4

1
@ coredump Eğer sorunu doğru anlarsam, o zaman n = 6 referans çözümünüz geçersiz girişler içeriyor (örneğin -------------------------N--------Q-, daha fazla parça eklenebileceği için geçersiz :) Q--------N---------------N--------Q-.
Sleafar

Yanıtlar:


2

Groovy, 515 bayt

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

Test yapmak

Sağlamak N komut satırı bağımsız değişken olarak:

groovy qak.groovy 4

Çıktının ilk satırı her zaman yorum olarak bir çözümdür (0 = boş, 1 = kraliçe, 2 = şövalye), ardından ikinci satırdaki kod:

//[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))

Aşağıdaki komut otomatik testler için kullanılabilir ( n'yi bir argüman olarak tekrar belirtin):

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

Çözümü olabildiğince küçük yapmaya çalıştığım için çok yavaştır (ayrıntılar için aşağıya bakın). Kısalmanın işe yarayıp yaramadığını görmek için sadece n = 4'ü test ettim.

Sonuçlar

n = 4: 40 çözüm ( dönüştürülmüş biçim )
n = 5: 172 çözüm ( dönüştürülmüş biçim )
n = 6: 2836 çözüm ( dönüştürülmüş biçim )

Algoritma

Bu, çözümün hafifçe ungolfed quine olmayan bir versiyonudur:

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

Kod boyutunu düşük tutmak için çok basit bir yaklaşım kullandım.

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

X değişkeni bir sonraki yazdırılacak çözümün dizinini tutar. Y , tüm çözümleri hesaplamak için kullanılan ve bunlardan sadece birini seçen yukarıdaki algoritmanın değiştirilmiş bir kopyasını tutar , bu nedenle bunun yavaş olması gerekir. Bu çözümün avantajı, fazladan bir kod gerektirmemesidir. Depolanan kod Y yardımıyla çalıştırılır Eval (gerçek quine gerekli değildir) sınıfı.

Modifiye kod tarafından işaret çözüm yazdırır X artırır X ve kendisinin bir kopyasını ekler:

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

Ayrıca tüm çözümleri ikinci adım için kod olarak çıkarmaya çalıştım, ama n = 6 için Groovy'nin kullanması için çok fazla kod üretiyordu.


Güzel cevap, iyi iş.
coredump

6

Common Lisp, 737

öz cevap

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

Örnek

Yukarıdakileri, bir işlev nesnesi döndüren REPL'de yapıştırın:

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

Onu arayın (yıldız en son döndürülen değere bağlı):

QN> (funcall * 4)

Bu, aşağıdakileri standart çıktıya yazdırır:

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

Ayrıca, bu işlev tarafından döndürülen değer:

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

... bir dizi değişmezdir. Sayı 5, kraliçeleri temsil eder, 6 şövalyeler içindir ve dahili olarak depolanan daha fazla bilgi dışında, başka bir şey boş bir hücre anlamına gelir. Döndürülen işlevi repl'e kopyalayıp yapıştırırsak, yeni bir işlev elde ederiz.

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

Ve argüman olmadan buna çağırabiliriz:

QN> (funcall * )

Bu çağrı yeni bir çözüm getirir #(5 0 0 0 0 0 0 2 0 0 0 6 0 0 2 0) ve başka bir işlevin kaynağını (burada gösterilmez). Orijinal işlev veya son üretilen birinin bir çözüm bulamaması durumunda hiçbir şey yazdırılmaz ve hiçbir şey iade edilmez.

Dahili değerler

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

Eskiden çok az çözüm üretiyordum. Şimdi, hangi hücrenin bir kraliçe ve bir şövalye için güvenli olduğunu, bağımsız olarak yayıyorum. Örneğin, burada n = 5 için güzel baskı ile bir çıktı verilmiştir:

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

Kraliçeyi yerleştirdiğimizde, Qbu kraliçeden uzaklaşan bir şövalye hamlesi olan konumlar hala kraliçeler için güvenli ve belirtilmiş olanlardır q. Aynı şekilde, yalnızca kraliçeler tarafından ulaşılabilen şövalyeler, diğer şövalyeler için güvenlidir. Değerler bitsel ve olası hareketleri temsil etmek için kullanılır ve bazı hücrelere herhangi bir parça tarafından erişilemez.

Daha doğrusu, burada, serbest hücrelerin kademeli olarak farklı değerlerle sınırlandırıldığı aşağıdaki çözüme (soldan sağa) giden panellerin sırasıdır:

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

Quine olmayan yaklaşım

Ungolfed, yorum yaptı

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

Kopyalar ve hatalar

İlk çözümüm yinelenen çözümler üretti. Bunu çözmek için, kraliçeler ve şövalyeler için iki sayaç tanıttım. Kraliçe (şövalye şövalyeleri) sayacı, bir kraliçenin (şövalye şövalyesi) bulunduğu tahtadaki ilk pozisyonun kaydını tutar: Yalnızca bu asgari pozisyonu takip eden pozisyonlara bir kraliçe ekledim (bir şövalye).

Bu yöntemler, önceki yinelemelerde bulunan çözümleri tekrar ziyaret etmemi engelliyor, çünkü artan bir kraliçe (şövalye) pozisyonu ile yineliyorum.

Ancak Sleafar, kraliçelere ve şövalyelere yer açabilecek, kurallara aykırı çözümler bulunduğunu fark etti. Bir süredir normal bir aramaya geri dönüp, tüm masrafları önlemek için bilinen tüm çözümleri saklamak zorunda kaldım (bu da hem bayt hem de bellek kullanımı açısından).

Bunun yerine, şimdi yaptığım şey şu: Potansiyel bir çözüm kurulu bulunduğunda, tam olarak bir kraliçe ve bir tane daha eklemeye çalışıyorum. sayaçları dikkate almadan şövalye (yani, karttaki tüm hücreler için). Bu mümkünse, o zaman geçerli yönetim kurulu öncekinin kopyasıdır ve çözümü reddediyorum.

Testler

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

Ardışık quines yapmak için farklı fikirlerim vardı. En kolay olanı muhtemelen tüm çözümleri ilk önce dizelerin listesi olarak üretmek ve her nesilde bu listeden çıkan sıralı dizileri yazmaktır. Ancak bu, mevcut yaklaşımdan daha kısa değildi. Alternatif olarak özyinelemeli kodu özel bir yığınla yeniden yazmaya çalıştım ve bir çözüm bulduğumda tüm durum değişkenlerini bıraktım; Amaç, bir sonraki adımın mevcut adımın devamı olarak işlenebilmesidir. Belki bu, yığın tabanlı bir dil için daha uygun olur. Şimdiki oldukça basit ve kullanımı her zaman eğlenceli olan Common Lisp okuyucu değişkenlerine dayanıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.