Generar todas las particiones de sublista

11

Dada una lista de enteros no vacía, genera cada partición posible de la lista donde cada partición es una sublista no vacía.

Entonces, para la lista, [1, 2, 3, 4]el resultado es:

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

El orden de las listas en la salida no importa, por lo que [[1, 2, 3, 4]]podría ser primero, último o donde sea. El orden de los elementos debe ser preservado.

Este es el código de golf, por lo que gana la respuesta más corta.


Relacionado: Particionar una lista!

mbomb007
fuente
2
¿Podemos omitir el entorno [...]en el formato de salida? (Siempre y cuando las particiones estén claramente separadas, por ejemplo, por saltos de línea.)
Martin Ender
Los formatos de entrada y salida son flexibles, pero deberían ser similares. Entonces, si la lista de entrada tiene sus elementos en una línea, las listas de salida también deberían tenerla.
mbomb007
Eso no es lo que quiero decir. Echa un vistazo a la respuesta Bash. Se utiliza :como separador de lista, pero en la salida, las particiones en sí mismas no están envueltas en un par adicional de [...].
Martin Ender
O, preguntado de manera diferente: en su formato de ejemplo en el desafío, ¿puedo eliminar el primero [y el último ]de cada línea?
Martin Ender

Respuestas:

13

Retina , 27 19 bytes

El recuento de bytes asume la codificación ISO 8859-1.

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

Pruébalo en línea!

Explicación

Por supuesto, esto calcula todas las particiones usando el procesamiento de cadenas. La idea básica es que podemos generar todas las particiones al decidir ,individualmente si queremos o no dividir la lista allí. Este tipo de cosas se pueden hacer en Retina haciendo coincidir cada uno ,por turno y utilizando un reemplazo que ofrezca las dos salidas posibles.

La entrada actúa como el caso base: la partición donde todos los elementos todavía están en una sola lista.

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

Ahora repetidamente ( +) hacemos coincidir la primera ( 1) coma ( ,), en cada línea ( %) (tratando esa línea como una cadena separada, que es relevante para $'y `` $ 1 'en la sustitución).

Esa coma se reemplaza con:

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

Recuerde que todo lo que está delante del partido y después del partido permanece en la cadena de todos modos, por lo que el resultado completo es en realidad lo $`;$'¶$`];[$'que explica por qué insertamos el sufijo y el prefijo en ese orden.

Este bucle se detiene una vez que todas las comas desaparecen.

;
,

Finalmente, reemplace los puntos y comas con comas nuevamente para que coincida con el formato de entrada.

Martin Ender
fuente
10

Pure Bash, 28

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

Aquí, las listas están separadas por dos puntos y entre corchetes. Por ejemplo, en la pregunta, la lista de entrada sería 1:2:3:4y la salida es:

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

Pruébalo en línea .

  • ${1//:/REPLACEMENT}reemplaza los dos puntos $1con{:,]:[\}
  • Esto genera una expansión de llaves como [1{:,]:[}2{:,]:[}3{:,]:[}4]
  • La evaluación (y los \escapes cuidadosos ) hacen que la expansión de la llave ocurra en último lugar y den el resultado deseado.

Si es necesario que coincida exactamente con el [[ , , ...]]formato dado , podemos hacer esto en su lugar:

Pure Bash, 47

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

Pruébalo en línea .

Trauma digital
fuente
6

Pyth , 2 bytes

./

Con entrada [1, 2, 3, 4](por ejemplo).

Explicación : ./es el operador de partición. Devuelve todas las divisiones de la lista de entrada en sublistas disjuntas. La entrada se alimenta implícitamente al programa.

¡Pruébalo en línea!

Jim
fuente
6

05AB1E , 5 bytes

Œæʒ˜Q

Pruébalo en línea!

Œæʒ˜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
fuente
1
Wow, esta es una respuesta muy clara!
Adnan
1
@Adnan gracias, también estoy bastante contento con eso. Aunque es todo menos eficiente :)
kalsowerus
¡Buena respuesta cuando aún no había un incorporado, +1 de mi parte! Solo dejo esto para cualquier otra persona que venga aquí en el futuro, pero 05AB1E ahora tiene una función integrada de 2 bytes para obtener todas las particiones :: Pruébelo en línea.
Kevin Cruijssen
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]

Pruébalo en línea!

-5 bytes gracias a @JonathanAllan

ovs
fuente
Oh, no puedo ^ v otra vez :( Intenté algo como esto y no funcionó, debí haber salido mal en alguna parte.
Jonathan Allan
1
... en cuyo caso cortar 5 más
Jonathan Allan
1
@JonathanAllan muchas gracias! Podría salvar a otro byte mediante la reutilización de la lque al final
ovs
Esta solución ya existe aquí . Le envié un mensaje a @feersum en TNB después de publicar la pregunta, para que tuviera la oportunidad de publicarla.
mbomb007
No quise decir que debías deshacerlo, solo quise decir que lo golpeaste. Es tu elección, por supuesto.
mbomb007
4

Haskell , 59 55 49 bytes

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

Pruébalo en línea!

Solución recursiva. Ejemplo de uso: p [1,2,3]devoluciones [[[1,2,3]],[[1,2],[3]],[[1],[2,3]],[[1],[2],[3]]].

-6 bytes gracias a xnor !

Laikoni
fuente
1
Puede escribir la segunda línea más corta con notación do: do a:b<-p r;[(x:a):b,[x]:a:b](esto cambia el orden de las listas).
xnor
1
Además, <*>hace exactamente lo que quieres [\(a:b)->(x:a):b,([x]:)]<*>p r, aunque es más largo que doporque la primera lambda parece necesitar una coincidencia de patrones.
xnor
3

J , 42 bytes

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

Genera todas las particiones de sublistas creando las claves para las sublistas de particiones de longitud 1 e iterando a la longitud de la lista de entrada. Cada sublista de partición se forma seleccionando de las teclas.

Por ejemplo, aquí está el proceso de crear las claves para una lista de longitud 4.

Ejemplo

Pruébalo en línea!

millas
fuente
2

Brachylog , 2 bytes

~c

Pruébalo en línea!

Envío de funciones que produce resultados al actuar como generador. (El enlace TIO contiene código adicional para convertirlo en un programa completo, con fines de prueba).

Por cierto, aunque técnicamente no es un componente integrado, esto se usa con tanta frecuencia en Brachylog que a) probablemente merece una representación de un solo byte, yb) el ccomponente integrado puede tomar un parámetro para hacer afirmaciones sobre su entrada (mientras que con la mayoría de los componentes integrados, un parámetro habla sobre cómo producir la salida ).

Explicación

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

fuente
2

APL, 26 bytes

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

Prueba:

      {⊂∘⍵¨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││
│└─────┴─┘│└───┴───┘│└───┴─┴─┘│└─┴─────┘│└─┴───┴─┘│└─┴─┴───┘│└─┴─┴─┴─┘│└───────┘│
└─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘

Explicación:

  • X←⍴1↓⍵: Xes la longitud de (la lista de entrada) con su primer elemento descartado
  • ⍳2*X: los números [1..2 ^ X]
  • (X⍴2)⊤: representación de base 2 de esos números, con Xposiciones (es decir, Xse ajustará a 0).
  • ↓⍉: gira la matriz y la divide a lo largo de las líneas ( da como resultado una matriz con los números a lo largo de las columnas), dando una matriz de vectores de bits
  • 1,¨: anteponer un 1 a cada vector de bits.
  • ⊂∘⍵¨: para cada vector de bits, dividir en cada 1.
marinus
fuente
1

Python , 90 bytes

superado por los ovs (haciendo algo que pensé que había intentado trabajar: 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

Una función recursiva que construye la lista de particiones a partir de sectores de la entrada con la cola alcanzada cuando los sectores son de longitud 1.

Pruébalo en línea!

Esto execahorra 4 bytes sobre ao while3 sobre un forbucle (abajo) ya que significa solo dos \nsegundos en lugar de dos niveles de sangría, lo que permite que toda la función esté en una línea (mientras que el orden de corte no 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
fuente
1

Haskell, 59 bytes

x#[]=[[[x]]]
x#(a:b)=[(x:a):b,[x]:a:b]
foldr((=<<).(#))[[]]
alephalpha
fuente
1

Ruby , 62 57 bytes

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

Pruébalo en línea!

Cómo funciona:

  • El número de particiones es 2 ^ (n-1): itero en números binarios en ese rango, tomo los grupos de ceros y unos y los mapeo como subconjuntos de la lista inicial.
  • En lugar de jugar con el rango, lo doblo y descarto los duplicados al final. Ahora también puedo descartar el primer dígito binario y acortar la función del fragmento.
GB
fuente
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]

Explicación: bes la lista de sublistas anteriores, ces la sublista actual, (que comienza como el primer elemento de la matriz, ya que debe estar en la primera sublista) mientras que des la lista de todas las sublistas. El resto de los elementos de la matriz se procesan recursivamente. En cada caso, hay dos opciones: el siguiente elemento se agrega a la sublista actual o la sublista actual se completa y el siguiente elemento inicia una nueva sublista. Los resultados recursivos se concatenan juntos. Cuando la matriz se agota, el resultado es la lista de todas las sublistas.

Neil
fuente
0

APL (NARS) 38 caracteres, 76 bytes

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

esto usa la función Nars 11 1‼ kk pero es muy lenta, inutilizable para una matriz arg de 9 elementos ya ...

  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

esto a continuación es la función que no utiliza el 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 

Vemos el 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
└∊───────────────────┘

No sé cómo funciona, es solo un intento heurístico ...

Posible cometo un error; ambas funciones construyen las particiones de la lista, independientemente de la entrada, y no solo 1 2 ... n.

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

Si alguien encuentra algo mejor ... ungof y prueba:

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

Si esto es demasiado espacio, dilo y elimino ejemplos ...

RosLuP
fuente