Générer l'ensemble des permutations pré-ajout-ajout dans un ordre trié lexicographiquement

14

Définissez une séquence de longueur pré-ajoutée-ajoutéen comme une permutation des nombres 1, 2, ..., npouvant être générés par la procédure suivante:

  • Commencez par le nombre 1.

  • Pour chaque numéro de 2la n, placez ce numéro au début ou à la fin de la séquence (soit précédez ou append , d' où le nom de la séquence).

Par exemple, c'est un moyen valide pour générer une séquence de pré-ajout-ajout de longueur 4:

1
21     [beginning]
213    [end]
2134   [end]

Votre tâche consiste à créer un programme ou une fonction qui prendra un nombre nde 3à 30en entrée, et à imprimer ou renvoyer toutes les séquences de longueur de pré-ajout-ajout ndans l'ordre lexicographique (si vous sortez des chaînes et non des listes, les nombres supérieurs à 9 seront représentés sous forme de lettres a-u, pour conserver la longueur de la chaîne). Par exemple, voici cette commande pour n = 4:

1234  [RRR]
2134  [LRR]
3124  [RLR]
3214  [LLR]
4123  [RRL]
4213  [LRL]
4312  [RLL]
4321  [LLL]

En général, il existe 2 n-1 permutations de longueur pré-ajoutée-ajoutée n.

Vous ne pouvez pas utiliser de fonctions de tri intégrées dans votre langue dans votre code. Le programme le plus court pour le faire dans n'importe quelle langue gagne.

Joe Z.
la source
Je ne suis pas fan de l'exigence de format de sortie, en particulier de la conversion en lettres a-u. Pouvons-nous simplement sortir des listes de nombres?
xnor
3
Vous voudrez peut-être accepter la réponse après un certain temps car certaines personnes ont tendance à ne pas répondre à une question si elle a une réponse acceptée.
Optimizer
1
Donc, vous avez une mauvaise réponse acceptée ..
Optimizer
2
FryAmTheEggman a publié sa réponse 21 minutes avant de modifier la vôtre.
Joe Z.
2
@Optimizer Je ne pense pas que ce soit la façon la plus étrange - la réponse de FryAmTheEggman était de 19 octets, 21 minutes avant la vôtre. Cela en fait la réponse la plus courte publiée le plus tôt.
Joe Z.

Réponses:

10

CJam, 22 20 19 17 octets

]]l~{)f+_1fm>|}/p

Expansion du code :

]]                   "Put [[]] onto stack. What we will do with this array of array is";
                     "that in each iteration below, we will first append the next";
                     "number to all present arrays, then copy all the arrays and";
                     "move the last element to first in the copy";
  l~                 "Read input number. Lets call it N";
    {         }/     "Run this code block N times ranging from 0 to N - 1";
     )f+             "Since the number on stack starts from 0, add 1 to it and append";
                     "it to all arrays in the array of array beginning with [[]]";
        _1fm>        "Copy the array of array and move last element from all arrays";
                     "to their beginning";
             |       "Take set union of the two arrays, thus joining them and eliminating";
                     "duplicates. Since we started with and empty array and started adding";
                     "numbers from 1 instead of 2, [1] would have appeared twice if we had";
                     "simply done a concat";
                p    "Print the array of arrays";

Comment ça marche :

Il s'agit d'une version de débogage du code:

]]l~ed{)edf+ed_ed1fm>ed|ed}/edp

Voyons comment cela fonctionne pour la saisie 3:

[[[]] 3]                                 "]]l~"            "Empty array of array and input";
[[[]] 1]                                 "{)"              "First iteration, increment 0";
[[[1]]]                                  "{)f+"            "Append it to all sub arrays";
[[[1]] [[1]]]                            "{)f+_"           "Copy the final array of array";
[[[1]] [[1]]]                            "{)f+_1fm>"       "shift last element of each";
                                                           "sub array to the beginning";
[[[1]]]                                  "{)f+_1fm>|}"     "Take set based union";
[[[1]] 2]                                "{)"              "2nd iteration. Repeat";
[[[1 2]]]                                "{)f+"
[[[1 2]] [[1 2]]]                        "{)f+_";
[[[1 2]] [[2 1]]]                        "{)f+_1fm>";
[[[1 2] [2 1]]]                          "{)f+_1fm>|}";
[[[1 2] [2 1]] 3]                        "{)";
[[[1 2 3] [2 1 3]]]                      "{)f+"
[[[1 2 3] [2 1 3]] [[1 2 3] [2 1 3]]]    "{)f+_";
[[[1 2 3] [2 1 3]] [[3 1 2] [3 2 1]]]    "{)f+_1fm>";
[[[1 2 3] [2 1 3] [3 1 2] [3 2 1]]]      "{)f+_1fm>|}";
[[[1 2 3] [2 1 3] [3 1 2] [3 2 1]]]      "{)f+_1fm>|}/";

Essayez-le en ligne ici

Optimiseur
la source
6

Haskell, 47 octets

f 1=[[1]]
f n=(\x->map(++[n])x++map(n:)x)$f$n-1
alephalpha
la source
1
Passer à la compréhension de la liste permet d'économiser quelques octets: f n=[[n:x,x++[n]]|x<-f$n-1]>>=id(en utilisant la fonction de concaténation code-golfers >>=id).
nimi
1
@nimi mais c'est dans le mauvais ordre r
fier haskeller
@proudhaskeller: Oh mon cher, je n'ai pas lu les spécifications assez attentivement. J'ai essayé de le réparer et j'ai trouvé quatre façons légèrement différentes de la même longueur que la version de @ alephalpha, donc je ne peux pas offrir d'amélioration. f n=[x++[n]|x<-f$n-1]++[n:x|x<-f$n-1], f n=map(++[n])(f$n-1)++[n:x|x<-f$n-1], f n=map(++[n])(f$n-1)++map(n:)(f$n-1),f n=(++[n])#n++(n:)#n;p#i=map p$f$i-1
Nimi
5

Python 2, 68

f=lambda n:[[1]]*(n<2)or[x*b+[n]+x*-b for b in[1,-1]for x in f(n-1)]

Produit une liste de listes de nombres.

Une solution récursive. Pour n==1, sortie [[1]]. Sinon, ajoutez nau début ou à la fin de toutes les (n-1)permutations. La pré-extension rend la permutation lexicographiquement plus tard que l'ajout, donc les permutations restent triées.

Le "booléen" bcode s'il faut mettre [n]au début ou à la fin. En fait, nous déplaçons le reste de la liste xdans l'expression x*b+[n]+x*-b. Mettre bas -1ou 1permet d'utiliser flip en niant, car une liste multipliée par -1est la liste vide.

xnor
la source
4

Pyth, 19

usCm,+dH+HdGr2hQ]]1

Essayez-le en ligne ici

Il s'agit d'un programme complet qui accepte les données de stdin.

Cela fonctionne de manière similaire à la solution de xnor, mais génère des valeurs un peu hors service, elles doivent donc être réorganisées. Ce qui se passe à chaque niveau, c'est que chaque liste de valeurs précédente a la nouvelle valeur ajoutée à la fin et au début et celles-ci sont chacune enveloppées dans un tuple 2 qui sont enveloppées ensemble dans une liste. Par exemple, la première étape fait ceci:

[[1]]
[([1,2], [2,1])]

Ensuite, cette liste de tuples est zippée (puis additionnée pour supprimer la liste la plus externe). Dans le premier cas, cela donne simplement la valeur non enveloppée d'en haut, car il n'y a qu'une seule valeur dans la liste.

Étapes indiquant 2-> 3:

([1,2], [2,1])
[([1,2,3],[3,1,2]),([2,1,3],[3,2,1])]
([1,2,3],[2,1,3],[3,1,2],[3,2,1])
FryAmTheEggman
la source
2

Mathematica, 57 54 49 octets

f@1={{1}};f@n_:=#@n/@f[n-1]&/@Append~Join~Prepend

Exemple:

f[4]

{{1, 2, 3, 4}, {2, 1, 3, 4}, {3, 1, 2, 4}, {3, 2, 1, 4}, {4, 1, 2, 3} , {4, 2, 1, 3}, {4, 3, 1, 2}, {4, 3, 2, 1}}

alephalpha
la source
2

J, 26 octets

   0|:<:((,,.,~)1+#)@[&0,.@1:

   (0|:<:((,,.,~)1+#)@[&0,.@1:) 3
1 2 3
2 1 3
3 1 2
3 2 1

Amélioration d'un octet grâce à FUZxxl .

randomra
la source
Remplacez ,.par ,"1un caractère.
FUZxxl
1

Pyth, 34 33 31 29

Fondamentalement, une traduction de la réponse Python de xnor . Je ne suis toujours pas génial avec Pyth, donc les suggestions d'amélioration sont les bienvenues.

Définit une fonction ypour renvoyer une liste de listes d'entiers.

L?]]1<b2smm++*kdb*k_dy-b1,1_1

Mise à jour: enregistré 2 octets grâce à FryAmTheEggman .

Explication:

L                                  define a function y with argument b that returns
 ?*]]1<b2                          [[1]] if b < 2 else
         s                         sum(
          m                        map(lambda d:
           m                       map(lambda k:
            ++*kdb*k_d             k*d + [b] + k*-d
                      y-b1         , y(b - 1))
                          ,1_1)    , (1, -1))
PurkkaKoodari
la source
Quelques trucs en pyth: -b1peut être tb, [1_1)peut être ,1_1(cependant vous pouvez simplement supprimer le crochet de fermeture car il vous suffit de compter les octets nécessaires pour créer la fonction, même si vous ne pourrez pas l'appeler sans la fermer), et vous vous n'avez pas besoin d'envelopper bdans une liste car pyth se convertit automatiquement en liste lors de l'ajout d'une liste à un int.
FryAmTheEggman
J'ai trouvé un moyen d'économiser plusieurs octets en effectuant manuellement la deuxième carte [1,-1]. Je peux enregistrer des octets pour coder en dur quelque chose d'aussi court, surtout lorsque vous simplifiez la logique. Je reçoisL?]]1<b2sCm,+db+bdytb
FryAmTheEggman
@FryAmTheEggman Vous voudrez peut-être ajouter cela comme votre propre réponse. C'est tout simplement génial.
PurkkaKoodari
OK, je voulais essayer de battre CJam avant de poster mais je suppose que l'astuce zip est suffisamment intéressante pour mériter de l'afficher. Bonne chance avec Pyth;)
FryAmTheEggman
1

Pure Bash, 103

Plus longtemps que je ne l'avais espéré:

a=1..1
for i in {2..9} {a..u};{
((++c<$1))||break
a={${a// /,}}
a=`eval echo $a$i $i$a`
}
echo ${a%%.*}
Traumatisme numérique
la source
1

JavaScript (ES6) 73 80

Implémentation JavaScript de la belle solution de @ Optimizer.

Récursif (73):

R=(n,i=1,r=[[1]])=>++i>n?r:r.map(e=>r.push([i,...e])+e.push(i))&&R(n,i,r)

Itératif (74):

F=n=>(i=>{for(r=[[1]];++i<=n;)r.map(e=>r.push([i,...e])+e.push(i))})(1)||r

Tester dans la console Firefox / FireBug

R(4)

[[1, 2, 3, 4], [2, 1, 3, 4], [3, 1, 2, 4], [3, 2, 1, 4], [4, 1, 2, 3] , [4, 2, 1, 3], [4, 3, 1, 2], [4, 3, 2, 1]]

edc65
la source
0

Ma solution Java:

public static void main(String[] args) {
    listPrependAppend(4);
}

private static void listPrependAppend(int n) {
    int total = (int) Math.pow(2, n - 1);
    int ps;
    boolean append;
    String sequence;
    String pattern;

    for (int num = 0; num < total; num++) {
        sequence = "";
        pattern = "";
        append = false;
        ps = num;
        for (int pos = 1; pos < n + 1; pos++) {
            sequence = append ? (pos + sequence) : (sequence + pos);
            append = (ps & 0x01) == 0x01;
            ps = ps >> 1;
            if (pos < n) {
                pattern += append ? "L" : "R";
            }
        }
        System.out.format("%s\t[%s]%n", sequence, pattern);
    }
}
Brett Ryan
la source
Oh fark, maintenant après avoir vu les autres réponses, je vois ce que vous entendez par réponse la plus courte.
Brett Ryan
2
Bien que votre solution soit respectable, concise et bien présentée à part entière, vous avez raison de dire qu'elle n'est pas tout à fait un candidat pour le problème en question.
Joe Z.
1
@BrettRyan Vous pouvez raccourcir votre code en supprimant les espaces inutiles et en utilisant des noms de variable à un caractère. Vous pouvez également remplacer falsepar quelque chose comme 5<4.
ProgramFOX
1
Merci les gars. C'était ma première tentative de participer à des défis de code. Je cherchais simplement des défis de programmation et je ne savais pas que l'objectif était d'obtenir la solution la plus courte. :) Merci de me laisser participer.
Brett Ryan