Gere todas as partições sublistadas

11

Dada uma lista não vazia de números inteiros, imprima todas as partições possíveis da lista em que cada partição é uma sublist não vazia.

Portanto, para a lista, [1, 2, 3, 4]o resultado é:

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

A ordem das listas na saída não importa; portanto, [[1, 2, 3, 4]]pode ser o primeiro, o último ou o local. A ordem dos elementos deve ser preservada.

Isso é código-golfe, então a resposta mais curta vence.


Relacionado: Particionar uma lista!

mbomb007
fonte
2
Podemos omitir o ambiente [...]no formato de saída? (Enquanto as partições são claramente separadas, por exemplo, por linefeeds.)
Martin Enders
Os formatos de entrada e saída são flexíveis, mas devem ser os mesmos. Portanto, se a lista de entrada tiver seus elementos em uma linha, as listas de saída também deverão.
Mbomb007
Não é isso que eu quero dizer. Dê uma olhada na resposta do Bash. Ele é usado :como separador de lista, mas na saída as próprias partições não são agrupadas em um par adicional de [...].
Martin Ender
Ou, perguntado de maneira diferente: no seu exemplo de formato no desafio, posso eliminar o primeiro [e o último ]de cada linha?
Martin Ender

Respostas:

13

Retina , 27 19 bytes

A contagem de bytes assume a codificação ISO 8859-1.

+1%`,
;$'¶$`];[
;
,

Experimente online!

Explicação

Obviamente, isso calcula todas as partições usando o processamento de strings. A idéia básica é que podemos gerar todas as partições decidindo para cada uma ,individualmente se queremos ou não dividir a lista lá. Esse tipo de coisa pode ser feito no Retina, combinando cada um ,por vez e usando uma substituição que fornece as duas saídas possíveis.

A entrada atua como o caso base: a partição em que todos os elementos ainda estão em uma única lista.

+1%`,
;$'¶$`];[

Agora +combinamos repetidamente ( ) a primeira ( 1) vírgula ( ,), em cada linha ( %) (tratando essa linha como uma sequência separada, que é relevante para $'e `` $ 1 `'na substituição).

Essa vírgula é substituída por:

;   A semicolon. This is just a stand-in for the comma, so we know we've already
    processed it and it won't be substituted again by the next iteration.
$'  Everything after the match. This completes the first (unchanged) version of
    the current line.
¶   A linefeed. Since the next iteration will scan for all lines again, this doubles
    the number of strings we're working with.
$`  Everything before the match. This completes the second (split) version of
    the current line.
];[ A semicolon around which we split the list.

Lembre-se de que tudo à frente da partida e depois da partida permanece na sequência de qualquer maneira, portanto o resultado completo é o $`;$'¶$`];[$'que explica por que inserimos o sufixo e o prefixo nessa ordem.

Esse loop é interrompido quando todas as vírgulas desaparecem.

;
,

Por fim, substitua os pontos e vírgulas por vírgulas novamente para corresponder ao formato de entrada.

Martin Ender
fonte
10

Pure Bash, 28

eval echo [${1//:/{:,]:[\}}]

Aqui, as listas são separadas por dois pontos e contidas entre colchetes. Por exemplo, na pergunta, a lista de entrada seria 1:2:3:4e a saída é:

[1:2:3:4] [1:2:3]:[4] [1:2]:[3:4] [1:2]:[3]:[4] [1]:[2:3:4] [1]:[2:3]:[4] [1]:[2]:[3:4] [1]:[2]:[3]:[4]

Experimente online .

  • ${1//:/REPLACEMENT}substitui os dois pontos $1por{:,]:[\}
  • Isso gera uma expansão de braçadeira como [1{:,]:[}2{:,]:[}3{:,]:[}4]
  • A avaliação (e \escapes cuidadosas ) faz com que a expansão da braçadeira aconteça por último e forneça o resultado desejado.

Se for necessário corresponder exatamente ao [[ , , ...]]formato fornecido , podemos fazer isso:

Pure Bash, 47

eval printf '%s\\n' ${1//, /{\\,\\ ,]\\,\\ [\}}

Experimente online .

Trauma Digital
fonte
6

Pitão , 2 bytes

./

Com entrada [1, 2, 3, 4](por exemplo).

Explicação : ./é o operador de partição. Retorna todas as divisões da lista de entrada em sub-listas disjuntas. A entrada é implicitamente fornecida ao programa.

Teste online!

Jim
fonte
6

05AB1E , 5 bytes

Œæʒ˜Q

Experimente online!

Œæʒ˜Q  Main link. Argument l
Œ      Get all sublists of l
 æ     Powerset of those lists
  ʒ˜Q  Filter: Keep the lists that when flattened equal the input
kalsowerus
fonte
1
Uau, esta é uma resposta muito legal!
Adnan
1
@ Adnan obrigado, também estou muito feliz com isso. Embora seja tudo, mas eficiente :)
kalsowerus
Boa resposta quando ainda não havia um builtin, +1 de mim! Deixando isso para qualquer pessoa que venha aqui no futuro, mas o 05AB1E agora possui um construtor de 2 bytes para obter todas as partições :: Experimente online.
Kevin Cruijssen 16/10
4

Python 3 , 82 72 66 bytes

f=lambda l:[k+[l[i:]]for i in range(len(l))for k in f(l[:i])]or[l]

Experimente online!

-5 bytes graças a @JonathanAllan

ovs
fonte
Oh meu, eu não posso ^ v novamente :( Eu realmente tentei algo como isso e não deu certo, eu devo ter ido em algum lugar errado.
Jonathan Allan
1
... caso em que cortar mais 5
Jonathan Allan
1
@JonathanAllan, muito obrigado! Eu poderia salvar outro byte reutilizando o lno final
ovs 18/05/19
Esta solução já existe aqui . Enviei uma mensagem para @feersum na TNB depois de postar a pergunta, para que ele tivesse a chance de publicá-la.
Mbomb007
Eu não quis dizer que você deveria desfazê-lo, só queria que você vencesse ele. A escolha é sua, é claro.
Mbomb007
4

Haskell , 59 55 49 bytes

p[x]=[[[x]]]
p(x:r)=do a:b<-p r;[(x:a):b,[x]:a:b]

Experimente online!

Solução recursiva. Exemplo de uso: p [1,2,3]retorna [[[1,2,3]],[[1,2],[3]],[[1],[2,3]],[[1],[2],[3]]].

-6 bytes graças ao xnor !

Laikoni
fonte
1
Você pode escrever a segunda linha mais curta com notação: do a:b<-p r;[(x:a):b,[x]:a:b](isso altera a ordem das listas).
Xnor
1
Além disso, <*>faz exatamente o que você deseja [\(a:b)->(x:a):b,([x]:)]<*>p r, embora seja mais longo do que doporque o primeiro lambda parece precisar de uma correspondência de padrão.
Xnor
3

J , 42 bytes

<@(</."1)~<:@#_&(][:;<@(,~"{~0 1+>./)"1)0:

Gera todas as partições da sub-lista criando as chaves para sublistas da partição de comprimento 1 e repetindo para o comprimento da lista de entrada. Cada sub-lista de partições é formada selecionando-se as teclas.

Por exemplo, aqui está o processo de criação das chaves para uma lista de tamanho 4.

Exemplo

Experimente online!

milhas
fonte
2

Braquilog , 2 bytes

~c

Experimente online!

Envio de função que produz saída via atuando como gerador. (O link TIO contém código extra para transformá-lo em um programa completo, para fins de teste.)

Aliás, embora não seja tecnicamente um builtin, isso é tão comumente usado no Brachylog que: a) provavelmente merece uma representação de byte eb; b) o cbuiltin pode usar um parâmetro para fazer afirmações sobre sua entrada (enquanto que na maioria dos builtins, um parâmetro fala sobre como produzir a saída ).

Explicação

~c
~     Find a value with the following properties:
 c      concatenating its elements produces {the input}

fonte
2

APL, 26 bytes

{⊂∘⍵¨1,¨↓⍉(X⍴2)⊤⍳2*X←⍴1↓⍵}

Teste:

      {⊂∘⍵¨1,¨↓⍉(X⍴2)⊤⍳2*X←⍴1↓⍵} 1 2 3 4
┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
│┌─────┬─┐│┌───┬───┐│┌───┬─┬─┐│┌─┬─────┐│┌─┬───┬─┐│┌─┬─┬───┐│┌─┬─┬─┬─┐│┌───────┐│
││1 2 3│4│││1 2│3 4│││1 2│3│4│││1│2 3 4│││1│2 3│4│││1│2│3 4│││1│2│3│4│││1 2 3 4││
│└─────┴─┘│└───┴───┘│└───┴─┴─┘│└─┴─────┘│└─┴───┴─┘│└─┴─┴───┘│└─┴─┴─┴─┘│└───────┘│
└─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘

Explicação:

  • X←⍴1↓⍵: Xé o comprimento de (a lista de entrada) com seu primeiro elemento descartado
  • ⍳2*X: os números [1..2 ^ X]
  • (X⍴2)⊤: representação de base 2 desses números, com Xposições (ou seja, Xela própria será enrolada em torno de 0).
  • ↓⍉: gire a matriz e divida-a ao longo das linhas ( fornece como resultado uma matriz com os números ao longo das colunas), fornecendo uma matriz de vetores de bits
  • 1,¨: acrescente 1 a cada vetor de bit.
  • ⊂∘⍵¨: para cada vetor de bit, divida a cada 1.
marinus
fonte
1

Python , 90 bytes

superado por ovs (fazendo algo que eu pensei que tinha tentado trabalhar: p)

def f(a):r=[[a]];i=len(a)-1;exec("for s in f(a[:i]):s+=[a[i:]];r+=[s]\ni-=1\n"*i);return r

Uma função recursiva que cria a lista de partições a partir de fatias da entrada com a cauda alcançada quando as fatias têm o comprimento 1.

Experimente online!

Ele execsalva 4 bytes em um whileou 3 em um forloop (abaixo), pois significa apenas dois \ns em vez de dois níveis de indentação, permitindo que toda a função esteja em uma linha (enquanto a ordem da fatia não importa).

def f(a):
 r=[[a]]
 for i in range(1,len(a)):
  for s in f(a[:i]):s+=[a[i:]];r+=[s]
 return r
Jonathan Allan
fonte
1

Python 3 , 67 bytes

f=lambda x,n=1:x[n:]and[y+[x[n:]]for y in f(x[:n])]+f(x,n+1)or[[x]]

Experimente online!

Dennis
fonte
1

Haskell, 59 bytes

x#[]=[[[x]]]
x#(a:b)=[(x:a):b,[x]:a:b]
foldr((=<<).(#))[[]]
alefalpha
fonte
1

Ruby , 62 57 bytes

->l{(0..2**l.size).map{|x|l.chunk{1&x/=2}.map &:last}|[]}

Experimente online!

Como funciona:

  • O número de partições é 2 ^ (n-1): eu itero números binários nesse intervalo, pego os grupos de zeros e uns e mapeio-os como subconjuntos da lista inicial.
  • Em vez de mexer com o intervalo, eu o dobro e descarto as duplicatas no final. Agora também posso descartar o primeiro dígito binário e diminuir a função do chunk.
GB
fonte
0

JavaScript (ES6), 87 bytes

([e,...a],b=[],c=[e],d=[...b,c])=>1/a[0]?[...f(a,b,[...c,a[0]]),...f(a,d,[a[0]])]:[d]

Explicação: bé a lista de sublistas anteriores, cé a sub-lista atual (que começa como o primeiro elemento da matriz, pois deve estar na primeira sub-lista), enquanto dé a lista de todas as sublistas. O restante dos elementos da matriz é processado recursivamente. Em cada caso, há duas opções: o próximo elemento é anexado à sub-lista atual ou a sub-lista atual é concluída e o próximo elemento inicia uma nova sub-lista. Os resultados recursivos são então concatenados juntos. Quando a matriz está esgotada, a lista da lista de todas as sublistas é o resultado.

Neil
fonte
0

APL (NARS) 38 caracteres, 76 bytes

{k←↑⍴⍵⋄x←11 1‼k k⋄y←⍵⋄∪{x[⍵;]⊂y}¨⍳↑⍴x}

isso usa a função Nars 11 1kk, mas é muito lenta, inutilizável para arg array de 9 elementos já ...

  P3←{k←↑⍴⍵⋄x←11 1‼k k⋄y←⍵⋄∪{x[⍵;]⊂y}¨⍳↑⍴x}

  ⍴∘P3¨{1..⍵}¨⍳8
1  2  4  8  16  32  64  128 
  P3 'abcd'
abcd    abc d    ab cd    a bcd    ab c d    a bc d    a b cd    a b c d

isto abaixo é a função que não usa o incorporado:

r←h w;k;i
   r←⊂,⊂w⋄k←↑⍴w⋄i←1⋄→B
A: r←r,(⊂⊂,i↑w),¨h i↓w⋄i+←1
B: →A×⍳i<k

  h 'abcd'
abcd    a bcd    a b cd    a b c d    a bc d    ab cd    ab c d    abc d
  ⍴∘h¨{1..⍵}¨⍳8
2  4  8  16  32  64  128 

nós vemos o tipo de cada resultado:

  o h ,1
┌──────┐
│┌1───┐│
││┌1─┐││
│││ 1│││
││└~─┘2│
│└∊───┘3
└∊─────┘
  o h 1 2
┌2───────────────────┐
│┌1─────┐ ┌2────────┐│
││┌2───┐│ │┌1─┐ ┌1─┐││
│││ 1 2││ ││ 1│ │ 2│││
││└~───┘2 │└~─┘ └~─┘2│
│└∊─────┘ └∊────────┘3
└∊───────────────────┘

Não sei como funciona, é apenas uma tentativa heurística ...

Possível cometer algum erro; ambas as funções constroem as partições da lista independentemente da entrada e não apenas 1 2 ... n.

RosLuP
fonte
0

Axioma, 251 bytes

C==>concat;A==>List Any;px(a:A):A==(k:=#a;r:=copy[a];k<=1=>r;i:=1;repeat(i>=k=>break;x:=a.(1..i);y:=a.((i+1)..k);z:=px(y);t:=[x,z.1];for j in 2..#z repeat(w:=(z.j)::A;m:=#w;v:=[x];for q in 1..m repeat v:=C(v,w.q);t:=C(t,[v]));r:=C(r,copy t);i:=i+1);r)

Se alguém encontrar algo melhor ... ungof e teste:

pp(a:List Any):List Any==
  k:=#a;r:=copy[a];k<=1=>r;i:=1
  repeat
    i>=k=>break
    x:=a.(1..i);y:=a.((i+1)..k);z:=pp(y);
    t:=[x,z.1]
    for j in 2..#z repeat
           w:=(z.j)::List Any
           m:=#w; v:=[x]
           for q in 1..m repeat 
                       v:=concat(v,w.q);
           t:=concat(t,[v])
    r:=concat(r,copy t);
    i:=i+1
  r

(7) -> px []
 (7)  [[]]
                                                           Type: List Any
(8) -> px [1]
 (8)  [[1]]
                                                           Type: List Any
(9) -> px [1,2]
 (9)  [[1,2],[[1],[2]]]
                                                           Type: List Any
(10) -> px [1,2,3]
 (10)  [[1,2,3],[[1],[2,3]],[[1],[2],[3]],[[1,2],[3]]]
                                                           Type: List Any
(11) -> px [1,2,3,4,5,6]
 (11)
[[1,2,3,4,5,6], [[1],[2,3,4,5,6]], [[1],[2],[3,4,5,6]],
 [[1],[2],[3],[4,5,6]], [[1],[2],[3],[4],[5,6]], [[1],[2],[3],[4],[5],[6]],
 [[1],[2],[3],[4,5],[6]], [[1],[2],[3,4],[5,6]], [[1],[2],[3,4],[5],[6]],
 [[1],[2],[3,4,5],[6]], [[1],[2,3],[4,5,6]], [[1],[2,3],[4],[5,6]],
 [[1],[2,3],[4],[5],[6]], [[1],[2,3],[4,5],[6]], [[1],[2,3,4],[5,6]],
 [[1],[2,3,4],[5],[6]], [[1],[2,3,4,5],[6]], [[1,2],[3,4,5,6]],
 [[1,2],[3],[4,5,6]], [[1,2],[3],[4],[5,6]], [[1,2],[3],[4],[5],[6]],
 [[1,2],[3],[4,5],[6]], [[1,2],[3,4],[5,6]], [[1,2],[3,4],[5],[6]],
 [[1,2],[3,4,5],[6]], [[1,2,3],[4,5,6]], [[1,2,3],[4],[5,6]],
 [[1,2,3],[4],[5],[6]], [[1,2,3],[4,5],[6]], [[1,2,3,4],[5,6]],
 [[1,2,3,4],[5],[6]], [[1,2,3,4,5],[6]]]
                                                           Type: List Any
(12) -> [[i,#px i] for i in [[],[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5,6]] ]
 (12)
[[[],1],[[1],1],[[1,2],2],[[1,2,3],4],[[1,2,3,4],8],[[1,2,3,4,5,6],32]]
                                                      Type: List List Any
(13) -> [#px(i) for i in [[],[1],[1,2],[1,2,3],[1,2,3,4],[1,2,3,4,5,6]] ]
 (13)  [1,1,2,4,8,32]
                                            Type: List NonNegativeInteger

Se houver muito espaço, diga isso e eu removo exemplos ...

RosLuP
fonte