Construire un permuter

9

Pour ce défi, vous allez créer une fonction (votre fonction peut être un programme complet) qui prend une liste en entrée et renvoie une permutation de cette liste. Votre fonction doit respecter les exigences suivantes.

  • Elle doit être déterministe.

  • Composer votre fonction avec elle-même un nombre variable de fois devrait être capable d'obtenir une liste de n'importe laquelle de ses permutations.

Il s'agit d'une question de code-golf, donc les réponses seront notées en octets, avec moins d'octets étant mieux.

Règles supplémentaires

  • Vous pouvez prendre tout type de liste, ( [Integer], [String], [[Integer]]) aussi longtemps qu'il

    • Peut être non vide
    • Peut contenir des objets distincts avec au moins 16 valeurs possibles. (Vous ne pouvez pas utiliser un Haskell [()]et prétendre que votre fonction est id)
    • Peut contenir des objets en double (pas d'ensembles)
  • Vous pouvez écrire un programme ou une fonction, mais vous devez respecter les E / S standard.

Ad Hoc Garf Hunter
la source
Mais S_nn'est cyclique que pourn<3
Leaky Nun
@LeakyNun, ce n'est pas demander une seule permutation qui génère le groupe symétrique: c'est demander une next_permutationfonction.
Peter Taylor
Serait-il suffisant de ne permuter que les listes de 0 et de 1?
xnor
Je ne suis pas sûr de comprendre l'intérêt de cette restriction. Si vous autorisez des listes de booléens, quel est l'intérêt de ne pas autoriser les itérables sur deux éléments distincts?
Dennis
@Dennis Vous faites valoir un bon argument. Je rejetterai les listes de booléens. Ou des types qui ont moins de 16 valeurs possibles.
Ad Hoc Garf Hunter

Réponses:

4

CJam (11 octets)

{_e!_@a#(=}

Démo en ligne montrant le cycle complet d'une liste de quatre éléments avec un élément en double.

Dissection

{      e# Define a block
  _e!  e#   Find all permutations of the input. Note that if there are duplicate
       e#   elements in the input then only distinct permutations are produced.
       e#   Note also that the permutations are always generated in lexicographic
       e#   order, so the order is independent of the input.
  _@a# e#   Find the index of the input in the list
  (=   e#   Decrement and get the corresponding element of the list
       e#   Incrementing would also have worked, but indexing by -1 feels less
       e#   wrong than indexing by the length, and makes this more portable to
       e#   GolfScript if it ever adds a "permutations" built-in
}
Peter Taylor
la source
2

Mathematica + Combinatorica (package intégré) 34 octets

19 octets pour charger le package et 15 pour la fonction.

<<"Combinatorica`";NextPermutation

Usage:

%@{c, b, a}

Sans le intégré, 61 octets

Extract[s=Permutations[Sort@#],Mod[s~Position~#+1,Length@s]]&

Combinatorica est censé être entièrement intégré à Mathematica, mais je pense que la fonction NextPermutation a été négligée.

Kelly Lowder
la source
2

C ++, 42 octets

#include <algorithm>
std::next_permutation

Cette opération exacte est intégrée dans C ++.

orlp
la source
2
Pourquoi l'espace après #include?
Yytsi
2

JavaScript (ES6), 145 139 137 134 108 octets

25 octets sauvés grâce à @Neil!

Prend la saisie sous forme de tableau de caractères alphabétiques. Renvoie la permutation suivante sous forme d'un autre tableau.

a=>(t=x=y=-1,a.map((v,i)=>v<a[i+1]?(t=v,x=i):y=i>x&v>t?i:y),a[x]=a[y],a[y]=t,a.concat(a.splice(x+1).sort()))

Comment?

Il s'agit d'une génération en ordre lexicographique qui traite les 4 étapes suivantes à chaque itération:

  1. Trouver le plus grand index X tel que a [X] <a [X + 1]

    a.map((v, i) => v < a[i + 1] ? (t = v, x = i) : ...)
  2. Trouver le plus grand indice Y supérieur à X tel que a [Y]> a [X]

    a.map((v, i) => v < a[i + 1] ? ... : y = i > x & v > t ? i : y)
  3. Échangez la valeur d' un [X] avec celle d' un [Y]

    a[x] = a[y], a[y] = t
  4. Trier la séquence de [X + 1] jusqu'à et y compris l'élément final, par ordre lexicographique croissant

    a.concat(a.splice(x + 1).sort())

Exemple:

pas

Démo

Arnauld
la source
Tu ne peux pas trier plutôt que renverser? Je pense aussi que vous v<a[i+1]&&(t=v,x=i)économisez un octet, et vous pourriez être en mesure de faire plus d'économies en utilisant spliceau lieu de deux slices.
Neil
@Neil Bonne prise!
Arnauld
Je pense que j'ai également pu fusionner les deux maps, pour 112 octets:a=>(t=x=y=-1,a.map((v,i)=>v<a[i+1]?(t=v,x=i):y=i>x&v>t?i:y),a[x]=a[y],a[y]=t,t=a.splice(++x).sort(),a.concat(t))
Neil
Je dois admettre que je ne pensais pas que ça a.concat(a.splice(++x).sort())allait marcher sinon j'aurais essayé ...
Neil
@Neil Merci! Mise à jour. (Avec 4 octets supplémentaires enregistrés car nous n'avons pas vraiment besoin de t pour concat () ).
Arnauld
1

Gelée , 6 octets

Œ¿’œ?Ṣ

Parcourt les permutations dans l'ordre lexicographique décroissant.

Essayez-le en ligne!

Comment ça fonctionne

Œ¿’œ?Ṣ  Main link. Argument: A (array)

Œ¿      Compute the permutation index n of A, i.e., the index of A in the
        lexicographically sorted list of permutations of A.
  ’     Decrement the index by 1, yielding n-1.
     Ṣ  Sort A.
   œ?   Getthe (n-1)-th permutation of sorted A.
Dennis
la source
1

C, 161 octets

Algorithme O (n) réel.

#define S(x,y){t=x;x=y;y=t;}
P(a,n,i,j,t)int*a;{for(i=n;--i&&a[i-1]>a[i];);for(j=n;i&&a[--j]<=a[i-1];);if(i)S(a[i-1],a[j])for(j=0;j++<n-i>>1;)S(a[i+j-1],a[n-j])}

Exemple d'utilisation:

int main(int argc, char** argv) {
    int i;
    int a[] = {1, 2, 3, 4};

    for (i = 0; i < 25; ++i) {
        printf("%d %d %d %d\n", a[0], a[1], a[2], a[3]);
        P(a, 4);
    }

    return 0;
}
orlp
la source
1

Python 2 , 154 octets

x=input()
try:exec'%s=max(k for k in range(%s,len(x))if x[%s-1]<x[k]);'*2%tuple('i1kjii');x[i-1],x[j]=x[j],x[i-1];x[i:]=x[:i-1:-1]
except:x.sort()
print x

Essayez-le en ligne!

Dennis
la source
Je pense que c'est plus court en tant que fonction qui permute la liste en place.
orlp
J'ai essayé cela, mais execj'ai donné toutes sortes d'erreurs dans une fonction
Dennis
0

Gelée , 10 octets

ṢŒ!Q©i⁸‘ị®

Essayez-le en ligne!

Trier> toutes les permutations> trouver une entrée> ajouter 1> indexer dans "toutes les permutations"

Leaky Nun
la source
@PeterTaylor Je l'ai corrigé.
Leaky Nun
Il existe des fonctions spécifiques pour les permutations (c'est-à-dire que vous pouvez simplement le faire Œ¿‘œ?Ṣ). Je n'avais pas envie de voler depuis, eh bien, même algo.
Erik the Outgolfer
@EriktheOutgolfer, cela peut être un peu compliqué pour les entrées qui contiennent des doublons.
Leaky Nun
Hmm ... Je suppose que oui, j'avais une version qui fonctionnait auparavant, mais vous semblez utiliser le Qtruc. Vous pouvez toujours jouer au golf ṢŒ!Qµi³‘ị.
Erik the Outgolfer
0

PHP , 117 octets

Prend entrée / sortie comme liste de chaînes de lettres inférieures

$a=str_split($s=$argn);rsort($a);if(join($a)!=$s)for($n=$s;($c=count_chars)(++$n)!=$c($s););else$n=strrev($s);echo$n;

Essayez-le en ligne!

Jörg Hülsermann
la source