Genera tutte le partizioni subliste


11

Dato un elenco di numeri interi non vuoto, genera ogni possibile partizionamento dell'elenco in cui ogni partizione è un elenco secondario non vuoto.

Quindi per l'elenco [1, 2, 3, 4]il risultato è:

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

L'ordine delle liste nell'output non ha importanza, quindi [[1, 2, 3, 4]]potrebbe essere il primo, l'ultimo o ovunque. L'ordine degli elementi deve essere preservato.

Questo è code-golf, quindi vince la risposta più breve.


Correlati: partizionare un elenco!


2
Possiamo omettere l'ambiente circostante [...]nel formato di output? (Finché le partizioni sono chiaramente separate, ad es. Da avanzamenti di riga.)
Martin Ender,

I formati di input e output sono flessibili, ma dovrebbero essere simili. Quindi, se l'elenco di input ha i suoi elementi su una riga, anche gli elenchi di output dovrebbero.
mbomb007,

Non è quello che intendo. Dai un'occhiata alla risposta di Bash. Utilizza :come separatore di elenco ma nell'output le partizioni stesse non sono racchiuse in una coppia aggiuntiva di [...].
Martin Ender,

Oppure, chiesto diversamente: nel tuo formato di esempio nella sfida, posso eliminare la prima [e l'ultima ]da ciascuna riga?
Martin Ender,

Risposte:



13

Retina , 27 19 byte

Il conteggio dei byte presuppone la codifica ISO 8859-1.

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

Provalo online!

Spiegazione

Naturalmente questo calcola tutte le partizioni usando l'elaborazione delle stringhe. L'idea di base è che possiamo generare tutte le partizioni decidendo per ciascuna ,individualmente se vogliamo o meno dividere la lista lì. Questo tipo di cose può essere fatto in Retina abbinandole ,a turno e usando una sostituzione che dia entrambe le possibili uscite.

L'input funge da caso base: la partizione in cui tutti gli elementi sono ancora in un unico elenco.

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

Ora ripetutamente ( +) abbiniamo la prima ( 1) virgola ( ,), su ogni riga ( %) (trattando quella riga come una stringa separata, che è rilevante per $'e `` $ 1 `nella sostituzione).

Quella virgola viene sostituita 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.

Ricorda che tutto ciò che precede l'incontro e dopo l'incontro rimane comunque nella stringa, quindi il risultato completo è in realtà il $`;$'¶$`];[$'motivo per cui inseriamo il suffisso e il prefisso in quell'ordine.

Questo ciclo si interrompe quando tutte le virgole sono sparite.

;
,

Infine, sostituisci di nuovo i punti e virgola con virgole per abbinare il formato di input.


10

Pure Bash, 28

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

Qui, gli elenchi sono separati da due punti e racchiusi tra parentesi quadre. Ad esempio nella domanda, l'elenco di input sarebbe 1:2:3:4e l'output è:

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

Provalo online .

  • ${1//:/REPLACEMENT}sostituisce i due punti in $1con{:,]:[\}
  • Questo genera un'espansione del tipo di parentesi graffa [1{:,]:[}2{:,]:[}3{:,]:[}4]
  • La valutazione (e le \fughe accurate ) fanno sì che l'espansione del controvento avvenga per ultima e dia il risultato desiderato.

Se è necessario abbinare esattamente il [[ , , ...]]formato specificato, possiamo invece farlo:

Pure Bash, 47

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

Provalo online .


6

Pyth , 2 byte

./

Con input [1, 2, 3, 4](ad esempio).

Spiegazione : ./è l'operatore della partizione. Restituisce tutte le divisioni della lista di input in sotto-liste disgiunte. L'input viene implicitamente inserito nel programma.

Provalo online!


6

05AB1E , 5 byte

Œæʒ˜Q

Provalo 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

1
Caspita, questa è una risposta molto chiara!
Adnan,

1
@Adnan grazie, ne sono anche abbastanza contento. Anche se è tutto fuorché efficiente :)
kalsowerus,

Bella risposta quando non c'era ancora un builtin, +1 da me! Lasciandolo per chiunque venga qui in futuro, ma 05AB1E ora ha un byte di 2 byte incorporato per ottenere tutte le partizioni : Provalo online.
Kevin Cruijssen,

4

Python 3 , 82 72 66 byte

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

Provalo online!

-5 byte grazie a @JonathanAllan


Oh mio Dio, non posso ^ v di nuovo :( In realtà ho provato qualcosa del genere e non ha funzionato, devo essermi sbagliato da qualche parte.
Jonathan Allan,

1
... nel qual caso eliminane altri 5
Jonathan Allan,

1
@JonathanAllan grazie mille! Potrei salvare un altro byte riutilizzando lalla fine
ovs

Questa soluzione esiste già qui . Ho inviato un messaggio a @feersum in TNB dopo aver pubblicato la domanda, in modo che potesse avere la possibilità di pubblicarlo.
mbomb007,

Non intendevo che dovessi annullarlo, intendevo solo che lo hai battuto. È una tua scelta, ovviamente.
mbomb007,

4

Haskell , 59 55 49 byte

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

Provalo online!

Soluzione ricorsiva. Esempio di utilizzo: p [1,2,3]ritorni [[[1,2,3]],[[1,2],[3]],[[1],[2,3]],[[1],[2],[3]]].

-6 byte grazie a xnor !


1
Puoi scrivere la seconda riga più breve con notazione: do a:b<-p r;[(x:a):b,[x]:a:b](questo cambia l'ordine delle liste).
xnor

1
Inoltre, <*>fa esattamente quello che vuoi [\(a:b)->(x:a):b,([x]:)]<*>p r, anche se è più lungo che doperché la prima lambda sembra aver bisogno di una corrispondenza del modello.
xnor

3

J , 42 byte

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

Genera tutte le partizioni dell'elenco secondario creando le chiavi per gli elenchi di partizioni di lunghezza 1 e ripetendo la lunghezza dell'elenco di input. Ciascun elenco secondario delle partizioni viene quindi formato selezionando dai tasti.

Ad esempio, ecco il processo di creazione delle chiavi per un elenco di lunghezza 4.

Esempio

Provalo online!



2

Brachylog , 2 byte

~c

Provalo online!

Invio di funzioni che producono output agendo come un generatore. (Il collegamento TIO contiene un codice aggiuntivo per trasformarlo in un programma completo, a scopo di test.)

Per inciso, sebbene non sia tecnicamente un builtin, questo è così comunemente usato in Brachylog che a) probabilmente merita una rappresentazione a byte singolo e b) il cbuiltin può prendere un parametro per fare affermazioni sul suo input (mentre con la maggior parte dei builtin, un parametro parla di come produrre l' output ).

Spiegazione

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

2

APL, 26 byte

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

Test:

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

Spiegazione:

  • X←⍴1↓⍵: Xè la lunghezza di (l'elenco di input) con il primo elemento eliminato
  • ⍳2*X: i numeri [1..2 ^ X]
  • (X⍴2)⊤: rappresentazione base-2 di quei numeri, con Xposizioni (ovvero Xsi avvolgerà a 0).
  • ↓⍉: ruota la matrice e dividila lungo le linee ( dà come risultato una matrice con i numeri lungo le colonne), dando una matrice di bit bit
  • 1,¨: antepone un 1 a ciascun vettore di bit.
  • ⊂∘⍵¨: per ogni vettore di bit, diviso per ogni 1.


1

Python , 90 byte

superato da ovs (facendo qualcosa che pensavo di aver provato a lavorare: 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 funzione ricorsiva che costruisce l'elenco delle partizioni dalle sezioni dell'input con la coda raggiunta quando le sezioni sono di lunghezza 1.

Provalo online!

Il execsalva 4 byte su uno whileo 3 su un forloop (sotto) poiché significa solo due \ns anziché due livelli di indentazione, permettendo l'intera funzione sia su una linea (mentre l'ordine di affettamento non 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


1

Haskell, 59 byte

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

1

Rubino , 62 57 byte

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

Provalo online!

Come funziona:

  • Il numero di partizioni è 2 ^ (n-1): eseguo l'iterazione su numeri binari in quell'intervallo, prendo i gruppi di zero e uno e li mappa come sottoinsiemi dell'elenco iniziale.
  • Invece di armeggiare con l'intervallo, lo faccio doppio e scarto i duplicati alla fine. Ora posso anche scartare la prima cifra binaria e accorciare la funzione di blocco.

0

JavaScript (ES6), 87 byte

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

Spiegazione: bè l'elenco di elenchi precedenti precedenti, cè l'elenco secondario corrente (che inizia come primo elemento dell'array, poiché deve essere presente nel primo elenco secondario) mentre dè l'elenco di tutti gli elenchi secondari. Il resto degli elementi dell'array viene quindi elaborato in modo ricorsivo. In ciascun caso sono disponibili due opzioni: l'elemento successivo viene aggiunto all'elenco secondario corrente oppure l'elenco secondario corrente viene completato e l'elemento successivo avvia un nuovo elenco secondario. I risultati ricorsivi vengono quindi concatenati insieme. Quando l'array è esaurito, viene visualizzato l'elenco di tutti gli elenchi secondari.


0

APL (NARS) 38 caratteri, 76 byte

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

questo usa la funzione Nars 11 1‼ kk ma è molto lento, inutilizzabile per arg array di 9 elementi già ...

  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

questa sotto è la funzione che non usa il built-in:

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 

vediamo il tipo ogni risultato:

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

Non so come funzioni, è solo un tentativo euristico ...

Possibile che commetta qualche errore; entrambe le funzioni costruiscono le partizioni dell'elenco qualunque sia l'input e non solo 1 2 ... n.


0

Assioma, 251 byte

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 qualcuno trova qualcosa di meglio ... ungof e prova:

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 questo è troppo spazio, dillo e rimuovo degli esempi ...

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.