Costruisci un Permuter


9

Per questa sfida hai intenzione di creare una funzione (la tua funzione potrebbe essere un programma completo) che accetta un elenco come input e restituisce una permutazione di tale elenco. La tua funzione deve rispettare i seguenti requisiti.

  • Deve essere deterministico.

  • Comporre la tua funzione con se stesso un numero variabile di volte dovrebbe essere in grado di ottenere un elenco di una qualsiasi delle sue permutazioni.

Questa è una domanda di code-golf, quindi le risposte verranno classificate in byte, con meno byte migliori.

Ulteriori regole

  • Si può prendere qualsiasi tipo di lista, ( [Integer], [String], [[Integer]]) purché

    • Può essere non vuoto
    • Può contenere oggetti distinti con almeno 16 possibili valori. (Non puoi usare un Haskell [()]e rivendicare la tua funzione id)
    • Può contenere oggetti duplicati (nessun set)
  • È possibile scrivere un programma o una funzione, ma è necessario rispettare l'IO standard.


Ma S_nè solo ciclico pern<3
Leaky Nun,

@LeakyNun, non richiede una singola permutazione che genera il gruppo simmetrico: sta chiedendo una next_permutationfunzione.
Peter Taylor,

Basterebbe solo permutare elenchi di 0 e 1?
xnor

Non sono sicuro di aver capito il punto di questa limitazione. Se consenti elenchi di booleani, qual è il punto di non consentire iterabili su due elementi distinti?
Dennis,

@Dennis Hai ragione. Non autorizzerò elenchi di booleani. O tipi che hanno meno di 16 possibili valori.
Ad Hoc Garf Hunter,

Risposte:


4

CJam (11 byte)

{_e!_@a#(=}

Demo online che mostra l'intero ciclo per un elenco di quattro elementi con un elemento duplicato.

Dissezione

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

2

Mathematica + Combinatorica (pacchetto integrato) 34 byte

19 byte per caricare il pacchetto e 15 per la funzione.

<<"Combinatorica`";NextPermutation

Uso:

%@{c, b, a}

Senza built-in, 61 byte

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

Si suppone che Combinatorica sia completamente integrata in Mathematica, ma penso che la funzione NextPermutation sia stata trascurata.



2

C ++, 42 byte

#include <algorithm>
std::next_permutation

Questa operazione esatta è integrata in C ++.


2
Perché lo spazio dopo #include?
Yytsi,

2

JavaScript (ES6), 145 139 137 134 108 byte

Salvataggio di ben 25 byte grazie a @Neil!

Accetta input come una matrice di caratteri alfabetici. Restituisce la permutazione successiva come un altro array.

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

Come?

Questa è una generazione in ordine lessicografico che elabora i 4 passaggi seguenti ad ogni iterazione:

  1. Trova l'indice più grande X in modo tale che una [X] <a [X + 1]

    a.map((v, i) => v < a[i + 1] ? (t = v, x = i) : ...)
  2. Trova l'indice più grande Y maggiore di X in modo tale che una [Y]> a [X]

    a.map((v, i) => v < a[i + 1] ? ... : y = i > x & v > t ? i : y)
  3. Scambia il valore di una [X] con quello di una [Y]

    a[x] = a[y], a[y] = t
  4. Ordina la sequenza da una [X + 1] fino all'elemento finale compreso, in ordine lessicografico crescente

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

Esempio:

passaggi

dimostrazione


Non puoi ordinare piuttosto che invertire? Inoltre penso che v<a[i+1]&&(t=v,x=i)risparmi un byte e potresti essere in grado di fare più risparmi usando spliceinvece di due slicesecondi.
Neil,

@Neil Buona cattura!
Arnauld,

Penso di essere stato in grado di unire anche le due maps, per 112 byte: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,

Devo ammettere che non pensavo che a.concat(a.splice(++x).sort())avrebbe funzionato altrimenti l'avrei provato ...
Neil,

@Neil Grazie! Aggiornato. (Con 4 più byte salvato perché non abbiamo davvero bisogno di t per concat () ).
Arnauld,

1

Gelatina , 6 byte

Œ¿’œ?Ṣ

Scorre le permutazioni in ordine lessicografico decrescente.

Provalo online!

Come funziona

Œ¿’œ?Ṣ  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.

1

C, 161 byte

Algoritmo O (n) effettivo.

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

Esempio di utilizzo:

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

1

Python 2 , 154 byte

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

Provalo online!


Penso che questo sia più breve in quanto funzione che consente l'elenco sul posto.
orlp,

Ci ho provato, ma execmi ha dato tutti i tipi di errori in una funzione
Dennis il

0

Gelatina , 10 byte

ṢŒ!Q©i⁸‘ị®

Provalo online!

Ordina> tutte le permutazioni> trova input> aggiungi 1> indice in "tutte le permutazioni


@PeterTaylor L'ho risolto.
Leaky Nun,

Ci sono builtin specifici per le permutazioni (cioè puoi semplicemente farlo Œ¿‘œ?Ṣ). Non mi andava di rubare poiché, beh, lo stesso algo.
Erik the Outgolfer,

@EriktheOutgolfer potrebbe essere un po 'disordinato per gli input che contengono duplicati.
Leaky Nun,

Hmm ... Immagino di sì, avevo una versione che funzionava in precedenza ma sembra che tu usi la Qcosa. Puoi ancora giocare a golf ṢŒ!Qµi³‘ị.
Erik the Outgolfer,


0

PHP , 117 byte

Accetta input / output come elenco di stringhe di lettere inferiori

$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;

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.