2012-11-18 2 views
3

목록의 가능한 모든 하위 목록의 목록을 포함하는 목록을 생성하는 함수를 작성해야합니다.목록의 가능한 모든 하위 목록

partitions :: [a] -> [[[a]]] 

그것을 제공한다 : 따라서 유형이어야

파티션 [1..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 (x:xs) = foldr insert [[]] (x:xs) 
    where insert ys zs = ys:x:zs 

예상대로 유형 오류가 발생하지만이를 수정하는 방법을 모르겠습니다. 나는 명백한 것을 놓치고 있다고 느낀다. 어떤 도움이라도 인정 될 것이다.

+0

필자는 powerset ('filterM (const [True, False])')를 원했을 것이라고 생각했지만 정의가 약간 다릅니다. 목록의 모든 가능한 분할을 원하십니까? – singpolyma

+2

'insert '의 타입은 무엇이라고 생각하십니까? 나는'insert :: a -> [[[a]]] -> [[[a]]]'라고 생각한다. 'insert'가 언제 사용되는 것으로 생각합니까? 사실,리스트를 통한'foldr' 재귀의 * 각 단계 *에서 사용되기 때문에, 여러분의 코드는'x'의 복사본을 많이 만드는 답을 제공하려고 시도하는 것 같습니다.'foldr'을 사용하는 것은 좋은 생각입니다 : 파티션이 무엇인지에 대해서 생각해보십시오 ('[] '). 파티션이 주어 졌을 때 비어 있지 않은리스트의 파티션을 계산하는 방법 ('[1,2,3,4]') ('[2,3,4]'). 후자의 경우, 각 꼬리 분할에 head 요소 (여기서는'1')를 추가하는 방법을 고려하십시오. 목록 작성자가 실제로 도움이 될 수 있습니다. – pigworker

+1

리스트의 각 복사본의 분할은'[1..n-1]'(리스트의 길이가 n 인 경우)의 모든 특성 함수와 일치합니다. 'replicateM (predn) [True, False]'(왜?)를 통해 이들을 생성 할 수 있으며, 적절한 결합 함수와'2^(n-1)'원본 복사본을'zipWith'합니다. (특성 함수의 명시적인 생성을 우회하는 솔루션을위한 추가 점) – Fixnum

답변

8

직접 재귀로 시작할 것입니다. 그것을 분해하십시오. 긴 목록의 첫 번째 요소에는 어떤 가능성이 있습니까?

  1. 파티션 목록 중 하나의 요소 일 수 있습니다.
  2. 둘 이상의 요소가있는 파티션 목록의 일부일 수 있습니다. 귀하의 예제에서

, 당신이 순서대로 원래의 요소를 유지하려는 것 같다, 그래서 각 파티션의 회원 만 다소 쉽게 연속 하위 목록이 될 수 있습니다.

그래서 우리는

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

를 산출한다.

+0

주문은 여기에 관계가 없습니다. 도움을 주셔서 감사합니다, 나는 당신이 나에게 준 것과 foldr 형태로 다시 작성할 수 있어야합니다. – Joe

관련 문제