Zulip Chat Archive
Stream: Is there code for X?
Topic: all partitions of a list
Paige Thomas (Aug 02 2024 at 17:21):
I was wondering if someone might know of a more elegant algorithm than this, that is simpler to prove results about.
def List.partitions
{α : Type} :
List α → List (List (List α))
| [] => [[]]
| [x] => [[[x]]]
| (x :: xs) =>
let partitions := List.partitions xs
let l := partitions.map
(fun (part : List (List α)) => ((x :: part.headI) :: part.tail))
let r := partitions.map
(fun (part : List (List α)) => [x] :: part)
l ++ r
#eval List.partitions ['a', 'b', 'c', 'd', 'e']
/-
[[['a', 'b', 'c', 'd', 'e']],
[['a', 'b', 'c', 'd'], ['e']],
[['a', 'b', 'c'], ['d', 'e']],
[['a', 'b', 'c'], ['d'], ['e']],
[['a', 'b'], ['c', 'd', 'e']],
[['a', 'b'], ['c', 'd'], ['e']],
[['a', 'b'], ['c'], ['d', 'e']],
[['a', 'b'], ['c'], ['d'], ['e']],
[['a'], ['b', 'c', 'd', 'e']],
[['a'], ['b', 'c', 'd'], ['e']],
[['a'], ['b', 'c'], ['d', 'e']],
[['a'], ['b', 'c'], ['d'], ['e']],
[['a'], ['b'], ['c', 'd', 'e']],
[['a'], ['b'], ['c', 'd'], ['e']],
[['a'], ['b'], ['c'], ['d', 'e']],
[['a'], ['b'], ['c'], ['d'], ['e']]]
-/
Daniel Weber (Aug 03 2024 at 19:35):
There is an equivalence to docs#List.sublists, perhaps you can take inspiration from how it's implemented?
Daniel Weber (Aug 03 2024 at 19:42):
def List.partitions
{α : Type} (l : List α) : List (List (List α)) :=
l.foldr (fun a acc ↦ acc.bind fun x ↦ [(a :: x.headI) :: x.tail, [a] :: x]) [[]]
Paige Thomas (Aug 04 2024 at 03:03):
Thank you. Is it possible to somehow incorporate a proof that the partition list is not empty to avoid the need for List.headI
, either in mine or yours?
Paige Thomas (Aug 04 2024 at 03:07):
Or, better yet, a way to construct the definition such that it is not needed.
Daniel Weber (Aug 04 2024 at 03:21):
The headI
there is actually used for the first step. I'm not sure how the definition could be stated without it, I'll think about it
Last updated: May 02 2025 at 03:31 UTC