N-queen-and-kopine quine


21

Існує варіант відомої проблеми N-queens, яка стосується королеви та лицарів і, як кажуть, «значно складніше» 1 . Постановка проблеми така:

Ви повинні розмістити на шаховій дошці рівну кількість лицарів ♞ і королеви such, щоб жоден шматок не нападав на будь-який інший предмет. Яку максимальну кількість штук ви можете розмістити на дошці, і скільки різних способів ви можете це зробити?

У цьому виклику вам буде запропоновано ввести n між 3 та 32 (таким чином, який є найбільш підходящим для вашої мови). Для даного n може бути нульове або більше варіантів вирішення вищезазначеної проблеми. Якщо рішення немає, ви повинні нічого не виводити / повертати ( нульовий , порожній рядок , помилковий , ...). В іншому випадку потрібно дати два результати:

  1. Дошка рішення (див. Нижче) для розміру n, де неможливо додати королеву чи лицарську шахову фігуру, не маючи жодного шматка під атакою. Повинна бути однакова кількість королеви та лицарів .
  2. Джерело запущеної програми, яка не приймає жодного вводу та дає (i) інше рішення (або нічого ) для того ж розміру n , у тому ж форматі, а також (ii) іншу програму для наступного рішення (тощо) ...).

Зауважте, що:

  • Послідовність програм ніколи не повинна повертати одну і ту ж дошку двічі, повинна охоплювати всі можливі рішення проблеми розміру n і врешті-решт повинна припинятися (не даючи результатів).
  • Ви можете повернути два значення, повернути одне і надрукувати друге, або роздрукувати два значення повернення.
  • Однак якщо ви друкуєте і плату, і наступну програму, вона не повинна вважатися частиною наступної програми (я б рекомендував друкувати дошку в коментарі або використовувати як стандартні потоки виводу, так і помилки).
  • Значення програми як повернення повинно бути рядком, а не закриттям.

Формат дошки

  • Дошка - квадрат розміром n .
  • Стільниця комітету може бути порожньою, королевою чи лицарем.
  • Ви повинні вибрати різні значення для кожного виду комірок (тобто ви можете використовувати інші символи, ніж Q, 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символи, які порожні клітини різних видів (див моя відповідь нижче). Я рахую 2836 дощок за n = 6 , як у відповіді Sleafar (я вніс помилку при зменшенні кількості байтів, але це тепер виправлено).

Велике спасибі Sleafar за те, що він знайшов не один, а два помилки в моєму коді.

Оцінка

Найкоротший код виграти в байтах.

Вимірюємо розмір першої програми, тієї, яка приймає n .


1 . Королеви та лицарі , від Roger KW Hui (будьте уважні! Містить рішення)


4
Можливо, ви повинні поставити за це щедрість. Чесно кажучи, проблема є досить складною без частин.
mbomb007

Чи можемо ми використовувати будь-які символи, окрім Q, N та - для позначення Королеви та Лицарів та порожніх, якщо вони відрізняються?
Фаталізувати

@Fatalize Так, звичайно
coredump

1
@coredump Я мав на увазі читання вмісту функції. І я прийму це як "так, вам дозволяється читати власний вихідний код та / або вміст функції". (Моє рішення покладається на це, тому ...)
wizzwizz4

1
@coredump Якщо я правильно розумію виклик, то ваше довідкове рішення для n = 6 містить невірні записи (наприклад -------------------------N--------Q-, недійсне, оскільки можна додати більше фрагментів :) Q--------N---------------N--------Q-.
Sleafar

Відповіді:


2

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

Наступний сценарій може бути використаний для автоматизованого тестування (надайте n в якості аргументу знову):

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

Квінефікація

Тут я використовував дуже простий підхід, щоб розмір коду був низьким.

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

Змінна X містить індекс рішення для друку наступного. Y містить модифіковану копію алгоритму вище, яка використовується для обчислення всіх рішень, а потім вибирає лише одне з них, що є причиною його настільки повільного. Перевага цього рішення полягає в тому, що воно не потребує особливого додаткового коду. Код, що зберігається в Y , виконується за допомогою Eval класу (справжня quine не потрібна).

Змінений код друкує рішення, на яке вказує X , збільшує X і додає копію самого себе:

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

Я також намагався вивести всі рішення як код для другого кроку, але для n = 6 він створював занадто багато коду для Groovy для обробки.


Гарна відповідь, хороша робота.
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 - для лицарів, а все інше означає порожню клітинку, за винятком того, що є більше інформації, яка зберігається всередині. Якщо ми скопіюємо повернуту функцію до repl, отримаємо нову функцію.

#<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. Так само, лицарі, доступні лише королевам, безпечні для інших лицарів. Значення розрядні і -ед, щоб представляти можливі рухи, і деякі комірки доступні без будь-якого елемента.

Точніше, ось послідовність дощок, що ведуть до наступного рішення (зліва направо), де вільні комірки поступово обмежуються різними значеннями:

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

У мене були різні ідеї зробити послідовні лайки. Найпростіший - це, мабуть, сформувати всі рішення спочатку у вигляді списку рядків та записати послідовні лайки, які з’являються із цього списку в кожному поколінні. Однак це, здається, не було коротшим, ніж сучасний підхід. Крім того, я намагався переписати рекурсивний код за допомогою спеціального стеку та скидати всі змінні стану кожного разу, коли я знаходжу рішення; мета полягає в тому, що наступний крок може бути оброблений як продовження поточного кроку. Можливо, це краще підходить для мови на основі стека. Поточний досить простий і покладається на загальні змінні зчитувача Lisp, якими завжди цікаво користуватися.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.