N-reine-et-équine quine

21

Il existe une variante du problème bien connu des N-reines qui implique des reines et des chevaliers et serait "beaucoup plus difficile" 1 . L'énoncé du problème est le suivant:

Vous devez placer un nombre égal de chevaliers ♞ et de reines ♛ sur un échiquier de sorte qu'aucune pièce n'attaque aucune autre pièce. Quel est le nombre maximum de pièces que vous pouvez placer sur le plateau et combien de façons différentes pouvez-vous le faire?

Dans ce défi de , vous recevrez une entrée n comprise entre 3 et 32 ​​(de la manière la plus adaptée à votre langue). Pour un n donné , il peut y avoir zéro ou plusieurs solutions au problème ci-dessus. Dans le cas où il n'y a pas de solution, vous ne devez rien produire / renvoyer ( nil , chaîne vide , false , ...). Sinon, vous devez donner deux résultats:

  1. Un plateau de solution (voir ci-dessous) pour la taille n où il n'est pas possible d'ajouter une pièce d'échecs reine ou chevalier sans qu'aucune pièce ne soit attaquée. Il doit y avoir un nombre égal de reines et de chevaliers .
  2. La source d'un programme à exécuter qui n'accepte aucune entrée et donne (i) une autre solution (ou rien ) pour la même taille n , dans le même format, ainsi que (ii) un autre programme pour la solution suivante (et ainsi de suite) ...).

Notez que:

  • La séquence de programmes ne doit jamais renvoyer la même carte deux fois, doit couvrir toutes les solutions possibles au problème de taille n et doit finalement se terminer (ne produire aucune sortie).
  • Vous pouvez soit renvoyer deux valeurs, renvoyer l'une et imprimer l'autre, soit imprimer les deux valeurs de retour.
  • Cependant , si vous imprimez à la fois la carte et le programme suivant, la carte ne doit pas être considérée comme faisant partie du programme suivant (je recommanderais d'imprimer la carte en commentaire ou d'utiliser à la fois la sortie standard et les flux d'erreur).
  • Le programme en tant que valeur de retour doit être une chaîne et non une fermeture.

Format du conseil

  • Une planche est un carré de taille n .
  • Une cellule de conseil peut être vide, une reine ou un chevalier.
  • Vous devez choisir des valeurs distinctes pour chaque type de cellules (c'est-à-dire que vous pouvez utiliser d'autres symboles que Q, N lors de l'impression du tableau).
  • Si vous retournez un tableau non-string, il doit s'agir d'une collection ordonnée des n 2 valeurs du tableau (par exemple, matrice, vecteur ou liste dans l'ordre principal ligne / colonne, ...).
  • Si vous imprimez le tableau, vous pouvez l'imprimer au carré ou en ligne. Par exemple, une carte de solution de taille 4 peut être imprimée comme suit (espaces non requis; symboles à votre discrétion):

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

    Si vous le sentez, vous pouvez également générer:

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

    ... mais cela suffit:

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

    Peu importe si vous parcourez les cellules dans un ordre de ligne ou de colonne, car il existe des solutions symétriques. Par exemple, les solutions pour n = 4 sont:

    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
    

Vous pouvez également regarder les solutions pour n = 5 sous forme de matrices ; les planches contient #, qet des nsymboles qui sont des cellules vides de différents types (voir ma réponse ci - dessous). Je compte 2836 cartes pour n = 6 , comme dans la réponse de Sleafar (j'ai introduit un bug lors de la réduction du nombre d'octets, mais il est maintenant corrigé).

Un grand merci à Sleafar pour avoir trouvé non pas un mais deux bugs dans mon code.

But

Le code le plus court en octets gagne.

Nous mesurons la taille du premier programme, celui qui accepte n .


1 . Queens and Knights , par Roger KW Hui (attention! Contient une solution)

coredump
la source
4
Vous devriez peut-être mettre une prime à ce sujet. Honnêtement, le problème est assez difficile sans la partie quine.
mbomb007
Pouvons-nous utiliser des symboles autres que Q, N et - pour désigner les reines et les chevaliers et vides, tant qu'ils sont distincts?
Fatalize
@Fatalize Oui, bien sûr
coredump
1
@coredump, je voulais dire lire le contenu de la fonction. Et je prendrai cela comme un "oui, vous êtes autorisé à lire votre propre code source et / ou contenu de fonction". (Ma solution en dépend, alors ...)
wizzwizz4
1
@coredump Si je comprends bien le défi, alors votre solution de référence pour n = 6 contient des entrées invalides (par exemple, elle -------------------------N--------Q-n'est pas valide car plus de morceaux peuvent être ajoutés :) Q--------N---------------N--------Q-.
Sleafar

Réponses:

2

Groovy, 515 octets

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

Essai

Fournissez n comme argument de ligne de commande:

groovy qak.groovy 4

La première ligne de la sortie est toujours une solution sous forme de commentaire (0 = vide, 1 = reine, 2 = chevalier), suivie du code de la deuxième ligne:

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

Le script suivant peut être utilisé pour des tests automatisés (fournissez à nouveau n comme argument):

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

Parce que j'ai essayé de rendre la solution aussi petite que possible, elle est très lente (voir ci-dessous pour plus de détails). J'ai testé seulement n = 4 avec cette version pour voir si la quineification fonctionne.

Résultats

n = 4: 40 solutions ( format converti )
n = 5: 172 solutions ( format converti )
n = 6: 2836 solutions ( format converti )

Algorithme

Il s'agit d'une version non quine légèrement non golfée de la solution:

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

J'ai utilisé une approche très simple ici pour garder la taille du code faible.

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

La variable X contient l'index de la solution à imprimer ensuite. Y contient une copie modifiée de l'algorithme ci-dessus, qui est utilisée pour calculer toutes les solutions, puis sélectionner une seule d'entre elles, ce qui est la raison de sa lenteur. L'avantage de cette solution est qu'elle ne nécessite pas beaucoup de code supplémentaire. Le code stocké dans Y est exécuté à l'aide de la classe Eval (un vrai quine n'est pas requis).

Le code modifié imprime la solution pointée par X , augmente X et ajoute une copie de lui-même:

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

J'ai également essayé de sortir toutes les solutions sous forme de code pour la deuxième étape, mais pour n = 6, cela produisait trop de code pour Groovy.

Sleafar
la source
Belle réponse, bon travail.
coredump
6

Lisp commun, 737

auto-réponse

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

Exemple

Collez ce qui précède dans le REPL, qui renvoie un objet fonction:

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

Appelez-le (l'étoile est liée à la dernière valeur renvoyée):

QN> (funcall * 4)

Cela imprime les éléments suivants sur la sortie standard:

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

De plus, la valeur renvoyée par cette fonction est:

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

... qui est un littéral de tableau. Le numéro 5 représente les reines, 6 pour les chevaliers et tout le reste représente une cellule vide, sauf qu'il y a plus d'informations stockées en interne. Si nous copions-collons la fonction retournée dans la repl, nous obtenons une nouvelle fonction.

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

Et nous pouvons l'appeler sans arguments:

QN> (funcall * )

Cet appel renvoie une nouvelle solution #(5 0 0 0 0 0 0 2 0 0 0 6 0 0 2 0)et la source d'une autre fonction (non représentée ici). Si la fonction d'origine ou la dernière générée ne trouve pas de solution, rien n'est imprimé et rien n'est retourné.

Valeurs internes

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

J'avais l'habitude de générer trop peu de solutions. Maintenant, je propage quelle cellule est sans danger pour une reine et pour un chevalier, indépendamment. Par exemple, voici une sortie pour n = 5 avec une jolie impression:

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

Lorsque nous avons placé la reine Q, les positions éloignées de cette reine sont toujours sans danger pour les reines et désignées q. De même, les chevaliers qui ne sont accessibles que par les reines sont sans danger pour les autres chevaliers. Les valeurs sont binaires et -ed pour représenter les mouvements possibles et certaines cellules sont accessibles par aucun type de pièce.

Plus précisément, voici la séquence de cartes menant à la solution suivante (de gauche à droite), où les cellules libres sont progressivement contraintes avec différentes valeurs:

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

Approche non quine

Version non golfée, commentée

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

Doublons et bogues

Ma toute première solution a généré des solutions en double. Afin de le résoudre, j'ai introduit deux compteurs pour les reines et les chevaliers. Le compteur pour les reines (resp. Chevaliers) garde une trace de la première position dans le tableau où une reine (resp. Chevalier) existe: j'ajoute une reine (resp. Un chevalier) uniquement aux positions qui suivent cette position minimale.

Cette méthode m'empêche de revoir les solutions qui ont déjà été trouvées dans les itérations précédentes, car j'itère avec une position de reine (resp. Chevalier) croissante.

Cependant, Sleafar a remarqué qu'il y avait des solutions pour lesquelles il pourrait y avoir de la place pour les reines et les chevaliers, ce qui est contraire aux règles. Pendant un certain temps, j'ai pensé que je devais revenir à une recherche normale et stocker toutes les solutions connues pour éviter les doublons, qui semblaient trop coûteux (à la fois en termes d'octets et d'utilisation de la mémoire).

Au lieu de cela, voici ce que je fais maintenant: quand une carte de solution potentielle est trouvée, j'essaie d'ajouter exactement une reine et un chevalier, sans prendre en compte les compteurs (c'est-à-dire pour toutes les cellules sur la carte). Si cela est possible, la carte actuelle est une copie de la précédente et je rejette la solution.

Les tests

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

J'ai eu différentes idées pour faire des quines successifs. Le plus simple est probablement de générer d'abord toutes les solutions sous forme de liste de chaînes et d'écrire des quines séquentielles qui apparaissent à partir de cette liste à chaque génération. Cependant, cela ne semble pas être plus court que l'approche actuelle. Alternativement, j'ai essayé de réécrire le code récursif avec une pile personnalisée et de vider toutes les variables d'état chaque fois que je trouve une solution; l'objectif est que l'étape suivante puisse être traitée comme une continuation de l'étape actuelle. Peut-être que ce serait mieux adapté à un langage basé sur la pile. La version actuelle est assez simple et repose sur des variables de lecteur Common Lisp, qui sont toujours amusantes à utiliser.

coredump
la source