J'ai trouvé utile de définir une fonction auxiliaire, partitionsCap
, qui ne laisse aucun des éléments dépasser une valeur donnée. Utilisé récursive, il peut être utilisé pour produire uniquement les monotonically résultats décroissants que vous voulez (pas de [1,3,1]
lorsque vous avez déjà [1,1,3]
):
partitions :: Int -> [[Int]]
partitions n = partitionsCap n n
partitionsCap :: Int -> Int -> [[Int]]
partitionsCap cap n
| n < 0 = error "partitions: negative number"
| n == 0 = [[]]
| n > 0 = [i : p | i <- [hi,hi-1..1], p <- partitionsCap i (n-i)]
where hi = min cap n
Au cœur de l'algorithme est l'idée que, lors du partitionnement N, vous prenez i
de n
jusqu'à 1, et préfixez i
aux partitions de n-i
. Simplifié:
concat [map (i:) $ partitions (n-i) | i <- [n,n-1..1]]
mais mal:
> partitions 3
[[3],[2,1],[1,2],[1,1,1]]
Nous voulons que [1,2]
aller loin.Par conséquent, nous avons besoin de plafonner les partitions que nous sommes à préfixer donc ils ne vont pas au-dessus i
:
concat [map (i:) $ partitionsCap i (n-i) | i <- [hi,hi-1..1]]
where hi = min cap n
Maintenant, pour le nettoyer: que concat et carte si proches attiré mon attention . Un peu d'arrière-plan: les listes de compréhension et la liste monad sont very closely related, et concatMap est le même que >>=
avec ses arguments retournés, dans la liste monad. Donc, je me demandais: est-ce que ces concat et carte se transforment en quelque sorte en >>=
, et peut-il que >>=
en quelque sorte douce-parler son chemin dans la compréhension de la liste?
Dans ce cas, la réponse est oui :-)
[i : p | i <- [hi,hi-1..1], p <- partitionsCap i (n-i)]
where hi = min cap n
révulsés l'édition qui a tué le poste –
Et encore. @dave, pourquoi essayez-vous de supprimer vos deux questions? :/ –