Re: Python newbie needs constructive suggestions

2006-07-22 Thread David G. Wonnacott
Many thanks to those of you who responded to my question about
anonymous functions with local variables, filling me in on

  e) do something else clever and Pythonic that I don't know about yet?

by pointing out that I can use (among other good things) lambda with
default arguments. That should suit my immediate needs well, since I
don't need to maintain state (or avoid maintaning state); I may also
look into closures (possibly anonymous ones?) and callable classes if
I need to go beyond this. And, of course, if the code is complex
enough, then one should give up the anonymous function and name it.

Rest assured that I will _not_ be attempting to write "let" in Python
and use it.

It looks like Python may be every much as big an improvement over C++
as I had hoped.

Dave Wonnacott
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: random shuffles

2006-07-22 Thread David G. Wonnacott
   From: "danielx" <[EMAIL PROTECTED]>
   Date: 22 Jul 2006 01:43:30 -0700

   Boris Borcic wrote:
   > does
   >
   > x.sort(cmp = lambda x,y : cmp(random.random(),0.5))
   >
   > pick a random shuffle of x with uniform distribution ?

...

   Let e be the element which was in the first position to begin with.
   What are its chances of being there after being "sorted"? Well, in
   order for it to still be there, it would have to survive N rounds of
   selection. In each selection, it has 1/2 chance of surviving. That
   means its total chance of survival is 1/(2**N), which is much less than
   1/N. QED!


This proof makes sense to me if the sorting algorithm makes a random
decision every time it swaps.

Couldn't we easily get an n*log(n) shuffle by performing a _single_
mapping of each element in the collection to a pair made up of a
random key and its value, and then sorting based on the keys and
stripping them out? i.e., in O(n) time, turn

   "2 clubs", "2 diamonds", "2 hearts", "2 spades", "3 clubs"

into something like

   [0.395, "2 clubs"], [0.158, "2 diamonds"], [0.432, "2 hearts"], [0.192, "2 
spades"], [0.266, "3 clubs"]

and then in O(n*log(n)) time, sort it into

   [0.158, "2 diamonds"], [0.192, "2 spades"], [0.266, "3 clubs"], [0.395, "2 
clubs"], [0.432, "2 hearts"]

and then strip out the keys again in O(n) time?

Or perhaps this has been discussed already and I missed that part? I
just joined the list... apologies if this is a repeat.



   You can accomplish this by doing what I will call "random selection".
   It would be like linear selection, except you wouldn't bother checking
   the head against every other element. When you want to figure out what
   to put at the head, just pick at random! I suspect this is what Python
   does in random.shuffle, since it is rather an easy to see it would
   result in something uniform (I swear I haven't looked at the source
   code for random.shuffle :P).


But, after making the linear selection, don't you still need to use
O(log(n)) time to find and remove the item from the collection? I
don't know much about Python's internal data structures, but if
there's an array in there, you need O(n) time to move up everything
after the deleted item; if there's a list, you need O(n) time to find
the element you picked at random; if there's a balanced tree, you
could find it and delete it in O(log(n)) time...

Help me review my undergraduate data structures here -- is there some
way to pick each item _exactly_once_ in O(n) time?

Dave Wonnacott

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Python-list Digest, Vol 34, Issue 373

2006-07-24 Thread David G. Wonnacott
O.K., I'll publicly retract this for the whole list -- EVERYBODY
PLEASE DISREGARD my thought about implementing an n*log(n) shuffle.

I had hinted in my message that this was probably something that I
should review from a data structures course, and of course there was a
simple oversight in my message: you don't have to preserve the order
of the collection from which you extract the element, so you can
extract it in O(1) time by just swapping it, and easily get an O(n)
shuffle algorithm (or, more easily, call random.shuffle()).

Thanks for the polite tone with which many folks have pointed out my
gross oversight.

for i in range(1,100):
print "I will not post to the Python list without thinking first"

Now suitably embarrassed,
Dave Wonnacott


   Date: 24 Jul 2006 06:24:48 -0700
   From: "Ben Sizer" <[EMAIL PROTECTED]>
   Subject: Re: random shuffles
   To: python-list@python.org

   Ross Ridge wrote:
   > David G. Wonnacott wrote:
   > > Couldn't we easily get an n*log(n) shuffle...
   >
   > Why are you trying to get an O(n*log(n)) shuffle when an O(n) shuffle
   > algorithim is well known and implemented in Python as random.shuffle()?

   I think David is referring to this: "don't you still need to use
   O(log(n)) time to find and remove the item from the collection?"

   The answer for him is no: as far as I know, the Python list is a
   random-access structure, so looking up 2 items and swapping them runs
   in constant time. You perform that N times to shuffle the sequence, so
   it runs in O(N).

   -- 
   Ben Sizer
-- 
http://mail.python.org/mailman/listinfo/python-list


P.S. Re: Python newbie needs constructive suggestions

2006-07-24 Thread David G. Wonnacott
In response to my question, ``What is the idiomatically appropriate
Python way to pass, as a "function-type parameter", code that is most
clearly written with a local variable?'', a number of you made very
helpful suggestions, including the use of a default argument; if one
wanted to give a name to the constant one in my original example,

   map(lambda x: x+1, [5, 17, 49.5])

one would write

   map(lambda x, one=1: x+one, [5, 17, 49.5])

I've been using this happily in several cases, but just discovered
that (of course), the variable "x" is not in scope until the
expression in the lambda, so if one wanted to, say, have a variable
that was 3*x, one could NOT write

   map(lambda x, threex=3*x: x+threex, [5, 17, 49.5])

[obviously there are easier ways to find 4*x, but I'm trying to keep
close to my simplified example].

I'll need to show the code to beginners, so I don't want to get into
the complexity of using the more advanced solutions that were
suggested (closures or callable classes), so I'm going to bail out in
such cases and just not use an anonymous function here.

I'm not sure there's really a question here, other than the implicit
"please let me know if there's yet another cool thing I can do here",
but I thought I'd add this postscript to my earlier postings for the
benefit of anyone following this thread. [I often see interesting
threads in the archive but am left with an unresolved question "I
wonder how that worked out"].

Dave Wonnacott

-- 
http://mail.python.org/mailman/listinfo/python-list