Re: Sending changed parameters into nested generators

2010-11-18 Thread cbr...@cbrownsystems.com
On Nov 12, 10:52 pm, "John O'Hagan"  wrote:
> On Sat, 13 Nov 2010, Steven D'Aprano wrote:
> > On Fri, 12 Nov 2010 09:47:26 +, John O'Hagan wrote:
> > > I have a generator function which takes as arguments another generator
> > > and a dictionary of other generators like this:
>
> > > def modgen(gen, gendict):
> > > for item in gen():
> > >   for k, v in gendict:
> > >   do_something_called_k(item, v.next())
>
> > >   yield item
>
> > [snip]
>
> > > If anyone's still reading :) , how can I send new values to arbitrary
> > > sub- generators?
>
> > I have a headache after reading your problem :(
>
> > I think it's a good time to point you at the Zen, particularly these five
> > maxims:
>
> > Beautiful is better than ugly.
> > Simple is better than complex.
> > Complex is better than complicated.
> > Flat is better than nested.
> > If the implementation is hard to explain, it's a bad idea.
>
> > I'm afraid that your nested generators inside another generator idea
> > fails all of those... it's not elegant (beautiful), it's complicated,
> > it's nested, and the implementation is hard to explain.
>
> > You could probably replace generators with full-blown iterators, but I
> > wonder what you're trying to accomplish that is so complicated that it
> > needs such complexity to solve it. What are you actually trying to
> > accomplish? Can you give a simple example of what practical task you hope
> > to perform? I suspect there's probably a more elegant way to solve the
> > problem.
>
> I hope there is!
>
> The project not practical but artistic; it's a real-time musical composition
> program.
>
> A (simplified) description: one module contains number-list generating
> functions, others contain functions designed to filter and modify the number
> lists produced, according to various parameters. Each such stream of number
> lists is assigned a musical meaning (e.g. pitch, rhythm, volume, etc) and they
> are combined to produce representations of musical phrases, which are sent to
> a backend which plays the music as it is produced, and makes PDF scores. Each
> such "instrument" runs as a separate thread, so several can play together in a
> coordinated fashion.
>
> All the compositional interest lies in the selection of number-list generators
> and how their output is modified. For example, if I say "Play every third note
> up an octave" it's not very interesting, compared to "Play every nth note up
> an interval of m", where n and m vary according to some pattern. It gets even
> more interesting when that pattern is a function of x and y, which also vary
> according to another pattern, and so on.
>
> To that end, I have each parameter of each modifier set by another generator,
> such that the value may change with each iteration. This may continue
> recursively, until at some level we give a parameter a simple value.
>
> That's all working, but I also want it to be interactive. Each thread opens a
> terminal where new options can be entered, but so far it only works, as I
> mentioned, for changing the values in a top-level mutable object.
>

I might first suggest this, although I have some caveats to add:

def genfilter(evaluator, **param_sources):
while True:
params = {}
for param, gen in param_sources.iteritems():
params[param] = gen.next()
yield evaluator(**params)

You can then do things like:

>>> def concat(in1, in2):
>>> return str(in1)+"|"+str(in2)
>>> a = (i for i in range(1,5))  # generator based on a list
>>> b = (2*i for i in xrange(1,5))   # 'pure' generator
>>> c = genfilter(concat, in1=a, in2=b)
>>> for x in c:
>>> print x
1|2
2|4
3}6
4|8

or, more relevant to your original question regarding modifying things
mid-stream:

>>> class Mult():
>>> def __init__(self, multiplier):
>>> self.mulitplier = multiplier
>>> def multi(self, val):
>>> return val*self.multiplier
>>>
>>> m = Mult(2)
>>> a = (i for i in range(1,10))
>>> b = (i for i in range(1,10))
>>> c = genfilter(m.multi, val=b)
>>> d = genfilter(concat, in1=a, in2=c)
>>> d.next()
1|2
>>> d.next()
2|4
>>> m.multiplier = 3
>>> d.next()
3|9

Obviously more complex and useful examples could be made, but
hopefully you get the idea: don't focus on modifying the generators,
instead modify the action of the functions which take the generators
as inputs.

But a real problem with this whole strategy is that a generator's
next() function is called every time it is evaluated. If the
relationship between your various generators forms a rooted tree,
that's not a problem, but I would think the relationships form a
directed acyclic graph, and in that case, you end up 'double
incrementing' nodes in a way you don't want:

>>> m = Mult(2)
>>> a = (i for i in range(1,10))
>>> b = genfilter(m.multi, val=a)
>>> c = genfilter(concat, in1=a, in2=b)
>>> for x in c:
>>> print x
1|4
3|8
5|12
7|16

And that's not an unnatural situation for your application: you might
have

Re: looping through possible combinations of McNuggets packs of 6, 9 and 20

2010-08-16 Thread cbr...@cbrownsystems.com
On Aug 16, 1:23 am, Roald de Vries  wrote:
> On Aug 15, 2010, at 11:51 PM, Ian Kelly wrote:
>
>
>
> > On Sun, Aug 15, 2010 at 4:36 PM, Baba  wrote:
> >> Hi Mel,
>
> >> indeed i thought of generalising the theorem as follows:
> >> If it is possible to buy n, n+1,…, n+(x-1) sets of McNuggets, for  
> >> some
> >> x, then it is possible to buy any number of McNuggets >= x, given  
> >> that
> >> McNuggets come in x, y and z packs.
>
> >> so with diophantine_nuggets(7,10,21) i would need 7 passes
> >> result:53
>
> >> but with (10,20,30) and 10 passes i get no result
>
> > You're on the right track.  In the case of (10,20,30) there is no
> > largest exactly purchasable quantity.  Any quantity that does not end
> > with a 0 will not be exactly purchasable.
>
> > I suspect that there exists a largest unpurchasable quantity iff at
> > least two of the pack quantities are relatively prime, but I have made
> > no attempt to prove this.
>
> That for sure is not correct; packs of 2, 4 and 7 do have a largest  
> unpurchasable quantity.
>

But 2 is coprime to 7. I think a better counterexample is 6, 10, 15;
no two are coprime, but there is a largest unpurchasable quantity.

> I'm pretty sure that if there's no common divisor for all three (or  
> more) packages (except one), there is a largest unpurchasable  
> quantity. That is: ∀ i>1: ¬(i|a) ∨ ¬(i|b) ∨ ¬(i|c), where ¬(x|
> y) means "x is no divider of y"
>

It's easy to prove that there is a largest unpurchasble quantity iff
gcd(x,y,z) = 1.

First, suppose d = gcd(x, y, z); then for some x', y', z' we have that
x = d*x', y = d*y', z = d*z'; and so for any a, b, c:

a*x + b*y + c*z = a*d*x' + b*d*y' + c*d*z'
= d*(a*x' + b*y' + c*z')

which means that d must always divide the total number of nuggets
purchasable; thus if d >1, there is no largest unpurchasable quantity
(you cannot purchase n*d + 1 nuggets for any n).

To go the other way, if d = 1, then there exists integers (not
neccessarily positive) such that

a*x + b*y + c*z = 1

so therefore

(a*x)*x + (b*x)*y + (c*x)*z = x

Choose A, B, and C to be positive integers with

A + a*x >= 0
B + b*x >= 0
C + c*x >= 0

Then we get a sequence of x consecutive numbers, all purchasable, via

(A + i*a)*x + (B + i*b)*x + (C + i*c)*z
= (Ax + By + Cz) + i*(ax + by cz)
= (Ax + By + Cz) + i

with i in range(x).

The next consecutive number is then achieved via

(Ax + By + Cz) + x = (A+1)x + By + Cz

and so on.

Cheers - Chas

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


Re: looping through possible combinations of McNuggets packs of 6, 9 and 20

2010-08-16 Thread cbr...@cbrownsystems.com
On Aug 16, 11:04 am, Baba  wrote:
> Hi Chas, Roald,
>
> These are all complicated formula that i believe are not expected at
> this level. If you look at the source (see my first submission) you
> will see that this exercise is only the second in a series called
> "Introduction to Programming". Therefore i am convinced that there is
> a much simpler solution.

The question I was responding to (a different one than your original
question) was whether there was a proof of Baba's conjecture that a
largest unobtainable quantity was possible if, and only if, the three
numbers in question had a gcd of 1. Roald had something like a "gut
feeling" that it was true, but such things are generally much more
clear cut than "gut feelings" - they can often easily be /proven/ to
be true or false, given the right mental tools.

In this case, that proof I gave doesn't immediately yield a concrete
answer to your /original/ question - assuming that a largest
obtainable solution is possible, /how/ do we find the largest
unobtainable solution? But it certainly identifies the conditions
whereby we can easily and quickly say that there is no such solution,
or conversely that such a solution must exist; and that is often
extremely helpful to finding an algorithm that /does/ answer your
original question.

(One thing it does provide is an upper bound to the space of solutions
that you should be looking at - and finding upper bounds and lower
bounds is a common programming task. Again, this isn't something that
you might be "expected" to know about at your level of study, but it
doesn't hurt you to be aware of it either :)!)

>
> Now, i believe that the number of consecutive passes required to make
> this work is equal to the smallest number of pack sizes.

That is your belief, your intuition; and developing good intuitions is
good... BUT...

> So if we have
> packs of (9,12,21) the number of passes needed would be 9 and...

... and now whatever you might go on to add is simply "going off into
the weeds", because I have just proven that there can be /no/ such
solution in that case: all three of those numbers are divisible by 3,
so you are not "on the trail" when trying to figure out a general
solution by considering examples of the type you mention.

At your level of study, such things may seem overly complicated (and
are certainly /not/ required to simply answer the question as
originally stated). But consider the thread in this group called
"python interview questions":

http://groups.google.com/group/comp.lang.python/browse_frm/thread/bb4d3514e9842f9e#

The "FizzBuzz" question involves a similar very basic grasp of the
type of mathematical reasoning and thinking that is most valued in
programmers in the job market. Of course, your Python class is not the
right place to be focusing exclusively on this sort of mathematics,
but I would encourage you to simultaneously educate yourself both in
the /language/ learning of Python (which is what your class is largely
about), along with the more universally applicable skill set that
comes from understanding the mathematical justifications of a "good"
algorithm

That additional knowledge will serve you equally well whether you are
programming in Python, Perl, Ruby, Java, C++, D, F, R, and so on
(surely someone will claim "Z" as a language soon, if they haven't
already...).

> ... the
> theorem would read
>
> "If it is possible to buy n,n+1,n+2,...n+8 nuggets it is possible to
> buy any number of nuggets >= 9 given that they come in packs of
> 9,12,21"
>

So I would ask as a simple exercise: how would you go about /proving/
that your assertion is actually a /theorem/, and not just a pretty
solid hunch that your statement is true because for small enough
numbers you can easily "do it in your head"? Yes, it's "clearly true",
but that is not a proof! That is the muscle which is exercised by
mathematical reasoning.

> However i turn in circles because i don't seem to get any results for
> some random pack combinations like (9,12,21) or (10,20,30).
>

Well, your intuitions are certainly close to the mark. But if you
added to your study a course on discrete mathematics, then you would
also immediately see why such turning in circles obviously can bear no
fruit, and that would give you a great advantage in solving far more
difficult and yet common problems of this type.

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


Re: looping through possible combinations of McNuggets packs of 6, 9 and 20

2010-08-18 Thread cbr...@cbrownsystems.com
On Aug 17, 2:44 pm, Baba  wrote:
> On Aug 16, 6:28 pm, "cbr...@cbrownsystems.com"
>
>  wrote:
> > First, suppose d = gcd(x, y, z); then for some x', y', z' we have that
> > x = d*x', y = d*y', z = d*z'; and so for any a, b, c:
>
>    could you explain the notation?
>
>    what is the difference btw x and x' ?
>
>    what is x = d*x', y supposed to say?

x', y', z' are names for three natural numbers; I could have chosen r,
s, t. "x=d*x'" above simply notes that since x is divisible by d, it
can be written as the product of d and some other natural number, and
the same is true for both y and z. therefore sums of multiples of x, y
and z are always divisible by d.

>
> > To go the other way, if d = 1, then there exists integers (not
> > neccessarily positive) such that
>
> > a*x + b*y + c*z = 1
>
>    what's the link with 6*a+9*b+20*c=n except the similarity?
>

The link is that it shows that if we have some u, v, and w with

6*u + 9*v + 20*w = n,

and we can find some a, b, and c which satisfy

6*a + 9*b + 20*c = 1

then if we let r = u + a, s = v + b, and t = w + c, we get that

6*r + 9*s + 20*t = n+1

although r, s, and t are not neccessarily positive numbers (as they
must be to solve your original problem). However, if u, v, and w are
sufficiently large compared to a, b, and c, then r, s and t WILL all
be positive.

But we can only find such an a,b, and c because the gcd of 6, 9, and
20 is equal to 1; that is why you can't solve this problem for nugget
pack sizes 6, 12, and 21.

Note that if there is one solution (a,b,c) to the gcd equation, there
infinitely many tuples (a,b,c) which satisfy the gcd equation, for
example:

6*0+ 9*9+ 20*(-4) = 1
6*(-5) + 9*(-1) + 20*2= 1
6*2+ 9*1+ 20*(-1) = 1

So the proof I gave regarded the /existence/ of a largest
unobtainable, not an algorithm for obtaining one. However from the
last of those three examples, we can see (details are in my original
proof) that the largest unobtainable must be less than

6*0+ 9*0+ 20*(1*5) = 100

so it is potentially helpful for finding an upper bound to the
problem.

> furthermore i came across this:
>
> For k = 3, efficient algorithms
> have been given by Greenberg and Davison ; if x1 < x2 < x3, these
> algorithms run in
> time bounded by a polynomial in log x3. Kannan  gave a very
> complicated algorithm
> that runs in polynomial time in log xk if k is fixed, but is wildly
> exponential in k. However,
> Ram´ırez Alfons´ın proved that the general problem is NP-hard, under
> Turing reductions,
> by reducing from the integer knapsack problem. So it seems very likely
> that there is no
> simple formula for computing g(x1, x2, . . . , xk) for arbitrary k.
>
> source:http://arxiv.org/PS_cache/arxiv/pdf/0708/0708.3224v1.pdf
>
> i would be interested in the answer to problem 3: explain in English
> why the theorem is true
>

I haven't looked at the link; but to be honest it's unlikely you would
understand it if you are having trouble with the much simpler question
regarding solutions in the case of 6, 12, and 21.

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


Re: looping through possible combinations of McNuggets packs of 6, 9 and 20

2010-08-18 Thread cbr...@cbrownsystems.com
On Aug 18, 10:52 am, Baba  wrote:
> Hi Chas
>
> Thanks for that and i agree on your last remark :)
>
> re the number of required consecutive passes required:
>
> The number of required consecutive passes is equal to the smallest
> number because after that you can get any amount of nuggets by just
> adding the smallest nugget pack to some other number.
>
> This is only true if gcd(a,b,c)=1.
>
> Thanks to all for the help in getting to the bottom of the exercise. I
> have truly enjoyed this and most importantly i have learned some new
> things. Hadn't really done any mathematics in a long time and only
> starting programming so this was good to get up to speed.
>
> kind regards to everyone!
> Baba

Happy to be of service!

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


Re: looping through possible combinations of McNuggets packs of 6, 9 and 20

2010-08-18 Thread cbr...@cbrownsystems.com
On Aug 18, 11:50 am, John Posner  wrote:
> On 8/18/2010 1:38 PM, cbr...@cbrownsystems.com wrote:
>
> >>> To go the other way, if d = 1, then there exists integers (not
> >>> neccessarily positive) such that
>
> >>> a*x + b*y + c*z = 1
>
> That fact is non-trivial, although the proof isn't *too* hard [1]. I
> found it interesting to demonstrate the simpler case (a*x + b*y = 1)...

And to get the more general case, if we write (a,b) for gcd of and b,
we can think of the "," as a binary operator that you can show is
associative:

((a,b), c) = (a, (b,c)) = (a, b, c)

and so a proof that exists x,y with a*x + b*y = (a,b) can then be
extended to a proof for an arbitrary number of elements.

(Oddly, "," is also distributive over itself: ((a,b), c) = ((a,c),
(b,c))...)

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


Re: lists and list item matches (ghost wodgame)

2010-09-22 Thread cbr...@cbrownsystems.com
On Sep 22, 3:39 pm, Baba  wrote:
> On Sep 22, 9:18 pm, Baba  wrote:
>
>
>
> > On Sep 22, 3:38 pm, nn  wrote:
>
> > > On Sep 21, 6:39 pm, Baba  wrote:
>
> > > > Hi
>
> > > > query level: beginner
>
> > > > as part of a learning exercise i have written code that:
>



> > wordlist = ['hello', 'bye']
> > hand = ''
> > for item in wordlist:
> >     if item.startswith(hand):
> >         while item.startswith(hand):
> >             if hand not in wordlist:
> >                 hand += raw_input('enter letter: ')
> >                 print hand
> >             else: break
> >         else: break
> > print 'you loose'
>
> > But i can't figure out why it won't work when adding the extra word.
> > Thanks by the way, it taught me not to be too confident when things
> > SEEM to work...
>



> looking at my original code again i realise that having a raw_input
> inside a FOR loop is flawed per se (at least for my purposes) so i
> will just assume that i was taking the wrong approach initially. No
> point in analysing it further. Thanks for your help.
>

Yes, the overall structure using the 'for' loop was a bit awkward, and
your second attempt using 'any' is much clearer; but I'd say it's
still worth seeing how your original logic failed. It has to do with
the action of the 'break's. Ask yourself, which code block does the
'if <> else: break' contained /within/ your while loop, break you out
of? And which code block does the 'while <> else: break' break you out
of?

One other thing... it's 'you LOSE', not 'you LOOSE'! (personal pet
peeve ;-) )

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


Pythonic way of saying 'at least one of a, b, or c is in some_list'

2010-10-28 Thread cbr...@cbrownsystems.com
It's clear but tedious to write:

if 'monday" in days_off or "tuesday" in days_off:
doSomething

I currently am tending to write:

if any([d for d in ['monday', 'tuesday'] if d in days_off]):
doSomething

Is there a better pythonic idiom for this situation?

Cheers - Chas

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


Re: Pythonic way of saying 'at least one of a, b, or c is in some_list'

2010-10-28 Thread cbr...@cbrownsystems.com
On Oct 28, 9:23 am, John Posner  wrote:
> On 10/28/2010 12:16 PM, cbr...@cbrownsystems.com wrote:
>
> > It's clear but tedious to write:
>
> > if 'monday" in days_off or "tuesday" in days_off:
> >      doSomething
>
> > I currently am tending to write:
>
> > if any([d for d in ['monday', 'tuesday'] if d in days_off]):
> >      doSomething
>
> > Is there a better pythonic idiom for this situation?
>
> Clunky, but it might prompt you to think of a better idea: convert the
> lists to sets, and take their intersection.
>
> -John

I thought of that as well, e.g.:

if set(["monday,"tuesday']).intersection(set(days_off)):
doSomething

but those extra recasts to set() make it unaesthetic to me; and worse

if not set(["monday,"tuesday']).isdisjoint(set(days_off)):
doSomething

is bound to confuse most readers.

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


Re: Pythonic way of saying 'at least one of a, b, or c is in some_list'

2010-10-28 Thread cbr...@cbrownsystems.com
On Oct 28, 10:05 am, Chris Rebert  wrote:
> On Thu, Oct 28, 2010 at 9:33 AM, cbr...@cbrownsystems.com
>
>
>
>  wrote:
> > On Oct 28, 9:23 am, John Posner  wrote:
> >> On 10/28/2010 12:16 PM, cbr...@cbrownsystems.com wrote:
>
> >> > It's clear but tedious to write:
>
> >> > if 'monday" in days_off or "tuesday" in days_off:
> >> >      doSomething
>
> >> > I currently am tending to write:
>
> >> > if any([d for d in ['monday', 'tuesday'] if d in days_off]):
> >> >      doSomething
>
> >> > Is there a better pythonic idiom for this situation?
>
> >> Clunky, but it might prompt you to think of a better idea: convert the
> >> lists to sets, and take their intersection.
>
> >> -John
>
> > I thought of that as well, e.g.:
>
> > if set(["monday,"tuesday']).intersection(set(days_off)):
> >    doSomething
>
> > but those extra recasts to set() make it unaesthetic to me; and worse
>
> Why not make days_off a set in the first place? Isn't it,
> conceptually, a set of days off?

That makes sense in my example situation; but often this construct
appears on the fly when the list is a preferred to be a list for other
reasons.

>
> > if not set(["monday,"tuesday']).isdisjoint(set(days_off)):
> >    doSomething
>
> > is bound to confuse most readers.
>
> This way is more straightforward:
>
> if set(["monday", "tuesday"]) & days_off:
>

That's much nicer, even if I have to recast days_off as set(days_off).

Cheers - Chas

> Cheers,
> Chris
> --http://blog.rebertia.com

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


Re: Pythonic way of saying 'at least one of a, b, or c is in some_list'

2010-10-29 Thread cbr...@cbrownsystems.com
On Oct 28, 11:56 am, Arnaud Delobelle  wrote:
> "cbr...@cbrownsystems.com"  writes:
> > It's clear but tedious to write:
>
> > if 'monday" in days_off or "tuesday" in days_off:
> >     doSomething
>
> > I currently am tending to write:
>
> > if any([d for d in ['monday', 'tuesday'] if d in days_off]):
> >     doSomething
>
> > Is there a better pythonic idiom for this situation?
>
> The latter can be written more concisely:
>
>     if any(d in days_off for d in ['monday', 'tuesday']):
>         # do something
>

For the list comprehension approach, I like this much better. In the
situation I am thinking of, it very naturally reads as 'if any of my
days off is monday or tuesday', rather than the logically equivalent,
but somewhat convoluted 'if any of monday or tuesday is one of my days
off'.

I should note that efficiency is not an issue to me here; this is for
when you have, say, a list user_options of at most around 15 options
or so, and you want to perform some action if one or more of a, b, or
c is an option listed in user_options. Big O notation isn't so
relevant as readability and 'naturalness'.

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


Re: Pythonic way of saying 'at least one of a, b, or c is in some_list'

2010-10-29 Thread cbr...@cbrownsystems.com
On Oct 29, 2:43 am, Steven D'Aprano  wrote:
> On Thu, 28 Oct 2010 09:16:42 -0700, cbr...@cbrownsystems.com wrote:
> > It's clear but tedious to write:
>
> > if 'monday" in days_off or "tuesday" in days_off:
> >     doSomething
>
> > I currently am tending to write:
>
> > if any([d for d in ['monday', 'tuesday'] if d in days_off]):
> >     doSomething
>
> Use a simple generator expression and any.
>
> if any(day in days_off for day in ['monday', 'tuesday']):
>     doSomething
>
> You (partially) defeat the short-circuiting behaviour of any() by using a
> list comprehension.
>

Good point, thanks.

> If you have a lot of items to test against, make days_off a set instead
> of a list, which makes each `in` test O(1) instead of O(N). For small N,
> the overhead of creating the set is probably going to be bigger than the
> saving, so stick to a list.
>
> Other than that, doing set operations is overkill -- it obfuscates the
> intention of the code for very little gain, and possibly negative gain.
> And as for the suggestion that you create a helper class to do the work,
> that's surely the recommended way to do it in Java rather than Python.
>

Agreed. In the situation I am thinking of, N is generally very small,
and readability trumps execution speed.

Cheers - Chas


> --
> Steven

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


Re: text file reformatting

2010-10-31 Thread cbr...@cbrownsystems.com
On Oct 31, 12:48 pm, Tim Chase  wrote:
> > PRJ01001 4 00100END
> > PRJ01002 3 00110END
>
> > I would like to pick only some columns to a new file and put them to a
> > certain places (to match previous data) - definition file (def.csv)
> > could be something like this:
>
> > VARIABLE   FIELDSTARTS     FIELD SIZE      NEW PLACE IN NEW DATA FILE
> > ProjID     ;       1       ;       5       ;       1
> > CaseID     ;       6       ;       3       ;       10
> > UselessV  ;        10      ;       1       ;
> > Zipcode    ;       12      ;       5       ;       15
>
> > So the new datafile should look like this:
>
> > PRJ01    001       00100END
> > PRJ01    002       00110END
>
> How flexible is the def.csv format?  The difficulty I see with
> your def.csv format is that it leaves undefined gaps (presumably
> to be filled in with spaces) and that you also have a blank "new
> place in new file" value.  If instead, you could specify the
> width to which you want to pad it and omit variables you don't
> want in the output, ordering the variables in the same order you
> want them in the output:
>
>   Variable; Start; Size; Width
>   ProjID; 1; 5; 10
>   CaseID; 6; 3; 10
>   Zipcode; 12; 5; 5
>   End; 16; 3; 3
>
> (note that I lazily use the same method to copy the END from the
> source to the destination, rather than coding specially for it)
> you could do something like this (untested)
>
>    import csv
>    f = file('def.csv', 'rb')
>    f.next() # discard the header row
>    r = csv.reader(f, delimiter=';')
>    fields = [
>      (varname, slice(int(start), int(start)+int(size)), width)
>      for varname, start, size, width
>      in r
>      ]
>    f.close()
>    out = file('out.txt', 'w')
>    try:
>      for row in file('data.txt'):
>        for varname, slc, width in fields:
>          out.write(row[slc].ljust(width))
>        out.write('\n')
>    finally:
>      out.close()
>
> Hope that's fairly easy to follow and makes sense.  There might
> be some fence-posting errors (particularly your use of "1" as the
> initial offset, while python uses "0" as the initial offset for
> strings)
>
> If you can't modify the def.csv format, then things are a bit
> more complex and I'd almost be tempted to write a script to try
> and convert your existing def.csv format into something simpler
> to process like what I describe.
>
> -tkc

To your point about the non-stand csv encoding in the defs.csv file,
you could use a reg exp instead of the csv module to solve that:

import re

parse_columns = re.compile(r'\s*;\s*')

f = file('defs.csv', 'rb')
f.readline() # discard the header row
r = (parse_columns.split(line.strip()) for line in f)
fields = [
 (varname, slice(int(start), int(start)+int(size), int(width) if
width else 0))
for varname, start, size, width in r
 ]
f.close()

which given the OP's csv produces for fields:

[('ProjID', slice(1, 6, 1)), ('CaseID', slice(6, 9, 10)), ('UselessV',
slice(10, 11, 0)), ('Zipcode', slice(12, 17, 15))]

and that should work with the remainder of your original code;
although perhaps the OP wants something else to happen when width is
omitted from the csv...

Cheers - Chas

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


Re: Pythonic way of saying 'at least one of a, b, or c is in some_list'

2010-10-31 Thread cbr...@cbrownsystems.com
On Oct 31, 4:27 pm, Lawrence D'Oliveiro  wrote:
> In message
> <687bcb76-0093-4d68-ba56-0390a3e1e...@30g2000yql.googlegroups.com>,
>
> cbr...@cbrownsystems.com wrote:
> > I should note that efficiency is not an issue to me here; this is for
> > when you have, say, a list user_options of at most around 15 options
> > or so, and you want to perform some action if one or more of a, b, or
> > c is an option listed in user_options. Big O notation isn't so
> > relevant as readability and 'naturalness'.
>
> I must say this whole thread has turned into a massive bikeshedding
> exercise.

Agreed that, to paraphrase RWE, a foolish insistence on big O
valuation is the hobgoblin of etc. On the other hand, I got a
reasonable answer to my question:

if any(option in ['optionA', 'optionB', 'optionC']
for option in supplied_options):
first_do_something_those_options_all_require()
if 'optionA' in supplied_options:
do_optionA_specific_stuff()


which is quite readable and flexible as an idiom, and so I am
satisfied overall.

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


Re: text file reformatting

2010-11-01 Thread cbr...@cbrownsystems.com
On Oct 31, 11:46 pm, iwawi  wrote:
> On 31 loka, 21:48, Tim Chase  wrote:
>
>
>
> > > PRJ01001 4 00100END
> > > PRJ01002 3 00110END
>
> > > I would like to pick only some columns to a new file and put them to a
> > > certain places (to match previous data) - definition file (def.csv)
> > > could be something like this:
>
> > > VARIABLE   FIELDSTARTS     FIELD SIZE      NEW PLACE IN NEW DATA FILE
> > > ProjID     ;       1       ;       5       ;       1
> > > CaseID     ;       6       ;       3       ;       10
> > > UselessV  ;        10      ;       1       ;
> > > Zipcode    ;       12      ;       5       ;       15
>
> > > So the new datafile should look like this:
>
> > > PRJ01    001       00100END
> > > PRJ01    002       00110END
>
> > How flexible is the def.csv format?  The difficulty I see with
> > your def.csv format is that it leaves undefined gaps (presumably
> > to be filled in with spaces) and that you also have a blank "new
> > place in new file" value.  If instead, you could specify the
> > width to which you want to pad it and omit variables you don't
> > want in the output, ordering the variables in the same order you
> > want them in the output:
>
> >   Variable; Start; Size; Width
> >   ProjID; 1; 5; 10
> >   CaseID; 6; 3; 10
> >   Zipcode; 12; 5; 5
> >   End; 16; 3; 3
>
> > (note that I lazily use the same method to copy the END from the
> > source to the destination, rather than coding specially for it)
> > you could do something like this (untested)
>
> >    import csv
> >    f = file('def.csv', 'rb')
> >    f.next() # discard the header row
> >    r = csv.reader(f, delimiter=';')
> >    fields = [
> >      (varname, slice(int(start), int(start)+int(size)), width)
> >      for varname, start, size, width
> >      in r
> >      ]
> >    f.close()
> >    out = file('out.txt', 'w')
> >    try:
> >      for row in file('data.txt'):
> >        for varname, slc, width in fields:
> >          out.write(row[slc].ljust(width))
> >        out.write('\n')
> >    finally:
> >      out.close()
>
> > Hope that's fairly easy to follow and makes sense.  There might
> > be some fence-posting errors (particularly your use of "1" as the
> > initial offset, while python uses "0" as the initial offset for
> > strings)
>
> > If you can't modify the def.csv format, then things are a bit
> > more complex and I'd almost be tempted to write a script to try
> > and convert your existing def.csv format into something simpler
> > to process like what I describe.
>
> > -tkc- Piilota siteerattu teksti -
>
> > - Näytä siteerattu teksti -
>
> Hi,
>
> Thanks for your reply.
>
> Def.csv could be modified so that every line has the same structure:
> variable name, field start, field size and new place and would be
> separated with semicolomns as you mentioned.
>
> I tried your script (which seems quite logical) but I get this
>
> Traceback (most recent call last):
>   File "testing.py", line 16, in 
>     out.write (row[slc].ljust(width))
> TypeError: an integer is required
>
> Yes - you said it was untested, but I can't figure out how to
> proceed...

The line

(varname, slice(int(start), int(start)+int(size)), width)

should instead be

(varname, slice(int(start), int(start)+int(size)), int(width))

although you give an example where there is no width - what does that
imply? In the above case, it will throw an exception.

Anyway, I think you'll find there's something a bit off in the output
loop with the parameter passed to ljust() as well. The value given in
your csv seems to be the absolute position, but as it's implemented by
Tim, it acts as the relative position.

Given Tim's parsing into the list fields, I have a feeling that what
you really want instead of

for varname, slc, width in fields:
out.write(row[slc].ljust(width))
out.write('\n')

is to have

s = ''
for varname, slc, width in fields:
s += " "*(width - len(s)) + row[slc]
out.write(s+'\n')

And if that is what you want, then you will surely want to globally
replace the name 'width' with for example 'start_column', because then
it all makes sense :).

Cheers - Chas

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


Re: text file reformatting

2010-11-01 Thread cbr...@cbrownsystems.com
On Nov 1, 1:58 am, iwawi  wrote:
> On 1 marras, 09:59, "cbr...@cbrownsystems.com"
>
>
>
>  wrote:
> > On Oct 31, 11:46 pm, iwawi  wrote:
>
> > > On 31 loka, 21:48, Tim Chase  wrote:
>
> > > > > PRJ01001 4 00100END
> > > > > PRJ01002 3 00110END
>
> > > > > I would like to pick only some columns to a new file and put them to a
> > > > > certain places (to match previous data) - definition file (def.csv)
> > > > > could be something like this:
>
> > > > > VARIABLE   FIELDSTARTS     FIELD SIZE      NEW PLACE IN NEW DATA FILE
> > > > > ProjID     ;       1       ;       5       ;       1
> > > > > CaseID     ;       6       ;       3       ;       10
> > > > > UselessV  ;        10      ;       1       ;
> > > > > Zipcode    ;       12      ;       5       ;       15
>
> > > > > So the new datafile should look like this:
>
> > > > > PRJ01    001       00100END
> > > > > PRJ01    002       00110END
>
> > > > How flexible is the def.csv format?  The difficulty I see with
> > > > your def.csv format is that it leaves undefined gaps (presumably
> > > > to be filled in with spaces) and that you also have a blank "new
> > > > place in new file" value.  If instead, you could specify the
> > > > width to which you want to pad it and omit variables you don't
> > > > want in the output, ordering the variables in the same order you
> > > > want them in the output:
>
> > > >   Variable; Start; Size; Width
> > > >   ProjID; 1; 5; 10
> > > >   CaseID; 6; 3; 10
> > > >   Zipcode; 12; 5; 5
> > > >   End; 16; 3; 3
>
> > > > (note that I lazily use the same method to copy the END from the
> > > > source to the destination, rather than coding specially for it)
> > > > you could do something like this (untested)
>
> > > >    import csv
> > > >    f = file('def.csv', 'rb')
> > > >    f.next() # discard the header row
> > > >    r = csv.reader(f, delimiter=';')
> > > >    fields = [
> > > >      (varname, slice(int(start), int(start)+int(size)), width)
> > > >      for varname, start, size, width
> > > >      in r
> > > >      ]
> > > >    f.close()
> > > >    out = file('out.txt', 'w')
> > > >    try:
> > > >      for row in file('data.txt'):
> > > >        for varname, slc, width in fields:
> > > >          out.write(row[slc].ljust(width))
> > > >        out.write('\n')
> > > >    finally:
> > > >      out.close()
>
> > > > Hope that's fairly easy to follow and makes sense.  There might
> > > > be some fence-posting errors (particularly your use of "1" as the
> > > > initial offset, while python uses "0" as the initial offset for
> > > > strings)
>
> > > > If you can't modify the def.csv format, then things are a bit
> > > > more complex and I'd almost be tempted to write a script to try
> > > > and convert your existing def.csv format into something simpler
> > > > to process like what I describe.
>
> > > > -tkc- Piilota siteerattu teksti -
>
> > > > - Näytä siteerattu teksti -
>
> > > Hi,
>
> > > Thanks for your reply.
>
> > > Def.csv could be modified so that every line has the same structure:
> > > variable name, field start, field size and new place and would be
> > > separated with semicolomns as you mentioned.
>
> > > I tried your script (which seems quite logical) but I get this
>
> > > Traceback (most recent call last):
> > >   File "testing.py", line 16, in 
> > >     out.write (row[slc].ljust(width))
> > > TypeError: an integer is required
>
> > > Yes - you said it was untested, but I can't figure out how to
> > > proceed...
>
> > The line
>
> >     (varname, slice(int(start), int(start)+int(size)), width)
>
> > should instead be
>
> >     (varname, slice(int(start), int(start)+int(size)), int(width))
>
> > although you give an example where there is no width - what does that
> > imply? In the above case, it will throw an exception.
>
> > Anyway, I think you'll find there's something a bit off in the output
> >

Re: multiple discontinued ranges

2010-11-11 Thread cbr...@cbrownsystems.com
On Nov 10, 10:02 am, Mel  wrote:
> xoff wrote:
> > I was wondering what the best method was in Python programming for 2
> > discontinued ranges. e.g. I want to use the range 3 to 7 and 17 to 23.
> > Am I obliged to use 2 for loops defining the 2 ranges like this:
>
> > for i in range (3,7):
> >  do bla
> > for i in range (7,17):
> >  do bla
>
> > or is there a more clever way to do this?
>
> One horribly clever way is to concoct a 9-th order polynomial to return
> 3,4,5,6,17,18,19,20,21,22 for input values 0,1,2,3,4,5,6,7,8,9.
>

And one would want one with integer coefficients... truly horribly
clever! A good example of complex is better than complicated...

> The reasonable way is to use two loops as you've done.  If the pattern of
> discontinuous ranges is really important in your application, you'd perhaps
> want to package it up (not tested):
>
> def important_range ():
> for x in xrange (3, 7):
> yield x
> for x in xrange (17,23):
> yield x
>

Reasonable; but DRY: don't repeat yourself. IMNSHO, better would be:

... def important_range ():
... for x in [xrange (3, 7), xrange (17,23)]:
... for y in x:
... yield y

because face it, you're probably going to add to that list of ranges
anyway, so you should anticipate it (and there's no cost if you don't
end up adding to it).

To extend that notion, I would imagine that itertools.chain is already
basically defined as:

... def chain(*args):
... for x in args:
... for y in x:
... yield y

so important_range() can then be simply defined as:

... def important_range:
... return chain(xrange (3, 7), xrange (17,23))

Cheers - Chas

> to be used elsewhere as
>
> for v in important_range():
> # use v ...
>

> Mel.

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


Re: IDLE debugger questions

2010-11-13 Thread cbr...@cbrownsystems.com
On Oct 23, 7:29 am, Roger Davis  wrote:



> Are there any Python debuggers with a decent GUI out there at all that
> will work on a Mac with the following features: (i) ability to pass in
> a sys.srgv[] list that the program would otherwise see without the
> debugger, (ii) display local variables, (iii) single-step through the
> source code, and (iv) set a breakpoint? I think I can live without
> anything else for the moment.
>

I'm very happy using the Eclipse IDE (available for Mac, PC and 'Nix)
with the pydev plug-in. It's free, well supported and well behaved,
and has all the debugging features you name and then some. It's also a
modern code editor with code-hinting, syntax highlighting, etc.

The only downside of Eclipse to me is its 'workspace' and 'project'
metaphors for file organization; which take a bit of getting used to,
particularly if you're used to just editing in a text editor, and then
running in Idle or a command line.

I still usually also have Idle open as well so I can test little code
snippets quickly and easily; but mostly I work in Eclipse.

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