Re: recursion question

2012-08-15 Thread nicolas.o...@gmail.com
First solution:

(defn groupSum [l x]
(or (zero? x) ; we have won!
(and (not ( x 0)) ; we can't win
   (not (empty? l)) ; lost!
   (or (groupSum (rest l) (- x (first l)))
(recur (rest l) x)

The we can't win line assume that all numbers are positive. We use
tail recursion in the only place we can use it.

If all numbers are positive, a more elaborate version would use this fact:
If all numbers are positive, and the sum of a suffix can't reach a
target, you should not try without the first element.
So the function will return :
 - either 0 if we reach the goal
 - a negative number if we went over the goal
 - a positive number if we went under the goal.

If we went under the goal, we don't need to try without the first element.

(defn groupSum0 [l n]
(if (or (empty? l) ( n 0))
n
(let [res (groupSum0 (rest l) (- n (first l)))]
 (if (= res 0) res ;; we are either winning or can't reach 
the goal
(if (zero? (groupSum0 (rest l) n))
  0  ;; we have won
   res)  ;; we repeat we can
reach the goal from here

(defn groupSum [l n] (zero? (groupSum0 l n)))

Next step would be to make groupSum0 not stack overflow on big inputs
and to add memoization to it.

Best regards,

Nicolas.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: recursion question

2012-08-15 Thread Balint Erdi
This is the classic Subset sum problem 
(http://en.wikipedia.org/wiki/Subset_sum_problem) and is an NP one.

I've implemented the pseudo-polynomial dynamic programming solution found 
on the above Wikipedia page:
https://gist.github.com/3359504

It returns the indexes of the elements that give the desired sum but it can 
trivially be transformed to whether there is a solution or not.

Balint

On Wednesday, August 15, 2012 1:13:32 AM UTC+2, John Holland wrote:

 I've been doing some programming exercises in Clojure, I've run into one I 
 don't know how to approach. If anyone can just give me the strategy to use 
 on this that'd be great. Here is the problem statement:

 Given an array of ints, is it possible to choose a group of some of the 
 ints, such that the group sums to the given target? 


 sample calls would be like:

 (groupSum [2, 4, 8] 10) → true
 (groupSum [2, 4, 8] 14) → true
 (groupSum [2, 4, 8]  9) → false


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: recursion question

2012-08-14 Thread Raoul Duke
¿
take the first #.
subtract that from the goal.
now ask if the remaining #s can sum to the now-lesser goal.
lather rinse repeat.
don't forget a base case.
watch your cpu heat very quickly up on even slightly longer lists.
?

On Tue, Aug 14, 2012 at 4:13 PM, John Holland jbholl...@gmail.com wrote:
 I've been doing some programming exercises in Clojure, I've run into one I
 don't know how to approach. If anyone can just give me the strategy to use
 on this that'd be great. Here is the problem statement:

 Given an array of ints, is it possible to choose a group of some of the
 ints, such that the group sums to the given target?


 sample calls would be like:

 (groupSum [2, 4, 8] 10) → true
 (groupSum [2, 4, 8] 14) → true
 (groupSum [2, 4, 8]  9) → false

 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: recursion question

2012-08-14 Thread Raoul Duke
sorry take the first# actually is meant to be worded as, in turn,
take out 1 of each of the #s, and recurse on what remains so that you
are doing the permutations at each level of the recursion/tree.

On Tue, Aug 14, 2012 at 4:15 PM, Raoul Duke rao...@gmail.com wrote:
 ¿
 take the first #.
 subtract that from the goal.
 now ask if the remaining #s can sum to the now-lesser goal.
 lather rinse repeat.
 don't forget a base case.
 watch your cpu heat very quickly up on even slightly longer lists.
 ?

 On Tue, Aug 14, 2012 at 4:13 PM, John Holland jbholl...@gmail.com wrote:
 I've been doing some programming exercises in Clojure, I've run into one I
 don't know how to approach. If anyone can just give me the strategy to use
 on this that'd be great. Here is the problem statement:

 Given an array of ints, is it possible to choose a group of some of the
 ints, such that the group sums to the given target?


 sample calls would be like:

 (groupSum [2, 4, 8] 10) → true
 (groupSum [2, 4, 8] 14) → true
 (groupSum [2, 4, 8]  9) → false

 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: recursion question

2012-08-14 Thread John Holland
I thought of doing something like that, but part of the requirements is 
that the sum could be achieved with *some of the numbers in the vector.

On Tuesday, August 14, 2012 7:15:27 PM UTC-4, raould wrote:

 ¿ 
 take the first #. 
 subtract that from the goal. 
 now ask if the remaining #s can sum to the now-lesser goal. 
 lather rinse repeat. 
 don't forget a base case. 
 watch your cpu heat very quickly up on even slightly longer lists. 
 ? 

 On Tue, Aug 14, 2012 at 4:13 PM, John Holland 
 jbho...@gmail.comjavascript: 
 wrote: 
  I've been doing some programming exercises in Clojure, I've run into one 
 I 
  don't know how to approach. If anyone can just give me the strategy to 
 use 
  on this that'd be great. Here is the problem statement: 
  
  Given an array of ints, is it possible to choose a group of some of the 
  ints, such that the group sums to the given target? 
  
  
  sample calls would be like: 
  
  (groupSum [2, 4, 8] 10) → true 
  (groupSum [2, 4, 8] 14) → true 
  (groupSum [2, 4, 8]  9) → false 
  
  -- 
  You received this message because you are subscribed to the Google 
  Groups Clojure group. 
  To post to this group, send email to clo...@googlegroups.comjavascript: 
  Note that posts from new members are moderated - please be patient with 
 your 
  first post. 
  To unsubscribe from this group, send email to 
  clojure+u...@googlegroups.com javascript: 
  For more options, visit this group at 
  http://groups.google.com/group/clojure?hl=en 


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: recursion question

2012-08-14 Thread Raoul Duke
On Tue, Aug 14, 2012 at 4:17 PM, John Holland jbholl...@gmail.com wrote:
 I thought of doing something like that, but part of the requirements is that
 the sum could be achieved with *some of the numbers in the vector.

in the stupidest approach that is just the same thing as all of the
numbers in the vector with a generator/filter up front that spits out
all the possible 1 length vectors, 2 length vectors, etc. derived from
the total vector? boy i'm just making you think along worse lines
performance-wise, aren't i? like the republicans say, just do the
opposite of whatever i'm saying to do... :-)

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: recursion question

2012-08-14 Thread Raoul Duke
 On Tue, Aug 14, 2012 at 4:17 PM, John Holland jbholl...@gmail.com wrote:
 I thought of doing something like that, but part of the requirements is that
 the sum could be achieved with *some of the numbers in the vector.

the other way of looking at it is that the recursion just quits once
the sum it is carrying along is the desired sum. instead of always
reaching the base case of a unit-length-vector.

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: recursion question

2012-08-14 Thread Andy Fingerhut
An additional step on top of Raoul's:

Take the first #, subtract it from the goal, recursively ask if the remaining 
#s can sum to the now-lesser goal.  If so, return yes, or the set of numbers 
that worked (which should include whatever was returned from the recursive 
call, plus the first #)

If not, recursively ask if the remaining #s can sum to the original goal.  If 
so return yes, or the set of numbers that worked (which does not include the 
first #)

In the worst case, that will try all 2^n possible subsets of the collection of 
numbers, and then return false.

There are dynamic programming methods that work faster if the sum of the 
numbers is small enough, but require holding in memory an array of at least N 
bits, where N is the target.

Andy

On Aug 14, 2012, at 4:17 PM, John Holland wrote:

 I thought of doing something like that, but part of the requirements is that 
 the sum could be achieved with *some of the numbers in the vector.
 
 On Tuesday, August 14, 2012 7:15:27 PM UTC-4, raould wrote:
 ¿ 
 take the first #. 
 subtract that from the goal. 
 now ask if the remaining #s can sum to the now-lesser goal. 
 lather rinse repeat. 
 don't forget a base case. 
 watch your cpu heat very quickly up on even slightly longer lists. 
 ? 
 
 On Tue, Aug 14, 2012 at 4:13 PM, John Holland jbho...@gmail.com wrote: 
  I've been doing some programming exercises in Clojure, I've run into one I 
  don't know how to approach. If anyone can just give me the strategy to use 
  on this that'd be great. Here is the problem statement: 
  
  Given an array of ints, is it possible to choose a group of some of the 
  ints, such that the group sums to the given target? 
  
  
  sample calls would be like: 
  
  (groupSum [2, 4, 8] 10) → true 
  (groupSum [2, 4, 8] 14) → true 
  (groupSum [2, 4, 8]  9) → false 
  
  -- 
  You received this message because you are subscribed to the Google 
  Groups Clojure group. 
  To post to this group, send email to clo...@googlegroups.com 
  Note that posts from new members are moderated - please be patient with 
  your 
  first post. 
  To unsubscribe from this group, send email to 
  clojure+u...@googlegroups.com 
  For more options, visit this group at 
  http://groups.google.com/group/clojure?hl=en 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clojure@googlegroups.com
 Note that posts from new members are moderated - please be patient with your 
 first post.
 To unsubscribe from this group, send email to
 clojure+unsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: recursion question

2012-08-14 Thread John Holland
Thanks for all the help!

On Tuesday, August 14, 2012 7:38:58 PM UTC-4, Andy Fingerhut wrote:

 An additional step on top of Raoul's:

 Take the first #, subtract it from the goal, recursively ask if the 
 remaining #s can sum to the now-lesser goal.  If so, return yes, or the set 
 of numbers that worked (which should include whatever was returned from the 
 recursive call, plus the first #)

 If not, recursively ask if the remaining #s can sum to the original goal. 
  If so return yes, or the set of numbers that worked (which does not 
 include the first #)

 In the worst case, that will try all 2^n possible subsets of the 
 collection of numbers, and then return false.

 There are dynamic programming methods that work faster if the sum of the 
 numbers is small enough, but require holding in memory an array of at least 
 N bits, where N is the target.

 Andy

 On Aug 14, 2012, at 4:17 PM, John Holland wrote:

 I thought of doing something like that, but part of the requirements is 
 that the sum could be achieved with *some of the numbers in the vector.

 On Tuesday, August 14, 2012 7:15:27 PM UTC-4, raould wrote:

 ¿ 
 take the first #. 
 subtract that from the goal. 
 now ask if the remaining #s can sum to the now-lesser goal. 
 lather rinse repeat. 
 don't forget a base case. 
 watch your cpu heat very quickly up on even slightly longer lists. 
 ? 

 On Tue, Aug 14, 2012 at 4:13 PM, John Holland jbho...@gmail.com wrote: 
  I've been doing some programming exercises in Clojure, I've run into 
 one I 
  don't know how to approach. If anyone can just give me the strategy to 
 use 
  on this that'd be great. Here is the problem statement: 
  
  Given an array of ints, is it possible to choose a group of some of the 
  ints, such that the group sums to the given target? 
  
  
  sample calls would be like: 
  
  (groupSum [2, 4, 8] 10) → true 
  (groupSum [2, 4, 8] 14) → true 
  (groupSum [2, 4, 8]  9) → false 
  
  -- 
  You received this message because you are subscribed to the Google 
  Groups Clojure group. 
  To post to this group, send email to clo...@googlegroups.com 
  Note that posts from new members are moderated - please be patient with 
 your 
  first post. 
  To unsubscribe from this group, send email to 
  clojure+u...@googlegroups.com 
  For more options, visit this group at 
  http://groups.google.com/group/clojure?hl=en 


 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@googlegroups.com javascript:
 Note that posts from new members are moderated - please be patient with 
 your first post.
 To unsubscribe from this group, send email to
 clojure+u...@googlegroups.com javascript:
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en




-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Re: recursion question

2012-08-14 Thread John Holland
Ended up with the following wondering if loop/recur is possible in this 
case?

(defn groupSum [a x] (cond
  (= (count a) 0) false
  (= (first a) x) true
  ( (first a) x) (if ( (count a) 1) (groupSum (rest 
a) x) false)
  :else (or
 (groupSum (rest a) (- x (first a)))
 (groupSum (rest a) x


-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en