N-nữ hoàng và ngựa


21

Có một biến thể của vấn đề N-queen nổi tiếng liên quan đến nữ hoàng và hiệp sĩ và được cho là "khó khăn hơn đáng kể" 1 . Báo cáo vấn đề như sau:

Bạn phải đặt một số hiệp sĩ bằng nhau và nữ hoàng trên bàn cờ sao cho không có quân cờ nào tấn công bất kỳ quân cờ nào khác. Số lượng tối đa của các mảnh bạn có thể đặt trên bảng là bao nhiêu và bạn có thể làm được bao nhiêu cách khác nhau?

Trong này thử thách, bạn sẽ được cung cấp một đầu vào n từ 3 đến 32 (trong một cách đó là phù hợp nhất đối với ngôn ngữ của bạn). Đối với một n cho trước , có thể có 0 hoặc nhiều giải pháp cho vấn đề trên. Trong trường hợp không có giải pháp, bạn phải xuất / trả lại không có gì ( nil , chuỗi rỗng , false , ...). Nếu không, bạn phải đưa ra hai kết quả:

  1. Một bảng giải pháp (xem bên dưới) cho kích thước n trong đó không thể thêm một nữ hoàng hoặc quân cờ hiệp sĩ mà không có bất kỳ quân cờ nào bị tấn công. Phải có một số lượng bằng nhau của các nữ hoàng và hiệp sĩ .
  2. Nguồn của chương trình được chạy không chấp nhận đầu vào và cung cấp cho (i) một giải pháp khác (hoặc không có gì ) cho cùng kích thước n , trong cùng định dạng, cũng như (ii) một chương trình khác cho giải pháp tiếp theo (v.v. ...).

Lưu ý rằng:

  • Trình tự các chương trình không bao giờ phải trả lại cùng một bảng hai lần, phải bao gồm tất cả các giải pháp có thể cho vấn đề kích thước n và cuối cùng phải chấm dứt (không tạo ra đầu ra).
  • Bạn có thể trả về hai giá trị, trả về một giá trị và in giá trị kia hoặc in hai giá trị trả về.
  • Tuy nhiên , nếu bạn in cả bảng và chương trình tiếp theo, bảng không được coi là một phần của chương trình tiếp theo (Tôi khuyên bạn nên in bảng trong nhận xét hoặc sử dụng cả luồng đầu ra tiêu chuẩn và luồng lỗi).
  • Giá trị chương trình dưới dạng trả về phải là một chuỗi, không phải là một bao đóng.

Định dạng bảng

  • Một bảng là một hình vuông có kích thước n .
  • Một tế bào bảng có thể trống, một nữ hoàng hoặc một hiệp sĩ.
  • Bạn phải chọn các giá trị riêng biệt cho từng loại ô (tức là bạn có thể sử dụng các ký hiệu khác ngoài Q, N khi in bảng).
  • Nếu bạn trả về một bảng không có chuỗi, thì đó phải là một tập hợp có thứ tự của n 2 giá trị của bảng (ví dụ: ma trận, vectơ hoặc danh sách theo thứ tự hàng / cột chính, ...).
  • Nếu bạn in bảng, bạn có thể in bình phương, hoặc dưới dạng một dòng. Ví dụ: bảng giải pháp có kích thước 4 có thể được in như sau (không cần khoảng trắng; ký hiệu theo ý của bạn):

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

    Nếu bạn cảm thấy như vậy, bạn cũng có thể xuất ra:

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

    ... nhưng điều này là đủ:

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

    Không có vấn đề gì nếu bạn lặp qua các ô theo thứ tự hàng chính hoặc cột chính, bởi vì có các giải pháp đối xứng. Ví dụ: các giải pháp cho n = 4 là:

    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
    

Bạn cũng có thể xem các giải pháp cho n = 5 dưới dạng ma trận ; Ban chứa #, qnbiểu tượng, đó là ô trống các loại khác nhau (xem câu trả lời của tôi dưới đây). Tôi đếm 2836 bảng cho n = 6 , như trong câu trả lời của Sleafar (Tôi đã giới thiệu một lỗi khi giảm số byte, nhưng hiện tại nó đã được sửa).

Rất cám ơn Sleafar vì đã tìm thấy không chỉ một mà hai lỗi trong mã của tôi.

Ghi bàn

Mã ngắn nhất trong byte thắng.

Chúng tôi đo kích thước của chương trình đầu tiên, chương trình chấp nhận n .


1 . Nữ hoàng và Hiệp sĩ , bởi Roger KW Hui (coi chừng! Có một giải pháp)


4
Có lẽ bạn nên đặt tiền thưởng vào việc này. Thành thật mà nói, vấn đề là đủ khó mà không có phần quine.
mbomb007

Chúng ta có thể sử dụng bất kỳ biểu tượng nào ngoài Q, N và - để biểu thị Nữ hoàng và Hiệp sĩ và trống không, miễn là chúng khác biệt?
Gây tử vong vào

@Firthize Có, chắc chắn
coredump

1
@coredump Ý tôi là đọc nội dung của hàm. Và tôi sẽ coi đó là "có, bạn được phép đọc mã nguồn và / hoặc nội dung chức năng của riêng bạn". (Giải pháp của tôi dựa vào nó, vì vậy ...)
wizzwizz4

1
@coredump Nếu tôi hiểu đúng thách thức, thì giải pháp tham chiếu của bạn cho n = 6 chứa các mục không hợp lệ (ví dụ: -------------------------N--------Q-không hợp lệ vì có thể thêm nhiều phần Q--------N---------------N--------Q-:).
Sleafar

Câu trả lời:


2

Groovy, 515 byte

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

Kiểm tra

Cung cấp n dưới dạng đối số dòng lệnh:

groovy qak.groovy 4

Dòng đầu tiên của đầu ra luôn là một giải pháp dưới dạng một nhận xét (0 = trống, 1 = nữ hoàng, 2 = hiệp sĩ), theo sau là mã trong dòng thứ hai:

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

Tập lệnh sau có thể được sử dụng để kiểm tra tự động (cung cấp n làm đối số một lần nữa):

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

Bởi vì tôi đã cố gắng làm cho giải pháp càng nhỏ càng tốt, nó rất chậm (xem bên dưới để biết chi tiết). Tôi đã thử nghiệm chỉ n = 4 với phiên bản này để xem liệu quineization có hoạt động không.

Các kết quả

n = 4: 40 giải pháp ( định dạng được chuyển đổi )
n = 5: 172 giải pháp ( định dạng được chuyển đổi )
n = 6: 2836 giải pháp ( định dạng được chuyển đổi )

Thuật toán

Đây là một phiên bản không quine hơi vô dụng của giải pháp:

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

Kiểm định

Tôi đã sử dụng một cách tiếp cận rất đơn giản ở đây để giữ kích thước mã thấp.

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

Biến X giữ chỉ mục của giải pháp để in tiếp theo. Y giữ một bản sao đã sửa đổi của thuật toán ở trên, được sử dụng để tính toán tất cả các giải pháp và sau đó chỉ chọn một trong số chúng, đó là lý do khiến nó quá chậm. Ưu điểm của giải pháp này là nó không yêu cầu nhiều mã bổ sung. Mã được lưu trữ trong Y được thực thi với sự trợ giúp của lớp Eval (không yêu cầu một quine thực sự).

Mã sửa đổi in ra giải pháp được chỉ ra bởi X , tăng X và nối thêm một bản sao của chính nó:

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

Tôi cũng đã cố gắng xuất tất cả các giải pháp dưới dạng mã cho bước thứ hai, nhưng với n = 6, nó đã tạo ra quá nhiều mã để Groovy xử lý.


Câu trả lời tốt đẹp, công việc tốt.
coredump

6

Lisp thường gặp, 737

tự trả lời

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

Thí dụ

Dán ở trên trong REPL, trả về một đối tượng hàm:

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

Gọi nó (ngôi sao bị ràng buộc với giá trị trả về cuối cùng):

QN> (funcall * 4)

Điều này in sau đây đến đầu ra tiêu chuẩn:

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

Ngoài ra, giá trị được trả về bởi hàm này là:

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

... đó là một mảng theo nghĩa đen. Số 5 đại diện cho nữ hoàng, 6 là dành cho hiệp sĩ và bất cứ điều gì khác là viết tắt của một ô trống, ngoại trừ có nhiều thông tin được lưu trữ nội bộ. Nếu chúng ta sao chép-dán hàm trả về vào thay thế, chúng ta sẽ có được một hàm mới.

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

Và chúng ta có thể gọi nó đến, mà không cần tranh luận:

QN> (funcall * )

Cuộc gọi này trả về một giải pháp mới #(5 0 0 0 0 0 0 2 0 0 0 6 0 0 2 0)và nguồn của một chức năng khác (không được hiển thị ở đây). Trong trường hợp hàm ban đầu hoặc hàm được tạo cuối cùng không tìm thấy giải pháp, không có gì được in và không có gì được trả về.

Giá trị nội bộ

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

Tôi đã sử dụng để tạo ra quá ít giải pháp. Bây giờ, tôi tuyên truyền tế bào nào an toàn cho nữ hoàng và cho một hiệp sĩ, một cách độc lập. Ví dụ, đây là một đầu ra cho n = 5 với in ấn đẹp:

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

Khi chúng tôi đặt nữ hoàng Q, các vị trí là một hiệp sĩ di chuyển khỏi nữ hoàng này vẫn an toàn cho các nữ hoàng và được ký hiệu q. Tương tự như vậy, các hiệp sĩ chỉ có thể tiếp cận bởi các nữ hoàng là an toàn cho các hiệp sĩ khác. Các giá trị được bitwise -ed để thể hiện các bước di chuyển có thể và một số ô có thể truy cập được mà không cần loại mảnh nào.

Chính xác hơn, đây là chuỗi các bảng dẫn đến giải pháp sau (từ trái sang phải), trong đó các ô tự do dần bị ràng buộc với các giá trị khác nhau:

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

Phương pháp không quine

Ungolfed, nhận xét phiên bả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)))

Bản sao và lỗi

Giải pháp đầu tiên của tôi xuất ra các giải pháp trùng lặp. Để giải quyết nó, tôi đã giới thiệu hai quầy dành cho nữ hoàng và hiệp sĩ. Bộ đếm dành cho nữ hoàng (hiệp sĩ hiệp sĩ) theo dõi vị trí đầu tiên trong hội đồng nơi có một nữ hoàng (hiệp sĩ): Tôi chỉ thêm một nữ hoàng (một hiệp sĩ) tại các vị trí theo vị trí tối thiểu đó.

Các phương pháp đó ngăn tôi xem xét lại các giải pháp đã được tìm thấy trong các lần lặp trước, bởi vì tôi lặp lại với vị trí nữ hoàng (hiệp sĩ) ngày càng tăng.

Tuy nhiên, Sleafar nhận thấy rằng có những giải pháp có thể có chỗ cho nữ hoàng và hiệp sĩ, điều này trái với quy tắc. Trong một thời gian, mặc dù tôi phải quay lại tìm kiếm bình thường và lưu trữ tất cả các giải pháp đã biết để ngăn ngừa trùng lặp, điều này cảm thấy quá tốn kém (cả về byte và sử dụng bộ nhớ).

Thay vào đó, đây là những gì tôi làm bây giờ: khi tìm thấy bảng giải pháp tiềm năng, tôi cố gắng thêm chính xác một nữ hoàng và một hiệp sĩ, mà không tính đến các quầy (tức là cho tất cả các ô trên bảng). Nếu điều này là có thể, thì bảng hiện tại là một bản sao của bảng trước đó và tôi từ chối giải pháp.

Xét nghiệm

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

Tôi đã có những ý tưởng khác nhau để thực hiện các nhiệm vụ liên tiếp. Cách đơn giản nhất có lẽ là tạo ra tất cả các giải pháp trước tiên dưới dạng danh sách các chuỗi và viết các chuỗi theo thứ tự xuất hiện từ danh sách đó ở mỗi thế hệ. Tuy nhiên điều này dường như không ngắn hơn cách tiếp cận hiện tại. Ngoài ra, tôi đã cố gắng viết lại mã đệ quy với ngăn xếp tùy chỉnh và kết xuất tất cả các biến trạng thái mỗi khi tôi tìm thấy giải pháp; mục tiêu là bước tiếp theo có thể được xử lý như là sự tiếp nối của bước hiện tại. Có lẽ điều này sẽ phù hợp hơn cho một ngôn ngữ dựa trên ngăn xếp. Cái hiện tại khá đơn giản và dựa vào các biến đọc chung Lisp, luôn luôn thú vị khi sử dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.