직접 재귀로 시작할 것입니다. 그것을 분해하십시오. 긴 목록의 첫 번째 요소에는 어떤 가능성이 있습니까?
- 파티션 목록 중 하나의 요소 일 수 있습니다.
- 둘 이상의 요소가있는 파티션 목록의 일부일 수 있습니다. 귀하의 예제에서
, 당신이 순서대로 원래의 요소를 유지하려는 것 같다, 그래서 각 파티션의 회원 만 다소 쉽게 연속 하위 목록이 될 수 있습니다.
그래서 우리는
*Partitions> partitions [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]]]
하지 원하는 순서를 산출
partitions :: [a] -> [[[a]]]
partitions [] = [[]] -- only one partition of an empty list, an empty partition
partitions (x:xs) = [[x]:part | part <- partitions xs] ++ [(x:ys):yss | (ys:yss) <- partitions xs]
를 시작할 수 있습니다. 그게 중요하다면 우리는 다시 써야합니다. 원하는 순서는 직접 계승의 첫 번째 요소 모두 선택을 나열, 그래서 우리는 쓸 수 그것은 우리가 명시 적으로 비어 있지 않은 파티션합니다 (재귀의 끝에서) 빈 파티션의 경우를 구별 할 필요가
partitions (x:xs) = partitions xs >>= \zs -> case zs of
[] -> [[[x]]]
(ys:yss) -> [[x]:ys:yss, (x:ys):yss]
, 위의 패턴은 암시 적으로 패턴 (ys:yss)
에 바인딩하여 수행되었습니다. 즉,리스트의 바인드 모나드 (>>=)
flip concatMap
는,
partitions (x:xs) = concatMap insert (partitions xs)
where
insert [] = [[[x]]]
insert (ys:yss) = [[x]:ys:yss, (x:ys):yss]
더 읽을 수있는 버전이다는 사실을 이용하여 원하는 순서
*Partitions> partitions [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]]]
를 산출한다.
필자는 powerset ('filterM (const [True, False])')를 원했을 것이라고 생각했지만 정의가 약간 다릅니다. 목록의 모든 가능한 분할을 원하십니까? – singpolyma
'insert '의 타입은 무엇이라고 생각하십니까? 나는'insert :: a -> [[[a]]] -> [[[a]]]'라고 생각한다. 'insert'가 언제 사용되는 것으로 생각합니까? 사실,리스트를 통한'foldr' 재귀의 * 각 단계 *에서 사용되기 때문에, 여러분의 코드는'x'의 복사본을 많이 만드는 답을 제공하려고 시도하는 것 같습니다.'foldr'을 사용하는 것은 좋은 생각입니다 : 파티션이 무엇인지에 대해서 생각해보십시오 ('[] '). 파티션이 주어 졌을 때 비어 있지 않은리스트의 파티션을 계산하는 방법 ('[1,2,3,4]') ('[2,3,4]'). 후자의 경우, 각 꼬리 분할에 head 요소 (여기서는'1')를 추가하는 방법을 고려하십시오. 목록 작성자가 실제로 도움이 될 수 있습니다. – pigworker
리스트의 각 복사본의 분할은'[1..n-1]'(리스트의 길이가 n 인 경우)의 모든 특성 함수와 일치합니다. 'replicateM (predn) [True, False]'(왜?)를 통해 이들을 생성 할 수 있으며, 적절한 결합 함수와'2^(n-1)'원본 복사본을'zipWith'합니다. (특성 함수의 명시적인 생성을 우회하는 솔루션을위한 추가 점) – Fixnum