2014-11-27 2 views
2

이 질문에서 V 값과 고유 한 정수 목록이 제공됩니다. 당신의 임무는 V까지 합계하는 크기가 4 인 하위 집합의 수를 찾는 것입니다. 목록의 각 요소는 한 번만 사용할 수 있습니다. 이러한 부분 집합을 찾을 수 없으면 대신 0을 출력하십시오. 예를 들어 for 루프를 구현하는 Clojure 방법은 무엇입니까?

의 정수 [3, 4, 5, 6, 7, 8, 9, 10]하고 값 30 경우, 출력되어야 5 서브셋은 :

이이 문제를 해결하기 어렵지 않다
[3, 8, 9, 10] 
[4, 7, 9, 10] 
[5, 6, 9, 10] 
[5, 7, 8, 10] 
[6, 7, 8, 9]. 

, 가장 직접적인 방법이다 for-loop 네 번 둥지. Clojure 방법은 무엇입니까?

답변

4

을 요약하지 않는 것은 내가 했 방법 :

(ns example.solve 
    (:require [clojure.math.combinatorics :as combo])) 

(defn solve 
    [s n v] 
    (filter (comp (partial = v) 
       (partial reduce +)) 
      (combo/combinations s n))) 

I을 내 예제에서는 math.combinatorics을 사용하고 있습니다. 이는 목록에서 4 개 요소의 모든 조합을 가져 오는 가장 간단한 방법이기 때문입니다. 여기

solve을 사용한 예이다. (실제 서브 세트를 생성하지 않고) 흥미롭게

=> (solve [3 4 5 6 7 8 9 10] 4 30) 
((3 8 9 10) (4 7 9 10) (5 6 9 10) (5 7 8 10) (6 7 8 9)) 
+2

답변을 설명하기 위해 매우 유용합니다. '(해결 [3, 4, 5, 6, 7, 8, 9, 10] 4 30) (3 8 9 10) (4 7 9 10) 5 6 9 10) (5 7 8 10) (6 7 8 9))' –

+0

@JamesSharp 고맙습니다! 내 대답에 당신의 모범을 추가했습니다. –

+1

comp 함수는 훌륭합니다! 고맙습니다. – Nick

3

내가 4 요소의 하위 집합을 얻을 수 clojure.map.combinatorics/combinations을 사용하고 그 밖에 다음 filter V.

다음
3

이 문제 만 합산 계산 관련된 (? 이중) 재귀 용액 인정

경우 당신은 초기 요소 3을 봅니다. 그런 다음 솔루션의 일부는 합계가 27 인 나머지 시퀀스에서 3 개 요소에서 취한 합계의 수입니다. 이는 동일한 문제의 더 작은 형태이므로 재귀 적으로 해결할 수 있습니다. 재귀의 맨 아래 부분은 원하는 요소가 목록에 있는지 간단한 검사로 귀결되는 1 요소에서 생성 된 합계를 찾을 때입니다.

솔루션의 다른 부분은 다음 요소 4를보고 목록의 나머지 부분에서 4를 26 이상으로 합계를 찾는 등의 작업이 포함됩니다.이 부분도 재귀 적으로 처리 할 수 ​​있습니다.

이 함수를 재귀 함수로 두는 것은 예제 시퀀스에 대해 원하는 답을 생성하는 다음과 같습니다.

직접 질문에 대답 측면에서
(defn solve [xs n len] 
    (if (seq xs) 
    (if (= len 1) 
     (if (some #{n} xs) 1 0) 
     (+ (solve (rest xs) 
       (- n (first xs)) 
       (dec len)) 
      (solve (rest xs) 
       n 
       len))) 
    0)) 

(solve [3 4 5 6 7 8 9 10] 30 4)    
;=> 5 
+0

실제 솔루션을 반환하기 위해 함수를 리팩토링했습니다. https://gist.github.com/lbeschastny/e1f16b4f888bbb532526 –

+0

Nice! 나는 당신의 리펙토링이 같은 모양을 가지고 있지만 concat을 +로 대체하고 필요한 곳에리스트를 만드는 것을 좋아한다. 감사합니다! –

+0

이렇게하면 숫자가 모두 양수임을 알면 일부 단락이 허용됩니다. – Thumbnail

1

, 여기 당신이 인덱스를 사용하여 할 수있는 방법이며, for 루프 :

(defn solve-for [xs v] 
    (for [ndx0 (range 0   (- (count xs) 3)) 
     ndx1 (range (inc ndx0) (- (count xs) 2)) 
     ndx2 (range (inc ndx1) (- (count xs) 1)) 
     ndx3 (range (inc ndx2) (count xs)) 
     :when (= v (+ (xs ndx0) (xs ndx1) (xs ndx2) (xs ndx3)))] 
    (list (xs ndx0) (xs ndx1) (xs ndx2) (xs ndx3)))) 

FWIW,이 접근 방식보다 약 70 % 더 빠른 것으로 판명 clojure.math.combinatorics을 사용하지만 이중 회귀 해법보다 두 배 느립니다.

관련 문제