Gere o conjunto de permutações de pré-adição-adição em ordem lexicograficamente classificada

14

Defina uma sequência de comprimento de pré-acréscimo-acréscimon para ser uma permutação dos números 1, 2, ..., nque podem ser gerados pelo seguinte procedimento:

  • Comece com o número 1.

  • Para cada número a partir 2de n, colocar este número para o início ou no final da sequência (quer preceder ou acrescentar que, daí o nome da sequência).

Por exemplo, esta é uma maneira válida de gerar uma sequência de pré-acréscimo-acréscimo de comprimento 4:

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

Sua tarefa é criar um programa ou função que levará um número nde 3para 30como entrada e imprimir ou retornar todas as sequências de comprimento de pré-apêndice a fim nem ordem lexicográfica (se você estiver produzindo seqüências de caracteres e não listas, os números acima de 9 serão representados como letras a-u, para preservar o comprimento da string). Por exemplo, é esse pedido para n = 4:

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

Em geral, existem 2 permutações de comprimento pré-anexado n-1n .

Você não pode usar nenhuma função de classificação interna no seu idioma no seu código. O programa mais curto para fazer isso em qualquer idioma vence.

Joe Z.
fonte
Não sou fã do requisito de formato de saída, em particular a conversão em letras a-u. Podemos apenas produzir listas de números?
Xnor
3
Você pode aceitar a resposta depois de algum tempo, pois algumas pessoas tendem a não responder a uma pergunta se ela tiver uma resposta aceita.
Optimizer
1
Então você tem resposta aceita errado ..
Optimizer
2
FryAmTheEggman postou sua resposta 21 minutos antes de você editar a sua.
Joe Z.
2
@Optimizer Não acho que seja a maneira mais estranha - a resposta de FryAmTheEggman foi de 19 bytes de comprimento 21 minutos antes da sua. Isso torna a resposta mais curta postada mais cedo.
Joe Z.

Respostas:

10

CJam, 22 20 19 17 bytes

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

Expansão do código :

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

Como funciona :

Esta é uma versão de depuração do código:

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

Vamos ver como ele funciona para entrada 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>|}/";

Experimente online aqui

Optimizer
fonte
6

Haskell, 47 bytes

f 1=[[1]]
f n=(\x->map(++[n])x++map(n:)x)$f$n-1
alefalpha
fonte
1
Mudar para a compreensão da lista economiza alguns bytes: f n=[[n:x,x++[n]]|x<-f$n-1]>>=id(usando a função concat code-golfers >>=id).
N
1
@nimi mas sua na ordem r errado
haskeller orgulhosos
@proudhaskeller: Oh, querida, não leu as especificações com cuidado. Tentei consertá-lo e encontrei quatro maneiras ligeiramente diferentes, todas do mesmo tamanho da versão do @ alephalpha, por isso não posso oferecer uma melhoria. 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)]

Mostra uma lista de listas de números.

Uma solução recursiva. Para n==1saída [[1]]. Caso contrário, adicione nno início ou no final de todas (n-1)aspermutações. A pré-anexação torna a permutação lexicograficamente mais tarde que a anexação, para que as permutações permaneçam ordenadas.

O "Booleano" bcodifica se você deve colocar [n]no início ou no final. Na verdade, movemos o resto da lista xna expressão x*b+[n]+x*-b. Colocar bcomo -1ou 1vamos usar flip negando, pois uma lista multiplicada por -1é a lista vazia.

xnor
fonte
4

Pyth, 19

usCm,+dH+HdGr2hQ]]1

Experimente online aqui

Este é um programa completo que recebe a entrada do stdin.

Isso funciona de maneira semelhante à solução do xnor, mas gera os valores um pouco fora de ordem e, portanto, eles devem ser reordenados. O que acontece em cada nível é que cada lista anterior de valores tem o novo valor adicionado ao final e ao início, e estes são agrupados em duas tuplas, agrupados em uma lista. Por exemplo, a primeira etapa faz isso:

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

Em seguida, essa lista de tuplas é compactada (e depois somada para remover a lista mais externa). No primeiro caso, isso fornece apenas o valor desembrulhado de cima, pois há apenas um valor na lista.

Passos mostrando 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
fonte
2

Mathematica, 57 54 49 bytes

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

Exemplo:

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

alefalpha
fonte
2

J, 26 bytes

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

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

Aprimoramento de 1 byte graças ao FUZxxl .

randomra
fonte
Substitua ,.por ,"1um caractere.
FUZxxl
1

Pyth, 34 33 31 29

Basicamente, uma tradução de xnor 's resposta Python . Ainda não sou bom com Pyth, por isso sugestões de melhoria são bem-vindas.

Define uma função ypara retornar uma lista de listas de números inteiros.

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

Atualização: salvou 2 bytes graças a FryAmTheEggman .

Explicação:

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
fonte
Algumas coisas pyth: -b1pode ser tb, [1_1)pode ser ,1_1(no entanto, você pode simplesmente largar o colchete próximo, pois só precisa contar os bytes necessários para criar a função, mesmo que você não possa chamá-lo sem fechá-lo), e você não é necessário bagrupar uma lista, pois o pyth se converte automaticamente em lista ao adicionar uma lista a um int.
FryAmTheEggman
Eu vim com uma maneira de salvar vários bytes manualmente, fazendo o segundo mapa [1,-1]. Posso salvar bytes para codificar algo tão curto, especialmente quando você simplifica a lógica. Eu receboL?]]1<b2sCm,+db+bdytb
FryAmTheEggman
@FryAmTheEggman Você pode realmente querer adicionar isso como sua própria resposta. Isso é demais.
PurkkaKoodari
OK, eu queria tentar vencer o CJam antes de postar, mas acho que o truque do zip é interessante o suficiente para merecer publicá-lo. Boa sorte com Pyth;)
FryAmTheEggman
1

Pure Bash, 103

Mais do que eu esperava:

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

JavaScript (ES6) 73 80

Implementação de JavaScript da boa solução do @ Optimizer.

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

Teste no 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
fonte
0

Minha solução 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
fonte
Oh fark, agora, depois de ver as outras respostas, entendo o que você quer dizer com resposta mais curta.
Brett Ryan
2
Embora sua solução seja respeitável, concisa e bem apresentada por si só, você está certo de que não é uma candidata ao problema em questão.
Joe Z.
1
@BrettRyan Você pode tornar seu código muito mais curto removendo espaços em branco desnecessários e usando nomes de variáveis ​​com um único caractere. Você também pode substituir falsepor algo como 5<4.
ProgramFOX
1
Obrigado rapazes. Foi minha primeira tentativa de participar de desafios de código. Eu estava apenas procurando alguns desafios de programação e não percebi que o objetivo era obter a solução mais curta. :) Obrigado por me deixar participar.
Brett Ryan