Re: [Twisted-Python] Counting errors in a DeferredList and avoiding Unhandled error in Deferred messages

2008-05-05 Thread Terry Jones
Hi Jean-Paul

 You can do this (if you replace `pass´ with `None´, anyway) or you can pass
 `consumeErrors=True´ to the `DeferredList´ initializer which will make it
 do something equivalent.

Thanks. Sorry - I should have just read the docs again :-)

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


Re: Global variables in modules...

2008-03-28 Thread Terry Jones
 Peter == Peter Otten [EMAIL PROTECTED] writes:
Peter [EMAIL PROTECTED] wrote:
[snip]
 ...can someone explain why invoking a.py prints 0?
 I would have thought that the global variable 'g' of module 'a' would
 be set to 1...

Peter When you run a.py as a script it is put into the sys.modules module
Peter cache under the key __main__ instead of a. Thus, when you import
Peter a the cache lookup fails and a.py is executed again. You end up with
Peter two distinct copies of the script and its globals
[snip]


Suggesting the following horribleness in a.py

g = 0

def main():
global g
import b
g = 1
b.callb()

if __name__ == __main__:
import sys, __main__
sys.modules['a'] = __main__
main()


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


Question on using distutils.core.run_setup

2008-03-17 Thread Terry Jones
I'm trying to programmatically install something built using distutils. I
found distutils.core.run_setup and can use it via

   dist = run_setup('setup.py', ['-q', 'install'])

Is that the recommended way to do an install from inside Python (as opposed
to doing it on the command line)?

If so, how can I find where the thing(s) I installed now resides?  I saw
dist.packages but that just has top-level package names. I could __import__
these (and then use module.__file__), but that's not a good solution as it
may run code I don't want run. On my machine, I can see the packages have
been installed under the system's python2.5/site-packages directory. But
how can I determine that programmatically? I don't see anything useful on
the distutils.dist.Distribution instance I'm getting back from run_setup.

Thanks!

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


Re: European python developers

2008-02-26 Thread Terry Jones
Hi Jerry

 I am hoping one or two members of this list might help me locate in Europe

Do you mean you want to re-locate here or that you're trying to locate
(i.e., find) people already here?

 My personal first choice is Spain

I'm in Barcelona (but not looking for work!).  There are a couple of
companies around that I know of who use Python and quite a lot of
individual programmers.

 The point is that I can't really afford to run around and experiment, so I
 was hoping for some helpful comments or suggestions on how to research

I'm not sure what you're wanting to research. See first comment above.

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


Re: flattening a dict

2008-02-17 Thread Terry Jones
Hi Arnaud  Benjamin

Here's a version that's a bit more general. It handles keys whose values
are empty dicts (assigning None to the value in the result), and also dict
keys that are not strings (see the test data below). It's also less
recursive as it only calls itself on values that are dicts.

But it returns a dict whose keys are tuples. You then need to decide
what to do with this. Hence the helper function strdictflatten for the case
when all dict keys can be converted to str.

As I told Arnaud in email, I greatly prefer his version for its elegance.

Terry


def dictflatten(d, prefix=None):
result = {}
if prefix is None: prefix = tuple()
for k, v in d.iteritems():
key = prefix + (k,)
if isinstance(v, dict):
if v:
result.update(dictflatten(v, key))
else:
result[key] = None
else:
result[key] = v
return result

def strdictflatten(d, sep='/'):
return dict((sep.join(map(str, k)), v) for k, v in 
dictflatten(d).iteritems())

if __name__ == '__main__':
test = {
 : {},
4 : 5,
mays : {eggs : spam},
jam : {soda : {love : dump}},
lamba : 23
}

d = dictflatten(test)
print strdictflatten(test)

 {'': None, 'lamba': 23, 'mays/eggs': 'spam', '4': 5, 'jam/soda/love': 
 'dump'}
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: flattening a dict

2008-02-17 Thread Terry Jones
 Arnaud == Arnaud Delobelle [EMAIL PROTECTED] writes:

Arnaud BTW, I keep using the idiom itertools.chain(*iterable).  I guess
Arnaud that during function calls *iterable gets expanded to a tuple.
Arnaud Wouldn't it be nice to have an equivalent one-argument function
Arnaud that takes an iterable of iterables and return the 'flattened'
Arnaud iterable?

This reminds me of a function I wrote a while back that iterates over all
its arguments, even calling passed functions and iterating over their
results. I knew *even less* about Python then than I do now; please set
flamethrowers to Constructive Criticism.

  http://www.fluidinfo.com/terry/2007/05/07/iteranything/

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


Re: type, object hierarchy?

2008-02-03 Thread Terry Jones
 Arnaud == Arnaud Delobelle [EMAIL PROTECTED] writes:

Arnaud Are you suggesting a new axiom for propositional logic:
Arnaud ((P = Q) ^ (R = Q)) = (P = R)  ?

Arnaud I.e. in fruit logic: every orange is a fruit and every apple is a
Arnaud fruit, therefore every orange is an apple.

This is otherwise known as Winterson's law:

  1. Every orange is a fruit
  2. Every apple is a fruit

  = Oranges are not the only fruit

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


Re: Just for fun: Countdown numbers game solver

2008-01-25 Thread Terry Jones
My output looks better sorted. I.e., for s in sorted(solutions)...

Giving the easier to read/compare:

Target 234, numbers = (100, 9, 7, 6, 3, 1)
(6, 1, 'add', 100, 'mul', 7, 'sub', 9, 'add', 3, 'div')
(6, 9, 'sub', 7, 'mul', 1, 'sub', 100, 'add', 3, 'mul')
(7, 3, 'mul', 6, 'sub', 9, 'mul', 1, 'sub', 100, 'add')
(7, 6, 'mul', 3, 'mul', 1, 'sub', 100, 'add', 9, 'add')
(7, 6, 'mul', 3, 'mul', 100, 'sub', 9, 'mul', 1, 'mul')
(100, 1, 'sub', 3, 'div', 7, 'mul', 6, 'sub', 9, 'add')
(100, 1, 'sub', 7, 'mul', 9, 'sub', 3, 'div', 6, 'add')
(100, 7, 'mul', 3, 'mul', 6, 'add', 9, 'div', 1, 'mul') *
(100, 7, 'mul', 6, 'sub', 1, 'sub', 9, 'add', 3, 'div')
(100, 7, 'sub', 3, 'div', 1, 'sub', 9, 'add', 6, 'mul')
(100, 7, 'sub', 3, 'div', 6, 'sub', 1, 'add', 9, 'mul')
(100, 9, 'add', 7, 'add', 1, 'add', 3, 'div', 6, 'mul')
(100, 9, 'sub', 7, 'div', 6, 'mul', 3, 'mul', 1, 'mul')
(100, 9, 'sub', 7, 'sub', 6, 'sub', 3, 'mul', 1, 'mul')

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


Re: Text-based data inspector for Python?

2008-01-24 Thread Terry Jones
 kj == kj  [EMAIL PROTECTED] writes:

kj I've only recently started programming in Python, trying to wean
kj myself from Perl.  One of the things I *really* miss from Perl is
kj a 100% mouse-free data inspector, affectionally known as the Perl
kj debugger, PerlDB, or just perl -d.  With it I can examine the most
kj elaborate data structures with ease:

You actually liked the perl debugger... gasp!  OK, I used it too, but it
left a few things to be desired (the mouse was not one).

kj And, since it's text-based, I can run it within a shell in Emacs, and
kj transfer anything I want between it and an editing buffer without even
kj a THOUGHT of touching the filthy mouse!  If there's a greater joy in
kj life I have yet to find it.

I use M-x pydb to debug python from inside emacs. I like it more than the
straight pdb as it's a bit more like gdb.

In pydb (and pdb) there's p and pp to print and pretty print a python
object. They work pretty well  there's no need for the mouse.

kj NOTE: In my address everything before the first period is backwards;
kj and the last period, and everything after it, should be discarded.

Nice. See 
http://www.fluidinfo.com/terry/2007/10/31/stagnant-email-address-arms-race/

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


Re: Just for fun: Countdown numbers game solver

2008-01-23 Thread Terry Jones
Hi Arnaud and Dan

 Arnaud == Arnaud Delobelle [EMAIL PROTECTED] writes:
 What was wrong with the very fast(?) code you sent earlier?

Arnaud I thought it was a bit convoluted, wanted to try something I
Arnaud thought had more potential.  I think the problem with the second
Arnaud one is that I repeat the same 'fold' too many times.

and later:

Arnaud Yes, I've been doing this by writing an 'action' (see my code) that
Arnaud takes note of all reached results.

These are both comments about pruning, if I understand you. In the first
you weren't pruning enough and in the second you're planning to prune more.

I'm giving up thinking about this problem because I've realized that the
pruning solution is fundamentally subjective. I.e., whether or not you
consider two solutions to be the same depends on how hard you're willing
to think about them (and argue that they're the same), or how smart you
are.

I have a new version that does some things nicely, but in trying to do
efficient pruning, I've realized that you can't satisfy everyone.

Some examples for the problem with target 253, numbers = 100, 9, 7, 6, 3, 1

Firstly, there are nice solutions that go way negative, like:

  1 7 6 3 9 sub mul mul sub   or   1 - 7 * 6 * (3 - 9)


Here's a pruning example. Are these the same?

  1 3 7 100 9 sub sub mul sub  or  1 - 3 * (7 - 100 - 9)
  1 3 7 9 100 sub add mul sub  or  1 - 3 * (7 - 9 - 100)

I think many people would argue that that's really the same and that one
of the two should not appear in the output. The same goes for your earlier
example for 406. It's 4 * 100 + 2 x 3, and 2 x 3 + 100 * 4, and so on.

My latest program does all these prunings.

But you can argue that you should push even further into eliminating things
that are the same. You could probably make a pretty fast program that
stores globally all the states it has passed through (what's on the stack,
what numbers are yet to be used, what's the proposed op) and never does
them again. But if you push that, you'll wind up saying that any two 
solutions that look like this:

  ... 1 add

e.g.

  6 9 3 sub mul 7 mul 1 add   or  6 * (9 - 3) * 7 + 1
  7 6 mul 9 3 sub mul 1 add   or  7 * 6 * (9 - 3) + 1

are the same. And if we go that far, then a really smart person might argue
that this

  100 7 sub 9 sub 3 mul 1 add  or  (100 - 7 - 9) * 3 + 1

is also the same (because all these solutions get to 252 and then add 1,
so they're clearly the same, right?):


Once you've gone that far, you might even argue that on a particular
problem of a particular difficulty (subjectively matching what your brain
is capable of) all solutions that start out by pushing 1 onto the stack are
actually the same.

And if you're even smarter than that, you might just look at any problem
and say Hey, that's easy! The answer is X or There's clearly no
solution because you'd immediately just see the answer (if any) and that
all others were just obvious variants.

E.g., if I said to you: make 20 out of (20, 10, 10, 3), I imagine you
could immediately list the answer(s?)

  20 = 20
  20 = 10 + 10
  20 = 20 + 10 - 10
  20 = 20 - 10 + 10

etc., and explain that those are all really the same. You'd prune on the
spot, and consider it obvious that the pruning was fully justified.

But my 6-year-old son couldn't tell you that, and I doubt he'd agree with
your prunings.

OK, enough examples.  I'm just trying to illustrate that the (difficult)
problem of efficiently pruning doesn't have an objective solution.  Pruning
is subjective. OTOH, the decision problem does this puzzle have any
solutions or not (and if so, produce one) does.

That's why I'm going to stop working on this. My stack solution code is
fun, but working on making it prune better is a black hole. And to make
matters worse, the more I push it (i.e., the more advanced its prunings
get), the less likely (some) people are to agree that its output is still
correct. You can't win.

If anyone wants the stack simulation code, send me an email.

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


Re: Just for fun: Countdown numbers game solver

2008-01-23 Thread Terry Jones
 Arnaud == Arnaud Delobelle [EMAIL PROTECTED] writes:

Arnaud FWIW, I have a clear idea of what the space of solutions is, and
Arnaud which solutions I consider to be equivalent.  I'll explain it
Arnaud below.  I'm not saying it's the right model, but it's the one
Arnaud within which I'm thinking.

OK. This reinforces why I'm not going to work on it anymore, the solution
is subjective (once you start pruning).

Arnaud I think it's best to forbid negatives.  Solutions always be written
Arnaud without any negative intermediate answer.  E.g. 1-7*6*(3-9) can be
Arnaud done as 1+7*6*(9-3).

That's a good optimization, and I think it's easy to prove that it's
correct supposing the target is positive and the inputs are all positive.

If you consider the intermediate results in a solution, then if you ever go
negative it's because of an operation X (must be a sub or a div) and when
you next become positive it's due to an operation Y (must be add or
mul). So you can reflect that part of the computation by doing the
opposite operations for that formerly sub-zero intermediate sequence.

Arnaud I don't consider these to be equivalent, because their equivalence
Arnaud depends on understanding the meaning of subtraction and addition.

Ha - you can't have it both ways Arnaud! You don't want the computation to
go negative... doesn't that (and my proof) have something to do with the
inverse nature of add and sub? :-)

Arnaud (I've also applied the 'big then small' rule explained below)

And now you're taking advantage of your knowledge of  and  ...

My original code did this big then small canonicalization too.

That's my point exactly - pruning depends on who you are, how smart you
are, how hard you work, your personal taste, etc.

Arnaud I see a solution as a full ordered binary tree.  Each node has a
Arnaud weight (which is the result of the calculation it represents) and
Arnaud the left child of a node has to be at least as heavy as the right
Arnaud child.  Each parent node can be labeled + - * or /.  If a node x
Arnaud has two children y and z and is labeled op, let me write x = (y
Arnaud op z)

Where does the sequence of numbers enter into this? You have a tree of
operations - is it acting on a stack? What's on the stack?

It sounds similar to what I've done. I walk up and down the tree, keeping
the stack and the stack history, doing operations (including pushing onto
the stack) and undoing them.

There are several more prunings I could be doing, but these require looking
further back in the stack.  E.g., I force div before mul and sub before
add, and I also apply the big then small rule to the intermediate stack
results if there are series of identical operations (not just to a single
operation). E.g. X / Y / Z can be re-ordered so that Y = Z, and A + B + C
can be reordered so A = B = C. Doing it on the stack results is different
(but similar) to doing it on the raw input numbers.

There are lots of other little and more complex things you can do to prune.

You want to prune early, of course. The stack model of computation make
this hard because it's always legitimate to push all the numbers onto the
stack, by which point you're already deep in the tree.

And this approach only lets you do local pruning - i.e., that affect the
branch of the tree you're on. If you stored the state of the stack, the
operation you're about to do, and the (sorted) numbers remaining to be
input, then if you ever hit that configuration elsewhere in the massive
tree, you could know that you'd been that way before. But are you justified
in pruning at that point? The identical state of the computation could have
been arrived at via a very different method.

But that's where the big speed-up in this approach is.

At this realization I decided to give up :-)

Arnaud To be perfectly honest (and expose my approach a little to your
Arnaud argument) I added a three additional rules:

Arnaud * Don't allow x - x
Arnaud * Don't allow x * 1
Arnaud * Don't allow x / 1

Yes, I do these too, including not allowing a zero intermediate (which is a
useless calculation that simply could not have been done - see, I have deep
knowledge of zero!).

Arnaud If there are repeats in the list of starting numbers, I don't worry
Arnaud about repeating solutions.

I handle most of those cases, but I didn't push all the way. With target 32
and input 8, 8, 8, 8 my code still gives 2 answers:

8 8 add 8 8 add add
8 8 add 8 add 8 add

 If anyone wants the stack simulation code, send me an email.

Arnaud I'd like to see it :)

I'll send it.

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


Re: Just for fun: Countdown numbers game solver

2008-01-23 Thread Terry Jones
 Arnaud == Arnaud Delobelle [EMAIL PROTECTED] writes:
 
 Ha - you can't have it both ways Arnaud! You don't want the computation to
 go negative... doesn't that (and my proof) have something to do with the
 inverse nature of add and sub? :-)

Arnaud I think I can have it both ways, here's why: the big then small
Arnaud and no negatives rules are applied indiscriminately by the
Arnaud algorithm: it doesn't need to know about the history of operations
Arnaud in order to make a decision depending on their nature.  OTOH,
Arnaud identifying (a + b) - c and a + (b - c) for example, requires
Arnaud inspection of the stack/tree/ calculation history.  It is an
Arnaud *informed* decision made by the algorithm

But this is having it both ways too :-)

The reason the algorithm can do it indiscriminately is because *you* know
that it always applies, and *you* figure out and implement the algorithm
that way. The algorithm doesn't have a mind of its own, after all.

BTW, there are some very important issues here. One is about representation
(thinking about representation is one of my pet vices). When you try to
solve some real-world problem with a computer, you must choose a
representation. What many people seem to fail to recognize is that in so
doing you've already begun to solve the problem. If you pick a better
representation, your algorithm can potentially be much dumber and still be
hugely faster than a brilliant algorithm on a terrible representation.

In maintaining an A  B invariant in operations A + B and A * B, you're
using insight into the problem to influence representation. With that
better representation, your algorithm doesn't have to do so much work.

I wrote some more about this a while ago at

  
http://www.fluidinfo.com/terry/2007/03/19/why-data-information-representation-is-the-key-to-the-coming-semantic-web/

Arnaud Note that disallowing 0 and disallowing x - x are equivalent, as
Arnaud the only way to get your first 0 is by doing x - x.

That depends. I allow negative numbers in the input, and also 0 (I just
don't let you use it :-))

Arnaud Thanks for the discussion, it's made me realise more clearly what I
Arnaud was doing.

Me too! Thanks.

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


Re: Just for fun: Countdown numbers game solver

2008-01-22 Thread Terry Jones
Hi Arnaud

 I've tried a completely different approach, that I imagine as 'folding'.  I
 thought it would improve performance over my previous effort but extremely
 limited and crude benchmarking seems to indicate disappointingly comparable
 performance...

I wrote a stack-based version yesterday and it's also slow. It keeps track
of the stack computation and allows you to backtrack. I'll post it
sometime, but it's too slow for my liking and I need to put in some more
optimizations. I'm trying not to think about this problem.

What was wrong with the very fast(?) code you sent earlier?

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


Re: Just for fun: Countdown numbers game solver

2008-01-21 Thread Terry Jones
 Arnaud == Arnaud Delobelle [EMAIL PROTECTED] writes:
Arnaud In countdown you are not required to use all numbers to reach the
Arnaud target.  This means you are missing solutions, e.g.  (1, 3, 6,
Arnaud 'mul', 'add', 7 , 'add', 9, 'mul')

Hi Arnaud.

Thanks, I didn't know that. The fix is a simple change to the first if my
function below.

WRT to the missing solution, note that my code only allowed multiplication
by 1 if it was the last thing done. That was because you can multiply by 1
at any time, and I didn't want to see those trivially equivalent solutions
(same goes for adding 0). Seeing as you're allowed to omit numbers, I've
now gotten rid of those trivial operations altogether in my solution.

Code and output below.

Terry


from operator import *

def countdown(target, nums, numsAvail, value, partialSolution, solutions, 
ops=(add, mul, sub, div)):
if value == target or not any(numsAvail):
# Ran out of available numbers. Add the solution, if we're right.
if value == target:
solutions.add(tuple(partialSolution))
elif value is None:
# Use each distinct number as a starting value.
used = set()
for i, num in enumerate(nums):
if num not in used:
numsAvail[i] = False
used.add(num)
partialSolution.append(num)
countdown(target, nums, numsAvail, num, partialSolution, 
solutions, ops)
numsAvail[i] = True
partialSolution.pop()
else:
for op in ops:
for i, num in enumerate(nums):
if numsAvail[i]:
numsAvail[i] = False
moreAvail = any(numsAvail)
try:
lastNum, lastOp = partialSolution[-2:]
except ValueError:
lastNum, lastOp = partialSolution[-1], None
# Don't allow any of:
if not any((
# Div: after mul, by 1, by 0, producing a fraction.
(op == div and (lastOp == 'mul' or num = 1 or value % 
num != 0)),
# If initial mul/add, canonicalize to 2nd operator 
biggest.
((op == mul or op == add) and lastOp is None and num  
lastNum),
# Don't allow add or sub of 0.
((op == add or op == sub) and num == 0),
# Don't allow mult by 1.
(op == mul and num == 1),
# Don't allow sub after add (allow add after sub).
(op == sub and lastOp == 'add'),
# If same op twice in a row, canonicalize operand order.
(lastOp == op.__name__ and num  lastNum)
)):
partialSolution.extend([num, op.__name__])
countdown(target, nums, numsAvail, op(value, num), 
partialSolution, solutions, ops)
del partialSolution[-2:]
numsAvail[i] = True

for nums, target in (((100, 9, 7, 6, 3, 1), 253),
 ((100, 9, 7, 6, 3, 1), 234),
 ((2, 3, 5), 21),
 ((7, 8, 50, 8, 1, 3), 923),
 ((8, 8), 16),
 ((8, 8, 8), 8),
 ((8, 0), 8),
 ((7,), 8),
 ((), 8),
 ((8, 8, 8, 8), 32)):
solutions = set()
countdown(target, nums, [True,] * len(nums), value=None, 
partialSolution=[], solutions=solutions)
print %d solutions to: target %d, numbers = %s % (len(solutions), target, 
nums)
for s in sorted(solutions, cmp=lambda a, b: cmp(len(a), len(b)) or cmp(a, 
b)):
print '\t', s


$ time countdown.py 
8 solutions to: target 253, numbers = (100, 9, 7, 6, 3, 1)
(6, 3, 'mul', 1, 'sub', 9, 'mul', 100, 'add')
(7, 6, 'mul', 9, 'add', 3, 'mul', 100, 'add')
(9, 3, 'sub', 7, 'mul', 6, 'mul', 1, 'add')
(100, 9, 'sub', 7, 'sub', 3, 'mul', 1, 'add')
(3, 1, 'add', 6, 'mul', 7, 'sub', 9, 'mul', 100, 'add')
(7, 1, 'add', 6, 'mul', 3, 'mul', 100, 'add', 9, 'add')
(7, 6, 'add', 3, 'add', 1, 'add', 9, 'mul', 100, 'add')
(100, 7, 'sub', 6, 'sub', 3, 'mul', 9, 'sub', 1, 'add')
19 solutions to: target 234, numbers = (100, 9, 7, 6, 3, 1)
(6, 3, 'mul', 7, 'add', 1, 'add', 9, 'mul')
(7, 1, 'add', 9, 'mul', 6, 'add', 3, 'mul')
(7, 3, 'mul', 1, 'sub', 6, 'add', 9, 'mul')
(7, 6, 'mul', 3, 'mul', 100, 'sub', 9, 'mul')
(100, 1, 'sub', 3, 'div', 7, 'sub', 9, 'mul')
(100, 1, 'sub', 7, 'mul', 9, 'add', 3, 'div')
(100, 7, 'mul', 3, 'mul', 6, 'add', 9, 'div')
(100, 9, 'sub', 7, 'div', 6, 'mul', 3, 'mul')
(100, 9, 'sub', 7, 'sub', 6, 'sub', 3, 'mul')
(6, 1, 'add', 100, 'mul', 7, 'sub', 9, 'add', 3, 'div')
(6, 9, 

Re: Just for fun: Countdown numbers game solver

2008-01-21 Thread Terry Jones
 Paul == Paul Rubin http://phr.cx@NOSPAM.invalid writes:

Hi Paul

Paul Here's my latest, which I think is exhaustive, but it is very slow.
Paul It prints a progress message now and then just to give the user some
Paul sign of life.  It should print a total of 256-8 = 248 of those
Paul messages and it takes around 20 minutes on my old 1 Ghz Pentium 3.
Paul It does find plenty of solutions for 234, e.g.

Paul 234 mul(9,sub(mul(mul(6,mul(3,1)),7),100))

Paul There are some obvious clunky ways to speed it up through memoizing
Paul and symmetry folding but I can't help thinking there's a concise
Paul elegant way to do that too.

The symmetry folding is important, you can cut off many recursive calls. My
code runs in 0.5 seconds for the 234 problem, but I have a MacBook Pro :-)

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


Re: Just for fun: Countdown numbers game solver

2008-01-21 Thread Terry Jones
 dg == dg google groups [EMAIL PROTECTED] writes:

dg It's great how many different sorts of solutions (or almost solutions)
dg this puzzle has generated. Speedwise, for reference my solution posted
dg above takes about 40 seconds on my 1.8GHz laptop, and the less elegant
dg version (on my webpage linked to in the original post) takes about 15
dg seconds. It seems to me like surely this problem can be more
dg efficiently solved than that?

dg Paul: 758 = 8+(5*((2+4)*25))

For this I get:

2 solutions to: target 758, numbers = (2, 4, 5, 8, 25)
(4, 2, 'add', 25, 'mul', 5, 'mul', 8, 'add')
(25, 4, 'mul', 5, 'sub', 8, 'mul', 2, 'sub')

real0m0.118s
user0m0.074s
sys 0m0.044s


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


Re: Just for fun: Countdown numbers game solver

2008-01-21 Thread Terry Jones
 cokofreedom == cokofreedom  [EMAIL PROTECTED] writes:

cokofreedom Terry, your technique is efficient and pretty readable! All
cokofreedom that could be added now is a way to output the data in a more
cokofreedom user-friendly print.

Yes, and a fix for the bug Arnaud just pointed out :-)
Below is code to print things more nicely for you.

Terry


from operator import *
from itertools import izip

def countdown(target, nums, numsAvail, value, partialSolution, solutions, 
ops=(add, mul, sub, div)):
if value == target or not any(numsAvail):
# Add the solution, if we're right.
if value == target:
solutions.add(tuple(partialSolution))
elif value is None:
# Use each distinct number as a starting value.
used = set()
for i, num in enumerate(nums):
if num not in used:
numsAvail[i] = False
used.add(num)
partialSolution.append(num)
countdown(target, nums, numsAvail, num, partialSolution, 
solutions, ops)
numsAvail[i] = True
partialSolution.pop()
else:
for op in ops:
for i, num in enumerate(nums):
if numsAvail[i]:
numsAvail[i] = False
moreAvail = any(numsAvail)
try:
lastNum, lastOp = partialSolution[-2:]
except ValueError:
lastNum, lastOp = partialSolution[-1], None
# Don't allow any of:
if not (
# Div: after mul, by 1, by 0, producing a fraction.
(op == div and (lastOp == 'mul' or num = 1 or value % 
num != 0)) or
# If initial mul/add, canonicalize to 2nd operator 
biggest.
((op == mul or op == add) and lastOp is None and num  
lastNum) or
# Don't allow add or sub of 0.
((op == add or op == sub) and num == 0) or
# Don't allow mult by 1.
(op == mul and num == 1) or
# Don't allow sub after add (allow add after sub).
(op == sub and lastOp == 'add') or
# If same op twice in a row, canonicalize operand order.
(lastOp == op.__name__ and num  lastNum)
):
partialSolution.extend([num, op.__name__])
countdown(target, nums, numsAvail, op(value, num), 
partialSolution, solutions, ops)
del partialSolution[-2:]
numsAvail[i] = True

op2sym = { 'add' : '+', 'sub' : '-', 'mul' : '*', 'div': '/', }

def pretty(s):
out = [str(s[0])]
lastOp = None
for value, op in izip(*(iter(s[1:]),) * 2):
if (op == 'mul' or op == 'div') and (lastOp == 'add' or lastOp == 
'sub'):
out.insert(0, '(')
out.append(')')
out.append(op2sym[op])
out.append(str(value))
lastOp = op
return ''.join(out)

for nums, target in (
((100, 9, 7, 6, 3, 1), 253),
((100, 9, 7, 6, 3, 1), 234),
((2, 3, 5), 21),
((7, 8, 50, 8, 1, 3), 923),
((8, 8), 16),
((8, 8, 8), 8),
((8, 0), 8),
((7,), 8),
((), 8),
((8, 8, 8, 8), 32),
((2, 4, 5, 8, 25), 758),
((2, 3, 4, 100), 406),
):
solutions = set()
countdown(target, nums, [True,] * len(nums), value=None, 
partialSolution=[], solutions=solutions)
print %d solutions to: target %d, numbers = %s % (len(solutions), target, 
nums)
for s in sorted(solutions, cmp=lambda a, b: cmp(len(a), len(b)) or cmp(a, 
b)):
print '\t', pretty(s)


Sample output:

8 solutions to: target 253, numbers = (100, 9, 7, 6, 3, 1)
(6*3-1)*9+100
(7*6+9)*3+100
(9-3)*7*6+1
(100-9-7)*3+1
((3+1)*6-7)*9+100
(7+1)*6*3+100+9
(7+6+3+1)*9+100
(100-7-6)*3-9+1
19 solutions to: target 234, numbers = (100, 9, 7, 6, 3, 1)
(6*3+7+1)*9
((7+1)*9+6)*3
(7*3-1+6)*9
(7*6*3-100)*9
((100-1)/3-7)*9
((100-1)*7+9)/3
(100*7*3+6)/9
(100-9)/7*6*3
(100-9-7-6)*3
((6+1)*100-7+9)/3
((6-9)*7-1+100)*3
(7*3-6)*9-1+100
7*6*3-1+100+9
(100-1)/3*7-6+9
((100-1)*7-9)/3+6
(100*7-6-1+9)/3
((100-7)/3-1+9)*6
((100-7)/3-6+1)*9
(100+9+7+1)/3*6
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Just for fun: Countdown numbers game solver

2008-01-21 Thread Terry Jones
 Arnaud == Arnaud Delobelle [EMAIL PROTECTED] writes:

Arnaud Sorry I gave an incorrect example to illustrate my question last
Arnaud night (I blame this on baby-induced sleep deprivation ;), so I'll
Arnaud have another go:

Arnaud Say I have 2, 3, 4, 100 and I want to make 406.  AFAICS there is only
Arnaud one way: (2*3)+(4*100), i.e. in postfix notation:
Arnaud 2 3 * 4 100 * +

Arnaud It seemed to me that your function wouldn't generate that sort of
Arnaud solution (as you always extend partialSolution by [num, op] making
Arnaud the subsequence [mul, add] impossible).  Am I wrong?

No, you're right.  I actually started out with a stack solution, and then
switched to something simpler (too simple). I'm going to redo it, but maybe
not right now...

Thanks!

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


Re: Just for fun: Countdown numbers game solver

2008-01-20 Thread Terry Jones
Here's a solution that doesn't use any copying of lists in for recursion.
It also eliminates a bunch of trivially equivalent solutions. The countdown
function is 37 lines of non-comment code.  Sample (RPN) output below.

Terry


from operator import *

def countdown(target, nums, numsAvail, value, partialSolution, solutions, 
ops=(add, mul, sub, div)):
if not any(numsAvail):
# Ran out of available numbers. Add the solution, if we're right.
if value == target:
solutions.add(tuple(partialSolution))
elif value is None:
# Use each distinct number as a starting value.
used = set()
for i, num in enumerate(nums):
if num not in used:
numsAvail[i] = False
used.add(num)
partialSolution.append(num)
countdown(target, nums, numsAvail, num, partialSolution, 
solutions, ops)
numsAvail[i] = True
partialSolution.pop()
else:
for op in ops:
for i, num in enumerate(nums):
if numsAvail[i]:
numsAvail[i] = False
moreAvail = any(numsAvail)
try:
lastNum, lastOp = partialSolution[-2:]
except ValueError:
lastNum, lastOp = partialSolution[-1], None
# Don't allow any of:
if not any((
# Div: after mul, by 1, by 0, producing a fraction.
(op == div and (lastOp == 'mul' or num = 1 or value % 
num != 0)),
# If initial mul/add, canonicalize to 2nd operator 
biggest.
((op == mul or op == add) and lastOp is None and num  
lastNum),
# Don't all subtracting 0 (instead allow adding 0).
(op == sub and num == 0),
# Don't allow adding 0 unless it's the very last thing 
we do.
(op == add and num == 0 and moreAvail),
# Don't allow mult by 1 unless it's the very last thing 
we do.
(op == mul and num == 1 and moreAvail),
# Don't allow sub after add (allow add after sub).
(op == sub and lastOp == 'add'),
# If same op twice in a row, canonicalize operand order.
(lastOp == op.__name__ and num  lastNum)
)):
partialSolution.extend([num, op.__name__])
countdown(target, nums, numsAvail, op(value, num), 
partialSolution, solutions, ops)
del partialSolution[-2:]
numsAvail[i] = True

for nums, target in (((100, 9, 7, 6, 3, 1), 253),
 ((100, 9, 7, 6, 3, 1), 234),
 ((2, 3, 5), 21),
 ((7, 8, 50, 8, 1, 3), 923),
 ((8, 8), 16),
 ((8, 8, 8), 8),
 ((8, 0), 8),
 ((7,), 8),
 ((), 8),
 ((8, 8, 8, 8), 32)):
print Target %d, numbers = %s % (target, nums)
solutions = set()
countdown(target, nums, [True,] * len(nums), value=None, 
partialSolution=[], solutions=solutions)
for s in solutions: print '\t', s


This produces:

Target 253, numbers = (100, 9, 7, 6, 3, 1)
(7, 6, 'add', 3, 'add', 1, 'add', 9, 'mul', 100, 'add')
(7, 6, 'mul', 9, 'add', 3, 'mul', 100, 'add', 1, 'mul')
(3, 1, 'add', 6, 'mul', 7, 'sub', 9, 'mul', 100, 'add')
(100, 7, 'sub', 6, 'sub', 3, 'mul', 9, 'sub', 1, 'add')
(7, 1, 'add', 6, 'mul', 3, 'mul', 100, 'add', 9, 'add')
Target 234, numbers = (100, 9, 7, 6, 3, 1)
(6, 1, 'add', 100, 'mul', 7, 'sub', 9, 'add', 3, 'div')
(100, 1, 'sub', 3, 'div', 7, 'mul', 6, 'sub', 9, 'add')
(7, 6, 'mul', 3, 'mul', 100, 'sub', 9, 'mul', 1, 'mul')
(100, 7, 'sub', 3, 'div', 6, 'sub', 1, 'add', 9, 'mul')
(7, 6, 'mul', 3, 'mul', 1, 'sub', 100, 'add', 9, 'add')
(6, 9, 'sub', 7, 'mul', 1, 'sub', 100, 'add', 3, 'mul')
(100, 9, 'sub', 7, 'sub', 6, 'sub', 3, 'mul', 1, 'mul')
(100, 7, 'mul', 3, 'mul', 6, 'add', 9, 'div', 1, 'mul')
(100, 1, 'sub', 7, 'mul', 9, 'sub', 3, 'div', 6, 'add')
(100, 7, 'sub', 3, 'div', 1, 'sub', 9, 'add', 6, 'mul')
(7, 3, 'mul', 6, 'sub', 9, 'mul', 1, 'sub', 100, 'add')
(100, 7, 'mul', 6, 'sub', 1, 'sub', 9, 'add', 3, 'div')
(100, 9, 'add', 7, 'add', 1, 'add', 3, 'div', 6, 'mul')
(100, 9, 'sub', 7, 'div', 6, 'mul', 3, 'mul', 1, 'mul')
Target 21, numbers = (2, 3, 5)
(5, 2, 'add', 3, 'mul')
Target 923, numbers = (7, 8, 50, 8, 1, 3)
(50, 8, 'mul', 1, 'sub', 3, 'div', 7, 'mul', 8, 'sub')
Target 16, numbers = (8, 8)
(8, 8, 'add')
Target 8, numbers = (8, 8, 8)
(8, 8, 'sub', 8, 

Re: writing Python in Emacs

2008-01-19 Thread Terry Jones
 Richard == Richard Szopa [EMAIL PROTECTED] writes:

Richard I am a devoted Emacs user and I write a lot in Python.

Me too.

Richard I need the following features:

Richard 1) Tab completion, ideally Slime like. That is, when there's not
Richard enough letters to unambiguously complete a symbol, I want it to
Richard show a buffer (w/o taking the focus) w/ the possible
Richard completions. In an ideal world, it would be able to complete
Richard fo.baTAB to foo.bar. I imagine this would require quite tight
Richard Emacs-Python integration.

I know this is not what you want, but I use hippie expand (M-/) to cycle
through possible completions. It's not Python aware, but it is of some use.

Richard 2) Sending the toplevel definition (class or function) to the Python
Richard buffer.

I switched to IPython to have better interaction with a spawned Python.

To use IPython you need to use the Python mode that is NOT the one from
(endorsed?) by the FSF. It gives you some completion (at least in the
*Python* buffer) and you can send pieces of the buffer to the python
process, via py-send-region (C-c |), py-execute-def-or-class (M-C-x), etc.

Richard 3) Hints on function/method arguments. IDLE has this done nearly
Richard right, but the hints are a bit too intrusive for me. I would like to
Richard see them in the minibuffer.

I don't have this.

Richard 4) (optional) I would like to see the definition of a function
Richard function or class by hitting M-. on its name. (I understand that
Richard this may be impossible for methods, as Emacs would have to
Richard automagically infer the type of the object).

This is just an emacs tag file need. Have you googled for something like
emacs tags python? The issue of methods might be overcome by just moving
through tags with the same name. Yes, that requires _you_ to know when
you've hit the right thing. That's not optimal, but it's better than
nothing. Ideally you could send the definition to IPython, ask it for the
class info, and use that to jump to the right tag.

Richard I have tried a couple of times both python-modes (the one shipped w/
Richard Python and the one shipped w/ Emacs), pymacs and stuff like that...
Richard And, as I said, never got it right. But, maybe I just cannot find the
Richard way to configure it, and some configuration hints will be enough...

If you have the time, please summarize your findings. The emacs/python
world has always seemed quite amorphous to me too.

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


RE: Some Berkeley DB questions (being maintained? queries?)

2008-01-17 Thread Terry Jones
 Brian == Brian Smith [EMAIL PROTECTED] writes:
Brian [EMAIL PROTECTED] wrote:

 2. Are there good python libraries for bdb available, that 
 are being maintained?

Brian I would like to know the answer to this question too--if you have
Brian used the pybsddb/bsddb.db module, please share your experience.

I used it a little in mid-2006. I ran into one issue that I resolved by
looking at the C source and fiddling with the Python interface. I sent mail
to the people mentioned in the bsddb README file. One (Barry Warsaw)
answered to say he hadn't looked at the code in a couple of years and was
probably not the person to contact.

 4. What are good, stable alternatives?

From memory, the Chandler project also has an interface to BSD DB, but I
don't remember any details at all.

I'm also interested in any ongoing or planned work on the Python interface.

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


Re: Open a List of Files

2008-01-09 Thread Terry Jones
 Fredrik == Fredrik Lundh [EMAIL PROTECTED] writes:

Fredrik Seriously, for a limited number of files, the dictionary approach
Fredrik is mostly pointless; you end up replacing

Fredrik foo = open(foo)
Fredrik foo.write(...)

Fredrik with

Fredrik somedict[foo] = open(foo)
Fredrik somedict[foo].write(...)

Yes, in some cases. But where you want to do multiple things you can always
pull the file descriptor of of the dict into a local var.

 - It has less risk of error (much less repetition).

Fredrik No, it hasn't.  There's more to type when using the files, and you
Fredrik have *two* things you can misspell; that is, you're replacing a
Fredrik NameError with either a NameError or a Key Error.

Well I meant less error risk in the context of opening the files. And I'm
happy to get a NameError or KeyError if I make the mistake you describe.
But bad code like this:

messages = open(os.path.join(host_path,'messages.txt'), 'wb')
deliveries = open(os.path.join(host_path,'deliveries.txt'), 'wb')
actions = open(os.path.join(host_path,'deliveries.txt'), 'wb')

doesn't give an error at all, and with all that identical and
semi-identical code it's much less obvious where the error is.

Cut  paste errors like this are pretty common, and they can be quite hard
to find (when they don't result in exceptions), in my experience.

 - It allows your code to later take a string file tag and
 write to that file by looking up its file descriptor in the dict.

Fredrik Instead of allowing your code to take a file object and write to that 
Fredrik file by writing to that file object?

No, see below:

 - You can close all open files with a trivial loop.

Fredrik Ok, this is actually an advantage.  Not that you need to do that very 
Fredrik often, since Python does it for you.

Yes.  That's partly why I said it would make him a better programmer in
general, not just in Python.

Fredrik And if you find yourself needing to do this a lot, you can of
Fredrik course stuff all the output files in a list but *still* use the
Fredrik variables to refer to the file when writing to them.

Yes, as above.

Fredrik There is one case where a dictionary of files makes perfect sense, of 
Fredrik course, and that's when you can associate the file with some *other* 
Fredrik value that you're *already* using. (Say, a user name or a machine name 
Fredrik or a severity level or something like that.)

Yes. That's what I meant by my original - badly worded - remark (see above)
that you could take a string file tag and use it to look up its file
descriptor.

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


Re: Open a List of Files

2008-01-09 Thread Terry Jones
 BJ == BJ Swope [EMAIL PROTECTED] writes:

I (at least) think the code looks much nicer.

BJ #Referring to files to write in various places...
BJ open_files['deliveries'].write(flat_line)
BJ open_files['deliveries'].write('\n')

If you were doing a lot with the deliveries file at some point, you could
put the file descriptor into a local variable

  deliveries = open_files['deliveries']
  deliveries.write(flat_line)
  deliveries.write('\n')

BJ #And finally to close the opened files
BJ for fn in open_files.keys():
BJ open_files[fn].close()

You don't need for fn in open_files.keys():, you can just use for fn in
open_files:, but simpler than that is to just use the dictionary values:

for fn in open_files.values():
fn.close()

Regards,
Terry
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Open a List of Files

2008-01-08 Thread Terry Jones
Hi BJ

  Fredrik Lundh [EMAIL PROTECTED] writes:
  Or in a dict:
 
  open_files = {}
  for fn in ['messages', 'recipients', 'viruses']:
 open_files[fn] = open(getfilename(fn), 'w')
 
 I decided that I was just trying to be too smooth by 1/2 so I fell back
 to ...
 
 messages = open(os.path.join(host_path,'messages.txt'), 'wb')
 deliveries = open(os.path.join(host_path,'deliveries.txt'), 'wb')
 actions = open(os.path.join(host_path,'actions.txt'), 'wb')
 parts = open(os.path.join(host_path,'parts.txt'), 'wb')
 recipients = open(os.path.join(host_path,'recipients.txt'), 'wb')
 viruses = open(os.path.join(host_path,'viruses.txt'), 'wb')
 esp_scores = open(os.path.join(host_path,'esp_scores.txt'), 'wb')

I think you should revisit this decision.  Something like Fredrik's code is
the way to go.  It has multiple advantages:

 - It's much shorter.
 - It's arguably easier to add/remove to/from.
 - It has less risk of error (much less repetition).
 - It allows your code to later take a string file tag and
   write to that file by looking up its file descriptor in the dict.
 - You can close all open files with a trivial loop.

Also, if you start writing code like Fredrik's instead of like what you
fell back on you'll make yourself a better programmer (in general, not just
in Python).

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


Re: Two candies

2008-01-02 Thread Terry Jones
 Raymond == Raymond Hettinger [EMAIL PROTECTED] writes:
Raymond * in most apps (except for sparse arrays), the initialization time
Raymond for an array is dominated by the time spent actually doing
Raymond something useful with the array (iow, this is an odd place to be
Raymond optimizing)

This brings to mind an old algorithms chestnut (exercise 2.12 in the 1st
edition of Aho, Hopcroft  Ullman [1]):

If the implementation of an algorithm uses (for simplicity's sake) a square
array to represent its data, why are _all_ such algorithms not necessarily
O(n^2) due simply to the initialization requirement (supposing a model of
computation that counts assignments)?

Terry

[1] 
http://www.amazon.com/Analysis-Algorithms-Addison-Wesley-Information-Processing/dp/0201000296
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: getting n items at a time from a generator

2007-12-29 Thread Terry Jones
Hi Igor

 Igor == Igor V Rafienko [EMAIL PROTECTED] writes:

 Also consider this solution from O'Reilly's Python Cookbook (2nd Ed.)
 p705
 
 def chop(iterable, length=2):
 return izip(*(iter(iterable),) * length)

Igor Is this *always* guaranteed by the language to work? Should the
Igor iterator returned by izip() change the implementation and evaluate
Igor the underlying iterators in, say, reverse order, the solution would
Igor no longer function, would it? Or is it something the return value of
Igor izip() would never do?

Igor (I am just trying to understand the solution, not criticize it. Took
Igor a while to parse the argument(s) to izip in the example).

I had to look at it a bit too.  I actually deleted the comment I wrote
about it in my own code before posting it here and decided to simply say
consider in the above instead :-)

As far as I understand it, you're right. The docstring for izip doesn't
guarantee that it will pull items from the passed iterables in any order.
So an alternate implementation of izip might produce other results. If it
did them in reverse order you'd get each n-chunk reversed, etc.

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


Re: getting n items at a time from a generator

2007-12-27 Thread Terry Jones
 Kugutsumen == Kugutsumen  [EMAIL PROTECTED] writes:
Kugutsumen On Dec 27, 7:07 pm, Paul Hankin [EMAIL PROTECTED] wrote:
 On Dec 27, 11:34 am, Kugutsumen [EMAIL PROTECTED] wrote:
 
  I am relatively new the python language and I am afraid to be missing
  some clever construct or built-in way equivalent to my 'chunk'
  generator below.

Kugutsumen Thanks, I am going to take a look at itertools.  I prefer the
Kugutsumen list version since I need to buffer that chunk in memory at
Kugutsumen this point.

Also consider this solution from O'Reilly's Python Cookbook (2nd Ed.) p705

def chop(iterable, length=2):
return izip(*(iter(iterable),) * length)

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


Re: Taxicab Numbers

2007-12-27 Thread Terry Jones
 rgalgon == rgalgon  [EMAIL PROTECTED] writes:

rgalgon I'm new to Python and have been putting my mind to learning it
rgalgon over my holiday break. I've been looking over the functional
rgalgon programming aspects of Python and I'm stuck trying to come up with
rgalgon some concise code to find Taxicab numbers
rgalgon (http://mathworld.wolfram.com/ TaxicabNumber.html).

rgalgon Taxicab(n), is defined as the smallest number that can be
rgalgon expressed as a sum of two positive cubes in n distinct ways

rgalgon In Haskell something like this could easily be done with:
rgalgon cube x = x * x * x

rgalgon taxicab n = [(cube a + cube b, (a, b), (c, d))
rgalgon | a - [1..n],
rgalgon b - [(a+1)..n],
rgalgon c - [(a+1)..n],
rgalgon d - [(c+1)..n],
rgalgon (cube a + cube b) == (cube c + cube d)]

rgalgon I'm looking for a succinct way of doing this in Python. I've been
rgalgon toying around with filter(),map(), and reduce() but haven't gotten
rgalgon anything half-way decent yet.

rgalgon So, how would you implement this taxicab(n) function in Python?

To give a fairly literal translation of your Haskell, you could just use
this:

def cube(n): return n ** 3

def taxicab(n):
n += 1
return [(cube(a) + cube(b), (a, b), (c, d))
for a in xrange(1, n)
for b in xrange(a + 1, n)
for c in xrange(a + 1, n)
for d in xrange(c + 1, n)
if cube(a) + cube(b) == cube(c) + cube(d)]

If you print the return value of this you get the same results as your
Haskell examples. I added the following to my Python file:

if __name__ == '__main__':
import sys
print taxicab(int(sys.argv[1]))

Then I see 

$ time taxicab.py 20
[(1729, (1, 12), (9, 10)), (4104, (2, 16), (9, 15))]

real0m0.098s
user0m0.046s
sys 0m0.046s


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


Re: How to generate pdf file from an html page??

2007-12-19 Thread Terry Jones
 Grant == Grant Edwards [EMAIL PROTECTED] writes:
Grant On 2007-12-19, abhishek [EMAIL PROTECTED] wrote:
  Hi everyone, I am trying to generate a PDF printable format file from
  an html page. Is there a way to do this using python. If yes then
  which library and functions are required and if no then reasons why it
  cant be done.
 
 Here's one way:
 
 --html2pdf.py-
 #!/usr/bin/python
 import os,sys
 
 inputFilename,outputFilename = sys.argv[1:3]
 
 os.system(w3m -dump %s | a2ps -B --borders=no | ps2pdf - %s % 
 (inputFilename,outputFilename))

Note that this is highly insecure. outputFilename could be passed e.g., as

  /tmp/file.pdf; rm -fr /home/abhishek

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


Re: Finding overlapping times...

2007-12-13 Thread Terry Jones
Hi Breal

 I have a list that looks like the following
 [(10, 100010), (15, 17), (19, 100015)]
 
 I would like to be able to determine which of these overlap each
 other.  So, in this case, tuple 1 overlaps with tuples 2 and 3.  Tuple
 2 overlaps with 1.  Tuple 3 overlaps with tuple 1.
 
 In my scenario I would have hundreds, if not thousands of these
 ranges.  Any nice pythonic way to do this?

This may be of no help, but

In 1995 I wrote a C library to do some stuff like this. You're welcome to
the code. It might give you some ideas, or you might want to wrap it for
Python. If you did that, and had additional energy, you could release the
result to the Python community.

As someone said, how/what to do depends what you want to do with the
resulting data structure once you've processed the inputs.

In my case I wanted to be able to read in a large number of ranges and be
able to answer questions like is X in the range?. I'm pretty sure I made
it possible to add ranges to ignore (i.e., that punch holes in an existing
range). I'm also pretty sure I'd have made this run in n log n time, by
first sorting all the lower bounds (and maybe sorting the upper ones too)
and then walking that list. 

One use case is e.g., for a printer program command line:

  print --inc-pages 40-70 --exc-pages 51-52 --inc-pages 100-120

which could use the library to step through the range of pages in a doc and
easily check which ones should be printed.  There are lots of other uses.
Lookup time on those queries was probably log n where n is the resulting
number of range fragments once the processing (merging/splitting) of the
command line was done.

I don't remember, but it took me several days to write the code, so it
wasn't completely trivial.

I can't offer help beyond the code I'm afraid - I have too much other stuff
going on.

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


Re: Speed of Nested Functions Lambda Expressions

2007-12-07 Thread Terry Jones
 Duncan == Duncan Booth [EMAIL PROTECTED] writes:
Duncan Terry Jones [EMAIL PROTECTED] wrote:
 Duncan Booth wrote:

Duncan You'll kick yourself for not seeing it.
Duncan If you changed fn_inner to:

Duncan def fn_inner():
Duncan a, v = v, a

Duncan then you also changed 'a' and 'v' into local variables.
Duncan LOAD/STORE_FAST is used to access local variables, LOAD/STORE_DEREF
Duncan are used to access variables in an outer scope.

Argh, yes :-)  [Cue background sound of kicking self]

Thanks.

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


Re: Speed of Nested Functions Lambda Expressions

2007-12-06 Thread Terry Jones
[Referring to the thread at
 http://mail.python.org/pipermail/python-list/2007-October/463348.html
 with apologies for top posting (I don't have the original mail)]

Duncan Booth wrote:

 You can use Python's bytecode disassembler to see what actually gets 
 executed here:
 
  def fn_outer(v):
 a=v*2
 def fn_inner():
 print V:%d,%d % (v,a)
 
 fn_inner()
 
  import dis
  dis.dis(fn_outer)
   2   0 LOAD_DEREF   1 (v)
[snip]


 When you execute the 'def' statement, the two scoped variables a and v 
 are built into a tuple on the stack, the compiled code object for the 
 inner function is also pushed onto the stack and then the function is 
 created by the 'MAKE_CLOSURE' instruction. This is then stored in a 
 local variable (STORE_FAST) which is then loaded and called.
 
 So the function definition is pretty fast, BUT notice how fn_inner is 
 referenced by STORE_FAST/LOAD_FAST whereas a and v are referenced by 
 LOAD_DEREF/STORE_DEREF and LOAD_CLOSURE.
 
 The code for fn_inner also uses LOAD_DEREF to get at the scoped 
 variables:

I'd like to understand what it is that triggers the use of LOAD/STORE_DEREF
versus LOAD/STORE_FAST. This seems dependent on how fn_inner above uses the
a and v variables. If I change the print V:%d,%d % (v,a) line to be
something like (a, v) = (v, a) or do other simple uses and assignments to a
and v, LOAD/STORE_FAST is used. It seems that it's the use of print (in
this case) that triggers the use of LOAD/STORE_DEREF in the bytecode.

Can anyone shed more light on what in general causes the switch to
LOAD/STORE_DEREF?

I find it a bit disconcerting that the simple presence of a nested function
(even if never used) may trigger significant slowdown in variable access
for the rest of the code in the containing function. I'd be happy to know
how/when this happens. I know I probably shouldn't care, but I do.

Thanks,
Terry Jones
-- 
http://mail.python.org/mailman/listinfo/python-list