Generare l'insieme delle permutazioni di appendice in appendice in ordine lessicografico


14

Definire a sequenza di lunghezza appendice antepostan per essere una permutazione dei numeri 1, 2, ..., nche può essere generata dalla seguente procedura:

  • Inizia con il numero 1.

  • Per ogni numero da 2a n, posiziona questo numero all'inizio o alla fine della sequenza ( anteporre o aggiungi , quindi il nome della sequenza).

Ad esempio, questo è un modo valido per generare una sequenza antependente di lunghezza 4:

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

Il tuo compito è costruire un programma o una funzione che prenderà un numero nda 3a 30come input, e stampare o restituire tutte le sequenze antependenti di lunghezza nin ordine lessicografico (se stai producendo stringhe e non elenchi, i numeri sopra 9 saranno rappresentati come lettere a-u, per preservare la lunghezza della stringa). Ad esempio, questo è quell'ordine pern = 4 :

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

In generale, ci sono 2 n-1 permutazioni di lunghezza appendice prepend n.

Non è possibile utilizzare alcuna funzione di ordinamento integrata nella propria lingua nel proprio codice. Vince il programma più breve per farlo in qualsiasi lingua.


Non sono un fan del requisito del formato di output, in particolare della conversione in lettere a-u. Possiamo semplicemente produrre liste di numeri?
xnor

3
Potresti voler accettare la risposta dopo qualche tempo poiché alcune persone tendono a non rispondere a una domanda se ha una risposta accettata.
Ottimizzatore

1
Quindi hai sbagliato risposta accettata ..
Ottimizzatore

2
FryAmTheEggman ha pubblicato la sua risposta 21 minuti prima che tu modificassi la tua.
Joe Z.

2
@Optimizer Non credo proprio che sia il modo più strano - la risposta di FryAmTheEggman era di 19 byte e 21 minuti prima della tua. Ciò la rende la risposta più breve postata per prima.
Joe Z.

Risposte:


10

CJam, 22 20 19 17 byte

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

Espansione del codice :

]]                   "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";

Come funziona :

Questa è una versione di debug del codice:

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

Vediamo come funziona per l'input 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>|}/";

Provalo online qui


6

Haskell, 47 byte

f 1=[[1]]
f n=(\x->map(++[n])x++map(n:)x)$f$n-1

1
Passare alla comprensione dell'elenco salva alcuni byte: f n=[[n:x,x++[n]]|x<-f$n-1]>>=id(usando la funzione concat di golfisti del codice >>=id).
nimi

1
@nimi ma è nell'ordine sbagliato r
orgoglioso haskeller il

@proudhaskeller: Oh caro, non ho letto abbastanza attentamente le specifiche. Ho provato a risolverlo e ho trovato quattro modi leggermente diversi tutti della stessa lunghezza della versione di @ alephalpha, quindi non posso offrire un miglioramento. 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
Nome del modello

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

Emette un elenco di elenchi di numeri.

Una soluzione ricorsiva. Per n==1, output [[1]]. Altrimenti, aggiungi nall'inizio o alla fine di tutto(n-1) -mutazioni. Prepending rende la permutazione lessicograficamente più tardi rispetto all'aggiunta, quindi le permutazioni rimangono ordinate.

Il "booleano" bcodifica se mettere [n]all'inizio o alla fine. In realtà, spostiamo il resto dell'elenco xnell'espressione x*b+[n]+x*-b. Mettere bcome -1o 1consente di usare il flip negando, poiché un elenco moltiplicato per -1è l'elenco vuoto.


4

Pyth, 19

usCm,+dH+HdGr2hQ]]1

Provalo online qui

Questo è un programma completo che accetta input da stdin.

Funziona in modo simile alla soluzione di xnor, ma genera valori un po 'fuori servizio, quindi devono essere riordinati. Ciò che accade ad ogni livello è che ogni precedente elenco di valori ha il nuovo valore aggiunto alla fine e all'inizio e questi sono ciascuno racchiuso in una 2 tupla che sono raggruppati in un elenco. Ad esempio, il primo passo fa questo:

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

Quindi, questo elenco di tuple viene compresso (e quindi sommato per rimuovere l'elenco più esterno). Nel primo caso, questo dà solo il valore non imballato dall'alto, in quanto esiste un solo valore nell'elenco.

Passaggi che mostrano 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])

2

Mathematica, 57 54 49 byte

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

Esempio:

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


2

J, 26 byte

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

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

Miglioramento di 1 byte grazie a FUZxxl .


Sostituire ,.per ,"1per un carattere.
FUZxxl

1

Pyth, 34 33 31 29

Fondamentalmente una traduzione di XNOR 'il Python risposta . Non sono ancora bravo con Pyth, quindi i suggerimenti di miglioramento sono i benvenuti.

Definisce una funzione yper restituire un elenco di elenchi di numeri interi.

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

Aggiornamento: salvato 2 byte grazie a FryAmTheEggman .

Spiegazione:

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

Alcune cose di Pyth: -b1può essere tb, [1_1)può essere ,1_1(tuttavia puoi semplicemente rilasciare la parentesi chiusa poiché devi solo contare i byte necessari per rendere la funzione, anche se non sarai in grado di chiamarla senza chiuderla), e tu non è necessario racchiudere bun elenco poiché pyth si converte automaticamente in elenco quando si aggiunge un elenco a un int.
FryAmTheEggman,

Ho trovato un modo per salvare diversi byte eseguendo manualmente la seconda mappa [1,-1]. Posso salvare byte per hardcode qualcosa che è così breve, specialmente quando si semplifica la logica. RicevoL?]]1<b2sCm,+db+bdytb
FryAmTheEggman il

@FryAmTheEggman Potresti davvero volerlo aggiungere come risposta personale. È semplicemente fantastico.
PurkkaKoodari,

OK, volevo provare a battere CJam prima di pubblicare, ma immagino che il trucco zip sia abbastanza interessante da meritare di pubblicarlo. Buona fortuna con Pyth;)
FryAmTheEggman

1

Pure Bash, 103

Più a lungo di quanto sperassi:

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

1

JavaScript (ES6) 73 80

Implementazione JavaScript della bella soluzione di @ Optimizer.

Ricorsivo (73):

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

Iterativo (74):

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

Test nella 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]]


0

La mia soluzione 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);
    }
}

Oh scia, ora dopo aver visto le altre risposte capisco cosa intendi per risposta più breve.
Brett Ryan

2
Mentre la tua soluzione è rispettabile, concisa e ben presentata a pieno titolo, hai ragione nel dire che non è proprio un candidato per il problema in questione.
Joe Z.

1
@BrettRyan Puoi rendere il tuo codice molto più breve rimuovendo gli spazi bianchi non necessari e usando nomi di variabili a un carattere. Puoi anche sostituirlo falsecon qualcosa di simile 5<4.
Programma FOX

1
Grazie ragazzi. È stato il mio primo tentativo di partecipare alle sfide del codice. Stavo solo cercando alcune sfide di programmazione e non mi rendevo conto che l'obiettivo era quello di ottenere la soluzione più breve. :) Grazie per avermi permesso di partecipare.
Brett Ryan
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.