[Tutor] lambdas, generators, and the like

2014-01-12 Thread Keith Winston
I've got this line:

for k in range(len(tcombo)):
tcombo_ep.append(list(combinations(tcombo, k+1)))

generating every possible length combination of tcombo. I then test
them, and throw most of them away. I need to do this differently, it
gets way too big (crashes my computer).

I'm going to play some more, but I think I need to test the
combinations as they're generated... and then only add them to a list
(probably better: a set) if they meet a requirement (something like
sum(specific.combination(tcombo) == goal)) AND if they are not already
part of that list (the uniqueness issue is why a set might be better)

I'm partially asking in order to clarify the question in my mind, but
any help will be appreciated. I don't really understand lambda
functions yet, but I can sort of imagine they might work here
somehow... or not.

Thanks!

-- 
Keith
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] lambdas, generators, and the like

2014-01-12 Thread Alan Gauld

On 12/01/14 09:04, Keith Winston wrote:


I'm partially asking in order to clarify the question in my mind, but
any help will be appreciated. I don't really understand lambda
functions yet, but I can sort of imagine they might work here
somehow... or not.


lambdas are just a shortcut for single expression functions.
You never need them, they just tidy up the code a bit by
avoiding lots of use-once short functions.

I'm not sure they would help a lot in your example. And,
given you don't understand them yet, they would add
complexity.

hth
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Roelof Wobben
Hello, 
 
Here is the whole exercise with examples. 
 
# By Sam the Great from forums
# That freaking superhero has been frequenting Udacity
# as his favorite boss battle fight stage. The 'Udacity'
# banner keeps breaking, and money is being wasted on
# repairs. This time, we need you to proceduralize the
# fixing process by building a machine to automatically
# search through debris and return the 'Udacity' banner
# to the company, and be able to similarly fix other goods.
# Write a Python procedure fix_machine to take 2 string inputs
# and returns the 2nd input string as the output if all of its
# characters can be found in the 1st input string and Give me
# something that's not useless next time. if it's impossible.
# NOTE: # If you are experiencing difficulties taking
# this problem seriously, please refer back to
# Superhero flyby, the prequel, in Problem Set 11.
# TOOLS: # if statement
 # while loop
 # string operations
 # Unit 1 Basics
# BONUS: # 
# 5* #  If you've graduated from CS101,
#  Gold  #  try solving this in one line.
# Stars! #
def fix_machine(debris, product):
### WRITE YOUR CODE HERE ###
### TEST CASES ###
print Test case 1: , fix_machine('UdaciousUdacitee', 'Udacity') == Give me 
something that's not useless next time.
print Test case 2: , fix_machine('buy me dat Unicorn', 'Udacity') == 'Udacity'
print Test case 3: , fix_machine('AEIOU and sometimes y... c', 'Udacity') == 
'Udacity'
print Test case 4: , fix_machine('wsx0-=mttrhix', 't-shirt') == 't-shirt'
 
Roelof

 
 To: tutor@python.org
 From: alan.ga...@btinternet.com
 Date: Sun, 12 Jan 2014 00:45:11 +
 Subject: Re: [Tutor] another better way to do this ?
 
 On 11/01/14 21:24, Roelof Wobben wrote:
 
  I have two strings a and b
 
  Now I have to check if the characters of b are all in a.
  But they do have to be in the same order.
 
 I'm not sure exactly what you mean? Can you give some examples of
 data that pass and that fail the criteria?
 
 Your algorithm below might meet one definition of the spec but
 its not valid code since it uses return but is not a function.
 
  length = len(b)
  start = 1
  while start  length :
 check = a.find (b[start])
 if check == -1 :
   return False
 start = start + 1
  return True
 
 Problems I see are:
 1) you start testing at b[1] not b[0]
 2) you don't check if the letters are in the same sequence in a as in b
 3) you probably could tidy it up using a for loop over b rather than 
 indexing
 
  But according to the site this can be solved in a one-liner.
 
 That depends on the spec.
 And have you covered regular expressions? That is probably one
 way to do a one-liner...
 
 But just because you can do it in one line doesn't mean you
 should. It's better for code to be readable than short.
 
 
 HTH
 -- 
 Alan G
 Author of the Learn to Program web site
 http://www.alan-g.me.uk/
 http://www.flickr.com/photos/alangauldphotos
 
 ___
 Tutor maillist  -  Tutor@python.org
 To unsubscribe or change subscription options:
 https://mail.python.org/mailman/listinfo/tutor
  ___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] lambdas, generators, and the like

2014-01-12 Thread Keith Winston
On Sun, Jan 12, 2014 at 4:19 AM, Alan Gauld alan.ga...@btinternet.com wrote:
 lambdas are just a shortcut for single expression functions.
 You never need them, they just tidy up the code a bit by
 avoiding lots of use-once short functions.


Thanks, I figured out how to iterate the combinations function. I'll
play with lambda functions some other time. I've been cranking away on
the Project Euler stuff, it's great fun, good Python practice...

-- 
Keith
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Alan Gauld

On 12/01/14 08:12, Roelof Wobben wrote:


# Write a Python procedure fix_machine to take 2 string inputs
# and returns the 2nd input string as the output if all of its
# characters can be found in the 1st input string and Give me
# something that's not useless next time. if it's impossible.


OK So there is nothing here about the orders being the same.
That makes it much easier.


# 5* #  If you've graduated from CS101,
#  Gold  #  try solving this in one line.


Its not too hard to do in one line.
I think a filtered list comprehension and the all() function
would be one way.


print Test case 1: , fix_machine('UdaciousUdacitee', 'Udacity') ==
Give me something that's not useless next time.
print Test case 2: , fix_machine('buy me dat Unicorn', 'Udacity') ==
'Udacity'
print Test case 3: , fix_machine('AEIOU and sometimes y... c',
'Udacity') == 'Udacity'
print Test case 4: , fix_machine('wsx0-=mttrhix', 't-shirt') == 't-shirt'


I'd not use the while loop personally, I'd go for a for loop over b
and use the in operation on a. So Something like

for letter in b:
   if letter not in a:
   return   
return b

HTH
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Peter Otten
Alan Gauld wrote:

 On 12/01/14 08:12, Roelof Wobben wrote:
 
 # Write a Python procedure fix_machine to take 2 string inputs
 # and returns the 2nd input string as the output if all of its
 # characters can be found in the 1st input string and Give me
 # something that's not useless next time. if it's impossible.
 
 OK So there is nothing here about the orders being the same.
 That makes it much easier.
 
 # 5* #  If you've graduated from CS101,
 #  Gold  #  try solving this in one line.
 
 Its not too hard to do in one line.
 I think a filtered list comprehension and the all() function
 would be one way.
 
 print Test case 1: , fix_machine('UdaciousUdacitee', 'Udacity') ==
 Give me something that's not useless next time.
 print Test case 2: , fix_machine('buy me dat Unicorn', 'Udacity') ==
 'Udacity'
 print Test case 3: , fix_machine('AEIOU and sometimes y... c',
 'Udacity') == 'Udacity'
 print Test case 4: , fix_machine('wsx0-=mttrhix', 't-shirt') ==
 't-shirt'
 
 I'd not use the while loop personally, I'd go for a for loop over b
 and use the in operation on a. So Something like
 
 for letter in b:
 if letter not in a:
 return   
 return b

The test cases are not explicit about what to do with multiple occurences of 
the same letter. I'd expect that debris must contain two 't's for 't-shirt' 
to match. So:

print Test case 5: , fix_machine('wsx0-=mtrhix', 't-shirt') == Give me 
something that's not useless next time.

If my assumption is correct a containment test is not sufficient; you need 
to count the characters:

def fix_machine(debris, product):
return (product
if all(debris.count(c) = product.count(c) for c in 
set(product))
else Give me something that's not useless next time.)

OP: You'll get bonus points (from me, so they're pointless points, but 
still) if you can solve this (including the fifth apocryphal test case) 
using the collections.Counter class.

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] lambdas, generators, and the like

2014-01-12 Thread Dave Angel
 Keith Winston keithw...@gmail.com Wrote in message:
 I've got this line:
 
 for k in range(len(tcombo)):
 tcombo_ep.append(list(combinations(tcombo, k+1)))
 
 generating every possible length combination of tcombo. I then test
 them, and throw most of them away. I need to do this differently, it
 gets way too big (crashes my computer).
 
You should learn how to write and use a generator. Anytime you
 find yourself creating a huge list, and only navigating it once, 
 consider writing a generator instead. A generator is any function
 that has a yield in it. You can turn the loop above into a
 one-level generator by

def gen (tcombo):
for k in range (len (tcombo))
  yield list (combinations (tcombo, k+1))

And depending how you use the nested list, remove the call to list
 () for some real serious space savings. 

(untested)



 any help will be appreciated. I don't really understand lambda
 functions yet, but I can sort of imagine they might work here
 somehow... or not.
 
A lambda is seldom necessary or useful in simple programs. 
 


-- 
DaveA nr



Android NewsGroup Reader
http://www.piaohong.tk/newsgroup

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Dave Angel
 Roelof Wobben rwob...@hotmail.com Wrote in message:

That documentation says nothing about order.  And the test cases
 specifically contradict it.

so try

if set (b) = set (a):


-- 
DaveA



Android NewsGroup Reader
http://www.piaohong.tk/newsgroup

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread eryksun
On Sun, Jan 12, 2014 at 8:21 AM, Peter Otten __pete...@web.de wrote:

 OP: You'll get bonus points (from me, so they're pointless points, but
 still) if you can solve this (including the fifth apocryphal test case)
 using the collections.Counter class.

Hint:

 print(Counter.__sub__.__doc__)
 Subtract count, but keep only results with positive counts.

 Counter('abbbc') - Counter('bccd')
Counter({'b': 2, 'a': 1})

 product = Counter('t-shirt')
 product - Counter('wsx0-=mttrhix')
Counter()
 product - Counter('wsx0-=mtrhix')
Counter({'t': 1})

`Counter` has multiset methods for the operators +, -, 
(intersection; min count), and | (union; max count). However, it
doesn't implement the `issubset` or `issuperset` methods of `set`, nor
the ordered comparisons (, , =, =) that depend on them.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Alan Gauld

On 12/01/14 14:43, Dave Angel wrote:


so try

if set (b) = set (a):


Ooh, nice! For some reason I've never thought of
applying set to a string before.


--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] lambdas, generators, and the like

2014-01-12 Thread Keith Winston
Thanks Dave, that looks like a good idea, I've played a little with
one-line generators (? the things similar to list comprehensions), but
I'm still wrapping my head around how to use them. Meanwhile I'm
reorganizing my code because I now understand better how to use
iterators (i.e. the combinations function), and I'm exploring using
tuples where I can instead of lists... if I followed an earlier
conversation properly, I think garbage collection might happen more
immediately with immutables than mutables, and this program is
crashing either Python or my entire computer every time I run it...
I'm generating a LOT of combinations.

On Sun, Jan 12, 2014 at 9:33 AM, Dave Angel da...@davea.name wrote:
  Keith Winston keithw...@gmail.com Wrote in message:
 I've got this line:

 for k in range(len(tcombo)):
 tcombo_ep.append(list(combinations(tcombo, k+1)))

 generating every possible length combination of tcombo. I then test
 them, and throw most of them away. I need to do this differently, it
 gets way too big (crashes my computer).

 You should learn how to write and use a generator. Anytime you
  find yourself creating a huge list, and only navigating it once,
  consider writing a generator instead. A generator is any function
  that has a yield in it. You can turn the loop above into a
  one-level generator by

 def gen (tcombo):
 for k in range (len (tcombo))
   yield list (combinations (tcombo, k+1))

 And depending how you use the nested list, remove the call to list
  () for some real serious space savings.

 (untested)



 any help will be appreciated. I don't really understand lambda
 functions yet, but I can sort of imagine they might work here
 somehow... or not.

 A lambda is seldom necessary or useful in simple programs.



 --
 DaveA nr



 Android NewsGroup Reader
 http://www.piaohong.tk/newsgroup

 ___
 Tutor maillist  -  Tutor@python.org
 To unsubscribe or change subscription options:
 https://mail.python.org/mailman/listinfo/tutor



-- 
Keith
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Keith Winston
On Sun, Jan 12, 2014 at 7:44 AM, Alan Gauld alan.ga...@btinternet.com wrote:
 OK So there is nothing here about the orders being the same.
 That makes it much easier.


There's another approach, I think, that's quite easy if order IS important.

Iterate through the letters of product, find() them initially from the
beginning of debris, and then from the index of the last letter found.
Accounts for multiples in product,  order.

def fix_machine(debris, product):
index = 0
success = False
for letter in product:
test = debris.find(letter, index)
if test:
index = test
else:   # Failure
return Give me something that's not useless next time.
return product   # Success

I suspect this could be done in one line, without regex, but it would
probably take me a week to figure out... maybe next week ;)

-- 
Keith
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Mark Lawrence

On 12/01/2014 19:22, Keith Winston wrote:

On Sun, Jan 12, 2014 at 7:44 AM, Alan Gauld alan.ga...@btinternet.com wrote:

OK So there is nothing here about the orders being the same.
That makes it much easier.



There's another approach, I think, that's quite easy if order IS important.

Iterate through the letters of product, find() them initially from the
beginning of debris, and then from the index of the last letter found.
Accounts for multiples in product,  order.

def fix_machine(debris, product):
 index = 0
 success = False
 for letter in product:
 test = debris.find(letter, index)
 if test:
 index = test
 else:   # Failure
 return Give me something that's not useless next time.
 return product   # Success

I suspect this could be done in one line, without regex, but it would
probably take me a week to figure out... maybe next week ;)



A better idea would be to find out why the above dosn't work correctly, 
I'll leave that in your capable hands :)


--
My fellow Pythonistas, ask not what our language can do for you, ask 
what you can do for our language.


Mark Lawrence

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Keith Winston
OOps, I never used the success boolean in my code, but forgot to
remove it. Sorry.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Keith Winston
On Sun, Jan 12, 2014 at 2:22 PM, Keith Winston keithw...@gmail.com wrote:
 if test:

Sigh and this line needs to read (if it's going to do what I said):

if test != -1:



-- 
Keith
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread eryksun
On Sun, Jan 12, 2014 at 2:38 PM, Keith Winston keithw...@gmail.com wrote:
 On Sun, Jan 12, 2014 at 2:22 PM, Keith Winston keithw...@gmail.com wrote:
 if test:

 Sigh and this line needs to read (if it's going to do what I said):

 if test != -1:

Consider the case of `product == letter`. Do you want to double
match on the 't' found in `debris`? I'm +1 for finding a solution...
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Keith Winston
On Sun, Jan 12, 2014 at 2:38 PM, Keith Winston keithw...@gmail.com wrote:
 Sigh and this line needs to read (if it's going to do what I said):

As  Alan pointed out, the examples provided do NOT account for order,
so if one uses my (corrected) algorithm, you get different results
from the examples. Without the fix you get the example results, but
may not realize that it's not accounting for repeats in that case
(which the instructions don't address either). It might be
instructive, if it's not already obvious, to understand why this would
be...
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Emile van Sebille

On 01/12/2014 06:43 AM, Dave Angel wrote:

  Roelof Wobben rwob...@hotmail.com Wrote in message:

That documentation says nothing about order.  And the test cases
  specifically contradict it.

so try

if set (b) = set (a):


or, as the OP specified, if order is relevant,

def test(a,b):
  for ii in a:
if ii not in b: a=a.replace(ii,)
  return b in a

Emile





___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Peter Otten
Emile van Sebille wrote:

 On 01/12/2014 06:43 AM, Dave Angel wrote:
   Roelof Wobben rwob...@hotmail.com Wrote in message:

 That documentation says nothing about order.  And the test cases
   specifically contradict it.

 so try

 if set (b) = set (a):
 
 or, as the OP specified, if order is relevant,
 
 def test(a,b):
for ii in a:
  if ii not in b: a=a.replace(ii,)
return b in a

 def test(a,b):
...for ii in a:
...  if ii not in b: a=a.replace(ii,)
...return b in a
... 
 test(axbxc, abc)
True
 test(abbxc, abc)
False

Is the second result desired?

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Emile van Sebille

On 01/12/2014 12:21 PM, Peter Otten wrote:


test(axbxc, abc)

True

test(abbxc, abc)

False

Is the second result desired?


No -- the second should match -- you found a test case I didn't...

def test(a,b):
  for ii in a:
if ii not in b: a=a.replace(ii,)
while ii+ii in a: a=a.replace(ii+ii,ii)
  return b in a

Show me another.  :)

Emile




___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Peter Otten
Emile van Sebille wrote:

 On 01/12/2014 12:21 PM, Peter Otten wrote:
 
 test(axbxc, abc)
 True
 test(abbxc, abc)
 False

 Is the second result desired?
 
 No -- the second should match -- you found a test case I didn't...
 
 def test(a,b):
for ii in a:
  if ii not in b: a=a.replace(ii,)
  while ii+ii in a: a=a.replace(ii+ii,ii)
return b in a
 
 Show me another.  :)

 def test(a,b):
...for ii in a:
...  if ii not in b: a=a.replace(ii,)
...  while ii+ii in a: a=a.replace(ii+ii,ii)
...return b in a
... 
 test(abac, abc)
False


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] another better way to do this ?

2014-01-12 Thread Keith Winston
On Sun, Jan 12, 2014 at 2:22 PM, Keith Winston keithw...@gmail.com wrote:
 There's another approach, I think, that's quite easy if order IS important.

Alas, there's one further problem with my script, relating to testing
multiple sequential letters in product... but I'm not going to say
more, I'll leave it as a problem for the OP. It's an easy fix once you
understand the issue.

-- 
Keith
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Euler Spoiler

2014-01-12 Thread Keith Winston
I'm working through some of the Project Euler problems, and the
following might spoil one of the problems, so perhaps you don't want
to read further...


The problem relates to finding all possible combinations of coins that
equal a given total. I'm basically brute-forcing it, which is probably
not the way to go, but has already taught me a good bit about sets,
tuples, and iterators, so... so far so good.

However, after all the refactoring I can think of, I can't get it past
a 3-coin list without it bogging down.

I'm sure there are wholly different approaches, feel free to hint at
them, but my real question is: is there any further fine-tuning of my
approach (or any outright problems with it) that would be instructive?
Thanks!

Also: I think it might have worked better with lists that tuples,
though I don't really understand why, unless I misunderstand speed or
memory management issues (or something else).

from itertools import combinations

coins = [100, 50, 20]  # should include 1, 2, 5, 10 (plus one 200 combo)
ans = set()
goal = 200
tcombo = ()

# Iterate over all possible length combinations of coins
for i in range(len(coins)):
print(i)
# For each unique combo of coins, and...
for combo in combinations(coins, i+1):
tcombo = ()
# For each coin in that combo...
for coin in combo:
# create a new tuple of as many of those coins as
# it would take to reach the goal
tcombo = tcombo + (coin,) * int(goal/coin)
# with this new extended list, generate all possible
length combinations
for k in range(len(tcombo)):
for c in combinations(tcombo, k + 1):
if sum(c) == goal:
ans = ans | {c}

print(ans)


-- 
Keith
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Euler Spoiler

2014-01-12 Thread Walter Prins
Hi Keith,

On 12 January 2014 23:12, Keith Winston keithw...@gmail.com wrote:

 I'm working through some of the Project Euler problems, and the
 following might spoil one of the problems, so perhaps you don't want
 to read further...


 The problem relates to finding all possible combinations of coins that
 equal a given total. I'm basically brute-forcing it, which is probably
 not the way to go, but has already taught me a good bit about sets,
 tuples, and iterators, so... so far so good.

 However, after all the refactoring I can think of, I can't get it past
 a 3-coin list without it bogging down.


Sorry I haven't got time to look at your attempt closely (nearly 1am here),
but try/have a look at this:

from itertools import chain, combinations

def powerset(iterable):
powerset([1,2,3]) -- () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)
#Taken from: http://docs.python.org/2/library/itertools.html
#(It doesn't strictly operate on or generate sets as can be seen.)
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

coins = [100, 50, 20, 20, 10, 10, 10]
goal = 200

solutions = set(list(s for s in powerset(coins) if sum(s) == goal))
print solutions
# outputs: set([(100, 50, 20, 20, 10), (100, 50, 20, 10, 10, 10)])



Walter
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Euler Spoiler

2014-01-12 Thread Danny Yoo
This sounds very much like a problem that demands trying to break the
problems down into subproblems, and then applying a
dynamic-programming approach to make it fairly easy to get an
efficient solution.  Such problems that are amendable to this approach
have a substructure to them so that the main problem breaks down
into smaller versions of the same problem.


As an example, Problem 15 on Lattice paths is a good one:

   http://projecteuler.net/problem=15

Here, the problem is asking: count how many paths there are in the n*n
grid.  A sub-problem of this is: count how many paths there are in the
(n-1)*n graph, and count how many paths there are in the N*(n-1) grid.
 Why are those particular subproblems interesting?  Because if you
have the answer for the (n-1)*n and the n*(n-1), then you add the
results of those two together, and you get the answer for the original
n*n case!


Another example of a dynamic programming situation is in Problem 18,

http://projecteuler.net/problem=18

where we can decompose the problem of trying to find the path that
maximizes the sum from the triangle as a whole to the sub-triangles on
the left and right hand sides.


In your problem statement, you're trying to answer the question:

Given some goal g, find all the ways to break change.

A subproblem of this is:

Given some goal (g - x) for each x in the denominations, find all
the ways to break change.

That is, a trick to solving the problem is to treat 'goal' as a
variable, part of the problem statement that can be changed.


Are you familiar with the dynamic programming approach?  I'm sure
folks here would be happy to talk about it more and show concrete
examples; it's a very powerful tool.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Euler Spoiler

2014-01-12 Thread Dave Angel
 Keith Winston keithw...@gmail.com Wrote in message:
 I'm working through some of the Project Euler problems, and the
 following might spoil one of the problems, so perhaps you don't want
 to read further...
 
 
 The problem relates to finding all possible combinations of coins that
 equal a given total. I'm basically brute-forcing it, which is probably
 not the way to go, but has already taught me a good bit about sets,
 tuples, and iterators, so... so far so good.
 
 However, after all the refactoring I can think of, I can't get it past
 a 3-coin list without it bogging down.

Care to define bogging down?  If you mean it gets REALLY slow
 then I'm not surprised.  Do you have any idea how many
 combinations there are for even a moderate sized list of
 coins?

For the call  combinations(tcombo, k + 1) with k =99 and tcombo of
 size 200, the number of iterations has 59 digits.  With a really
 fast computer you might scratch the surface in a trillion
 trillion trillion years.

One way to improve on that enormously would be to scrap tcombo and
 call itertool.combinations_with_replacement. But I think the
 notion of generating all combinations and then selecting is
 doomed to failure for all but the smallest problems.

Incidentally I think you have way too many nested loops. Even if
 brute force were going to work,  you'd do it with
 itertool.combinations_with_replacement(coins without doing combo
 or tcombo. 


-- 
DaveA



Android NewsGroup Reader
http://www.piaohong.tk/newsgroup

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Euler Spoiler

2014-01-12 Thread Keith Winston
Thanks everyone, things to chew on. I'll look at the other itertools
functions mentioned. I did solve Proj. Euler 15  18 (and it's
corresponding 67), one more elegantly than the other, and I have given
some thought to how to break this one down, but haven't figured it out
yet. I think I might not be willing to wait a trillion years. I think
I'm going to stop development on this approach, both 1) because I
don't think it's going to work, and 2) because I might have learned
most of what I can from it, re: Python skills.

I am quite interested in the dynamic programming approach, which I
understand my approach to PE 18 was consistent with, but which I don't
yet understand how to apply more broadly or consistently. I'll do some
reading on it.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Euler Spoiler

2014-01-12 Thread Danny Yoo
To be concrete, I think you're looking at Problem 31, right?

http://projecteuler.net/problem=31

in which case, we have a few choices for denomination:

1p, 2p, 5p, 10p, 20p, 50p, 100p, 200p

and we're trying to _count_ how many ways to make 200p.



Here's a sketch of how I'd attack this by considering a DP-style
approach.  If you want to avoid any spoilers, please skip this
message.

Otherwise, I'll try to be as transparent as to my thought process as I can.

---

We first want to name and conquer.

Let C(k) be the number of ways to make change for 'k' pence.

Why C(k)?  Because I think C(200) is what we're looking for.  I'm
making 'k' be the parameter here because I think an approach that
tries to figure out C, where n ranges from [0-200], should do the
trick.


Note: for now, let's assume that C does not remember _how_ we're
making the change.  It should only remember the number of ways to do
so.



What are some values for C?  Let us try to reason what C must be for
low values of 'k'.

--

C(0) = 1.  There's one way to make change for zero pence, namely the
empty case.  It might be important to argue this edge case, so that's
why I'm considering it.

--

C(1) = 1.  We know we can do this one trivially.

1p

--

C(2) = 2.  We can either do it as:

1p + 1p, or
2p

--

C(3) = 2.  We can do it as:

2p + 1p, or
1p + 1p + 1p.



Note: we don't want to treat:

1p + 2p

as another possibility!

Why not?  Because that would be a duplicate of

2p + 1p

which we already counted for already.

Believe it or not, this observation is important, because we'll find
in a few moments that it forces us to reconsider an amendment to our
approach.

---


One observation so far: it looks like we can construct more of C by
looking at previous elements of C.  That would mean we just run
through constructing C bottom-up, from k=1 through 200.  If that's
the case, then we're golden.  We can just keep the intermediate values
of C as an array of ints.

Easy.

Or not.  :P  Let's see what happens.


--

C(4) = ...?

This is starting not to be so obvious.

Let's try to reason it out.  From our observation, let's see if we can
just take previous elements that we computed for C and just sum it up
in some nice way.

If we're trying to make change for four pence, then...

1.  If there's a change-making sequence that starts of as:

2p + ...,

for example, the ... would stand for ways of making change for the
remainder 4p - 2p == 2p.

Looking back at how we computed C(2), we could make C(2) out of:

1p + 1p, or
2p

So if we just put 2p in front of those, that gives us:

2p + 1p + 1p, or
2p + 2p.

Good!


2.  If there's a change-making sequence that starts off as 1p + ...,
for example, the ... would stand for the ways of making change for
the remainder 4p - 1p == 3p.

Looking back at how we computed C(3), we know that it was constructed out of:

2p + 1p, or
1p + 1p + 1p.

So maybe we can just put 1p in front of those!

1p + ... ways of making C(3)

==

1p + 2p + 1p, or
1p + 1p + 1p + 1p.


... Oh!  But wait, we don't want to count:

1p + 2p + 1p

because we already did that, essentially, when we did

2p + 1p + 1p

In fact, we ran into this issue earlier on when we were trying to
figure out C(3).


So C(4) is 3, because we can make it out of:

2p + 1p + 1p, or
2p + 2p, or
1p + 1p + 1p + 1p.

---

Huh.  That wasn't as simple as just adding up previous values for C.  Nuts.


Let's think about this a bit.  Earlier, we were hoping we could just
naively look at C for previous values of k, and just add them up.  But
we want to make sure we DON'T over-count ways of making the change.


The difficulty that we're running across is due to the structure of C:
it doesn't let us know if we're counting a change-making that already
takes into consideration something we already counted.

What to do?

Maybe our earlier approach, to not remember how exactly we're making
the change, can be amended.

One approach might be to change the return type of C.  Rather than
have it keep track of just the number of ways of counting change, we
might instead hold onto a description of the change sums themselves.
This should work!  But it would mean that we have to hold a list of
list of denominations.  And we'd have to do an additional
duplication-filtering step.  But we know we can do it this way, if we
really needed to.



But there is another approach.  I will sketch this approach out
because I'm pretty sure it's the one the problem writers intended.

Let's look again at that troublesome change-making that's causing us grief:

1p + 2p + 1p

We don't want this because it's a duplicate of:

2p + 1p + 1p

Well, what's different about it?  The numbers are in a different
order.  The case we don't care particularly for, 1p + 2p + 1p,