Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #69432 > unrolled thread
| Started by | Chris Angelico <rosuav@gmail.com> |
|---|---|
| First post | 2014-04-01 01:33 +1100 |
| Last post | 2014-04-01 02:55 -0600 |
| Articles | 20 on this page of 37 — 11 participants |
Back to article view | Back to comp.lang.python
Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 01:33 +1100
Re: Code style query: multiple assignments in if/elif tree Marko Rauhamaa <marko@pacujo.net> - 2014-03-31 18:40 +0300
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 03:03 +1100
Re: Code style query: multiple assignments in if/elif tree Rustom Mody <rustompmody@gmail.com> - 2014-03-31 09:20 -0700
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 03:29 +1100
Re: Code style query: multiple assignments in if/elif tree "Rhodri James" <rhodri@wildebst.org.uk> - 2014-03-31 21:31 +0100
Re: Code style query: multiple assignments in if/elif tree Ned Batchelder <ned@nedbatchelder.com> - 2014-03-31 17:42 -0400
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 09:50 +1100
Re: Code style query: multiple assignments in if/elif tree Ben Finney <ben+python@benfinney.id.au> - 2014-04-01 09:57 +1100
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 10:12 +1100
Re: Code style query: multiple assignments in if/elif tree Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-04-01 00:57 +0000
Re: Code style query: multiple assignments in if/elif tree Ethan Furman <ethan@stoneleaf.us> - 2014-03-31 17:30 -0700
Re: Code style query: multiple assignments in if/elif tree Steven D'Aprano <steve@pearwood.info> - 2014-04-01 04:26 +0000
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 16:01 +1100
Re: Code style query: multiple assignments in if/elif tree Steven D'Aprano <steve@pearwood.info> - 2014-04-01 07:20 +0000
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 18:35 +1100
Re: Code style query: multiple assignments in if/elif tree Steven D'Aprano <steve@pearwood.info> - 2014-04-01 08:07 +0000
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 19:12 +1100
Re: Code style query: multiple assignments in if/elif tree Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-01 02:18 -0600
Re: Code style query: multiple assignments in if/elif tree Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-01 02:24 -0600
Re: Code style query: multiple assignments in if/elif tree Rustom Mody <rustompmody@gmail.com> - 2014-03-31 22:45 -0700
Re: Code style query: multiple assignments in if/elif tree David Hutto <dwightdhutto@gmail.com> - 2014-04-01 02:05 -0400
Re: Code style query: multiple assignments in if/elif tree Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-01 00:28 -0600
Re: Code style query: multiple assignments in if/elif tree Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-01 00:13 -0600
Re: Code style query: multiple assignments in if/elif tree David Hutto <dwightdhutto@gmail.com> - 2014-04-01 02:24 -0400
Re: Code style query: multiple assignments in if/elif tree Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-01 00:39 -0600
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 17:55 +1100
Re: Code style query: multiple assignments in if/elif tree Steven D'Aprano <steve@pearwood.info> - 2014-04-01 07:29 +0000
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 18:49 +1100
Re: Code style query: multiple assignments in if/elif tree Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-01 02:29 -0600
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 19:56 +1100
Re: Code style query: multiple assignments in if/elif tree David Hutto <dwightdhutto@gmail.com> - 2014-04-01 03:21 -0400
Re: Code style query: multiple assignments in if/elif tree Chris Angelico <rosuav@gmail.com> - 2014-04-01 18:26 +1100
Re: Code style query: multiple assignments in if/elif tree David Hutto <dwightdhutto@gmail.com> - 2014-04-01 03:34 -0400
Re: Code style query: multiple assignments in if/elif tree David Hutto <dwightdhutto@gmail.com> - 2014-04-01 03:39 -0400
Re: Code style query: multiple assignments in if/elif tree David Hutto <dwightdhutto@gmail.com> - 2014-04-01 03:46 -0400
Re: Code style query: multiple assignments in if/elif tree Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-01 02:55 -0600
Page 1 of 2 [1] 2 Next page →
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-01 01:33 +1100 |
| Subject | Code style query: multiple assignments in if/elif tree |
| Message-ID | <mailman.8744.1396276875.18130.python-list@python.org> |
Call this a code review request, if you like. I'm wondering how you'd go about coding something like this. Imagine you're in a train, and the brakes don't apply instantly. The definition, in the interests of passenger comfort, is that the first second of brake application has an acceleration of 0.2 m/s/s, the next second has 0.425 m/s/s, and thereafter full effect of 0.85 m/s/s. You have a state variable that says whether the brakes have just been applied, have already been applied for at least two seconds, or haven't yet been applied at all. Problem: Work out how far you'll go before the brakes reach full power, and how fast you'll be going at that point. Here's how I currently have the code. The variable names are a tad long, as this was also part of me teaching my brother Python. # Already got the brakes fully on if mode=="Brake2": distance_to_full_braking_power, speed_full_brake = 0.0, curspeed # The brakes went on one second ago, they're nearly full elif mode=="Brake1": distance_to_full_braking_power, speed_full_brake = curspeed - 0.2125, curspeed - 0.425 # Brakes aren't on. else: distance_to_full_braking_power, speed_full_brake = (curspeed - 0.1) + (curspeed - 0.4125), curspeed - 0.625 # If we hit the brakes now (or already have hit them), we'll go another d meters and be going at s m/s before reaching full braking power. But I don't like the layout. I could change it to a single assignment with expression-if, but that feels awkward too. How would you lay this out? (Note that the "else" case could have any of several modes in it, so I can't so easily use a dict.) ChrisA
[toc] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2014-03-31 18:40 +0300 |
| Message-ID | <874n2ecr5x.fsf@elektro.pacujo.net> |
| In reply to | #69432 |
Chris Angelico <rosuav@gmail.com>:
> Call this a code review request, if you like. I'm wondering how you'd
> go about coding something like this.
As a simple layout question, I'd do it like this:
========================================================================
if mode == "Brake2":
# Already got the brakes fully on
distance_to_full_braking_power = 0.0
speed_full_brake = curspeed
elif mode == "Brake1":
# The brakes went on one second ago, they're nearly full
distance_to_full_braking_power = curspeed - 0.2125
speed_full_brake = curspeed - 0.425
else:
# Brakes aren't on.
distance_to_full_braking_power = (curspeed - 0.1) + (curspeed - 0.4125)
speed_full_brake = curspeed - 0.625
# If we hit the brakes now (or already have hit them), we'll go another
# d meters and be going at s m/s before reaching full braking power.
========================================================================
Marko
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-01 03:03 +1100 |
| Message-ID | <mailman.8745.1396281843.18130.python-list@python.org> |
| In reply to | #69433 |
On Tue, Apr 1, 2014 at 2:40 AM, Marko Rauhamaa <marko@pacujo.net> wrote: > As a simple layout question, I'd do it like this: > > ======================================================================== > if mode == "Brake2": > # Already got the brakes fully on > distance_to_full_braking_power = 0.0 > speed_full_brake = curspeed > elif mode == "Brake1": > # The brakes went on one second ago, they're nearly full > distance_to_full_braking_power = curspeed - 0.2125 > speed_full_brake = curspeed - 0.425 > else: > # Brakes aren't on. > distance_to_full_braking_power = (curspeed - 0.1) + (curspeed - 0.4125) > speed_full_brake = curspeed - 0.625 > > # If we hit the brakes now (or already have hit them), we'll go another > # d meters and be going at s m/s before reaching full braking power. > ======================================================================== No particular advantage over the current version - it doesn't simplify it any, all you've done is break it across more lines. (The unpacking may not be ideal; as I said, this was a vehicle for teaching oddments of Python, so I used multiple assignment partly for the sake of using it.) Incidentally, if you want to see the code in context, it's here: https://github.com/Rosuav/runningtime/blob/master/runningtime.py ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-03-31 09:20 -0700 |
| Message-ID | <6775d115-a592-4082-a427-5789e1dd2875@googlegroups.com> |
| In reply to | #69434 |
On Monday, March 31, 2014 9:33:54 PM UTC+5:30, Chris Angelico wrote: > On Tue, Apr 1, 2014 at 2:40 AM, Marko Rauhamaa wrote: > > As a simple layout question, I'd do it like this: > > ======================================================================== > > if mode == "Brake2": > > # Already got the brakes fully on > > distance_to_full_braking_power = 0.0 > > speed_full_brake = curspeed > > elif mode == "Brake1": > > # The brakes went on one second ago, they're nearly full > > distance_to_full_braking_power = curspeed - 0.2125 > > speed_full_brake = curspeed - 0.425 > > else: > > # Brakes aren't on. > > distance_to_full_braking_power = (curspeed - 0.1) + (curspeed - 0.4125) > > speed_full_brake = curspeed - 0.625 > > # If we hit the brakes now (or already have hit them), we'll go another > > # d meters and be going at s m/s before reaching full braking power. > > ======================================================================== > No particular advantage over the current version - it doesn't simplify > it any, all you've done is break it across more lines. Not answering your original question but the above comment Your version was sufficiently garbled indentation-wise (it may give you sweet pleasure to know my 'client' is GG) that I gave up on reading it. Marko's version was clear enough that it seems to match your spec [Ive not really verified it word for word... Just sayin'] On the whole I prefer multiple assignments. Maybe in this case use small variable names with separate(d) explanatory comments??
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-01 03:29 +1100 |
| Message-ID | <mailman.8746.1396283403.18130.python-list@python.org> |
| In reply to | #69435 |
On Tue, Apr 1, 2014 at 3:20 AM, Rustom Mody <rustompmody@gmail.com> wrote: > On the whole I prefer multiple assignments. > Maybe in this case use small variable names with > separate(d) explanatory comments?? Shorter variable names would certainly be the more normal, heh. I let my brother do that part of the typing, picking names and so on. Better for teaching to let the victi-- err, the student have the power to choose. :) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | "Rhodri James" <rhodri@wildebst.org.uk> |
|---|---|
| Date | 2014-03-31 21:31 +0100 |
| Message-ID | <op.xdlsnlqv5079vu@gnudebeest> |
| In reply to | #69436 |
On Mon, 31 Mar 2014 17:29:54 +0100, Chris Angelico <rosuav@gmail.com> wrote: > On Tue, Apr 1, 2014 at 3:20 AM, Rustom Mody <rustompmody@gmail.com> > wrote: >> On the whole I prefer multiple assignments. >> Maybe in this case use small variable names with >> separate(d) explanatory comments?? > > Shorter variable names would certainly be the more normal, heh. I let > my brother do that part of the typing, picking names and so on. Better > for teaching to let the victi-- err, the student have the power to > choose. :) Not just more normal, but more readable too. The trouble with your original example was that the lines were too long (even ignoring the trouble line-wrapping caused in your post) to take in with only a couple of eye movements along the line. That makes a really quite surprising difference to the comprehensibility of the whole thing. -- Rhodri James *-* Wildebeest Herder to the Masses
[toc] | [prev] | [next] | [standalone]
| From | Ned Batchelder <ned@nedbatchelder.com> |
|---|---|
| Date | 2014-03-31 17:42 -0400 |
| Message-ID | <mailman.8755.1396302172.18130.python-list@python.org> |
| In reply to | #69433 |
On 3/31/14 12:03 PM, Chris Angelico wrote: > Incidentally, if you want to see the code in context, it's here: > > https://github.com/Rosuav/runningtime/blob/master/runningtime.py > > ChrisA I know you didn't ask about these aspects, but they jumped out at me: tabs for indentation instead of spaces, and docstring-style comments in places that aren't docstrings. These seem like unusual choices. -- Ned Batchelder, http://nedbatchelder.com
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-01 09:50 +1100 |
| Message-ID | <mailman.8757.1396306245.18130.python-list@python.org> |
| In reply to | #69433 |
On Tue, Apr 1, 2014 at 8:42 AM, Ned Batchelder <ned@nedbatchelder.com> wrote: > On 3/31/14 12:03 PM, Chris Angelico wrote: >> >> Incidentally, if you want to see the code in context, it's here: >> >> https://github.com/Rosuav/runningtime/blob/master/runningtime.py >> >> ChrisA > > > I know you didn't ask about these aspects, but they jumped out at me: tabs > for indentation instead of spaces, and docstring-style comments in places > that aren't docstrings. These seem like unusual choices. Tabs instead of spaces? They're plenty common enough, but I am *not* getting into that debate now. The file's perfectly consistent - aside from inside strings, all indentation is done with tabs, one per level. How do you go about doing multi-line comments? I know I've seen other code using triple-quoted strings for long comments before. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2014-04-01 09:57 +1100 |
| Message-ID | <mailman.8758.1396306668.18130.python-list@python.org> |
| In reply to | #69433 |
Chris Angelico <rosuav@gmail.com> writes:
> How do you go about doing multi-line comments? I know I've seen other
> code using triple-quoted strings for long comments before.
Just use a sequence of one-line comments::
# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut a
# sapien tempor, suscipit orci sed, elementum nisl. Suspendisse at
# lacus ut diam dignissim lobortis ac vitae augue.
#
# Phasellus bibendum neque a justo vulputate, quis accumsan quam
# egestas. Etiam aliquet blandit ante sit amet cursus.
A decent code editor (e.g. Emacs, Vim) will allow manipulation of
a sequence of one-line comments in Python's comment style, and allow
treating it as a paragraphs for purposes such as re-wrapping the lines.
I agree with others that triple-quoted strings are best reserved for
string literals (including docstrings), not comments.
--
\ “Alternative explanations are always welcome in science, if |
`\ they are better and explain more. Alternative explanations that |
_o__) explain nothing are not welcome.” —Victor J. Stenger, 2001-11-05 |
Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-01 10:12 +1100 |
| Message-ID | <mailman.8759.1396307562.18130.python-list@python.org> |
| In reply to | #69433 |
On Tue, Apr 1, 2014 at 9:57 AM, Ben Finney <ben+python@benfinney.id.au> wrote: > Chris Angelico <rosuav@gmail.com> writes: > >> How do you go about doing multi-line comments? I know I've seen other >> code using triple-quoted strings for long comments before. > > Just use a sequence of one-line comments:: > > # Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut a > # sapien tempor, suscipit orci sed, elementum nisl. Suspendisse at > # lacus ut diam dignissim lobortis ac vitae augue. > # > # Phasellus bibendum neque a justo vulputate, quis accumsan quam > # egestas. Etiam aliquet blandit ante sit amet cursus. > > A decent code editor (e.g. Emacs, Vim) will allow manipulation of > a sequence of one-line comments in Python's comment style, and allow > treating it as a paragraphs for purposes such as re-wrapping the lines. > > I agree with others that triple-quoted strings are best reserved for > string literals (including docstrings), not comments. Fair enough. I can't remember where (or when!) it was that I learned triple-quoted strings were appropriately abused as comments, so I've just done a quick re-layout into hash comments. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-04-01 00:57 +0000 |
| Message-ID | <533a0edd$0$29994$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #69454 |
On Tue, 01 Apr 2014 10:12:38 +1100, Chris Angelico wrote:
[...]
>> I agree with others that triple-quoted strings are best reserved for
>> string literals (including docstrings), not comments.
>
> Fair enough. I can't remember where (or when!) it was that I learned
> triple-quoted strings were appropriately abused as comments, so I've
> just done a quick re-layout into hash comments.
Probably here :-)
But note the emphasis on "abused". The only time I would use triple-
quoted strings as comments is if I wanted to quickly comment out a
section of code:
do_this()
do_that()
'''
def do_something_else():
"""Docstring"""
pass
do_something_else()
'''
do_more()
do_less()
sort of thing. (Note the cunning use of ''' instead of """.) But I
wouldn't leave it like that in production code.
It's *tempting* to use """ to mark out a large block of text, and I
wouldn't say that doing so was wrong, but it's a bit different, and
programmers are very like cats: they don't like different.
--
Steven D'Aprano
http://import-that.dreamwidth.org/
[toc] | [prev] | [next] | [standalone]
| From | Ethan Furman <ethan@stoneleaf.us> |
|---|---|
| Date | 2014-03-31 17:30 -0700 |
| Message-ID | <mailman.8763.1396313500.18130.python-list@python.org> |
| In reply to | #69433 |
On 03/31/2014 04:12 PM, Chris Angelico wrote: > On Tue, Apr 1, 2014 at 9:57 AM, Ben Finney <ben+python@benfinney.id.au> wrote: >> Chris Angelico <rosuav@gmail.com> writes: >> >>> How do you go about doing multi-line comments? I know I've seen other >>> code using triple-quoted strings for long comments before. >> >> Just use a sequence of one-line comments:: >> >> # Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut a >> # sapien tempor, suscipit orci sed, elementum nisl. Suspendisse at >> # lacus ut diam dignissim lobortis ac vitae augue. >> # >> # Phasellus bibendum neque a justo vulputate, quis accumsan quam >> # egestas. Etiam aliquet blandit ante sit amet cursus. >> >> A decent code editor (e.g. Emacs, Vim) will allow manipulation of >> a sequence of one-line comments in Python's comment style, and allow >> treating it as a paragraphs for purposes such as re-wrapping the lines. >> >> I agree with others that triple-quoted strings are best reserved for >> string literals (including docstrings), not comments. > > Fair enough. I can't remember where (or when!) it was that I learned > triple-quoted strings were appropriately abused as comments, so I've > just done a quick re-layout into hash comments. Personally, I use the sequence of one-line comments. But, hey, Guido [1] himself likes the triple-quoted string as comment feature [2], so feel free to use it yourself if you like. -- ~Ethan~ [1] https://mail.python.org/pipermail/python-dev/2013-March/124947.html [2] https://mail.python.org/pipermail/python-ideas/2009-October/006204.html
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2014-04-01 04:26 +0000 |
| Message-ID | <533a3fd8$0$2909$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #69432 |
On Tue, 01 Apr 2014 01:33:09 +1100, Chris Angelico wrote:
> Call this a code review request, if you like. I'm wondering how you'd go
> about coding something like this.
I wouldn't. I'd start off by analysing the problem, and putting it into
the simplest format possible, and *then* start writing code if and only
if needed. See below.
The first mistake of computational mathematics is to do the computation
before the mathematics, and the Holy Grail is to avoid the computation
altogether.
> Imagine you're in a train, and the brakes don't apply instantly. The
> definition, in the interests of passenger comfort,
Ah, you're using comfort in the modern sense, i.e. what people used to
call discomfort :-P
The scenario you describe has (effectively) infinite rate-of-change-of-
acceleration, often called "jerk". (A jerk is a rapid change in
acceleration.) Human comfort is (within reasonable limits) more affected
by jerk than acceleration. The passengers will feel three quite
distinctive jerks, one when the brakes are first applied (which is
probably reasonable), then one at 1s, then again at 2s. That's not
comfortable by any stretch of the imagination.
> is that the first
> second of brake application has an acceleration of 0.2 m/s/s, the next
> second has 0.425 m/s/s, and thereafter full effect of 0.85 m/s/s.
In mathematics, this is called hybrid function, and is usually written
like this:
g(t) for t < 0
f(t) = { 42 for t == 0
h(t) for t > 0
or something similar. (The opening brace { ought to be large enough to
cover all three lines, and there is no closing brace.)
In your case, you have three constant functions.
> You
> have a state variable that says whether the brakes have just been
> applied, have already been applied for at least two seconds, or haven't
> yet been applied at all.
I wouldn't model it that way. Especially since you've missed at least one
state :-) I'd model the acceleration as a function of time, otherwise you
have to convert a time into a state. Nevertheless, if you insist, we can
use a state variable instead:
0 for state == "BRAKES NOT APPLIED YET"
accel = { 0.2 for state == "BRAKES ON FOR BETWEEN 0 AND 1 SECOND"
0.425 for STATE == BRAKES ON FOR BETWEEN 1 AND 2 SECOND"
0.85 for state == "BRAKES ON FOR MORE THAN 2 SECONDS"
Implied, but not stated, is that once the train stops, acceleration also
goes to zero -- the train does not start moving backwards.
Haskell has nifty pattern-matching syntax for this that looks quite close
to the mathematical hybrid function syntax, but in Python, we're limited
to explicitly using an if. If I were coding this, and I'm not, I'd wrap
it in a function. One advantage of a state variable rather than a
continuous time function is that we can do this:
def accel(state):
return {NO_BRAKING: 0.0,
LOW_BRAKING: 0.2,
MID_BRAKING: 0.425,
HIGH_BRAKING: 0.85}[state]
which is simple enough to skip using a function in the first place, and
just use the dict lookup directly. But for a more general question you'll
want acceleration as a function of time.
If you prefer if...elif over a dict, I'd still hide it in a function.
> Problem: Work out how far you'll go before the
> brakes reach full power, and how fast you'll be going at that point.
Given that problem, we actually only care about LOW_BRAKING and
MID_BRAKING. The problem becomes quite simple:
At t=0, the train is travelling at u m/s and the brakes are applied with
acceleration of 0.2m/s^2 for one second, then 0.425m/s^2 for an
additional one second. What is the speed of the train after those two
seconds, and the distance travelled.
This becomes a simple question for the four standard equations of motion:
(1) v = u + at
(2) s = 1/2(u + v)t
(3) s = ut + 1/2(at^2)
(4) v^2 = u^2 + 2as
Only (1) and (3) are needed.
The distance travelled in the first second is:
s1 = u - 0.1 m
and the speed of the train at that time becomes:
v = u - 0.2 m/s
Applying this for the second second gives:
s2 = (u - 0.2) - 0.2125 m
v = (u - 0.2) - 0.425 m/s
and the total distance:
s = s1 + s2
No programming required, just a calculator :-)
Given that solving the entire problem is barely five lines, writing code
to do so is probably unnecessary.
The only thing I haven't done is check that the train isn't travelling so
slowly that it comes to a complete halt within two seconds. I leave that
as an exercise. (Hint: if the final speed is negative, the train came to
a halt.)
> Here's how I currently have the code. The variable names are a tad long,
> as this was also part of me teaching my brother Python.
Whatever you used to post this, ate the indentation.
> # Already got the brakes fully on
> if mode=="Brake2": distance_to_full_braking_power, speed_full_brake =
> 0.0, curspeed
> # The brakes went on one second ago, they're nearly full elif
> mode=="Brake1": distance_to_full_braking_power, speed_full_brake =
> curspeed - 0.2125, curspeed - 0.425 # Brakes aren't on.
> else: distance_to_full_braking_power, speed_full_brake = (curspeed -
> 0.1) + (curspeed - 0.4125), curspeed - 0.625 # If we hit the brakes now
> (or already have hit them), we'll go another d meters and be going at s
> m/s before reaching full braking power.
Using sequence unpacking just to save a newline is naughty :-)
dist, speed = (curspeed - 0.1) + (curspeed - 0.4125), curspeed - 0.625
is an abuse of syntax, not far removed from:
dist = (curspeed - 0.1) + (curspeed - 0.4125); speed = curspeed - 0.625
It will be much more comprehensible written as two statements.
> But I don't like the layout. I could change it to a single assignment
> with expression-if, but that feels awkward too. How would you lay this
> out?
>
> (Note that the "else" case could have any of several modes in it, so I
> can't so easily use a dict.)
It could have, but doesn't. Is your aim to build a general purpose
Newtonian linear motion solver, or to solve this one problem?
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-01 16:01 +1100 |
| Message-ID | <mailman.8767.1396328509.18130.python-list@python.org> |
| In reply to | #69466 |
On Tue, Apr 1, 2014 at 3:26 PM, Steven D'Aprano <steve@pearwood.info> wrote:
> On Tue, 01 Apr 2014 01:33:09 +1100, Chris Angelico wrote:
>
>> Call this a code review request, if you like. I'm wondering how you'd go
>> about coding something like this.
>
> I wouldn't. I'd start off by analysing the problem, and putting it into
> the simplest format possible, and *then* start writing code if and only
> if needed. See below.
>
> The first mistake of computational mathematics is to do the computation
> before the mathematics, and the Holy Grail is to avoid the computation
> altogether.
Fair enough. :)
>> Imagine you're in a train, and the brakes don't apply instantly. The
>> definition, in the interests of passenger comfort,
>
> Ah, you're using comfort in the modern sense, i.e. what people used to
> call discomfort :-P
>
> The scenario you describe has (effectively) infinite rate-of-change-of-
> acceleration, often called "jerk". (A jerk is a rapid change in
> acceleration.) Human comfort is (within reasonable limits) more affected
> by jerk than acceleration. The passengers will feel three quite
> distinctive jerks, one when the brakes are first applied (which is
> probably reasonable), then one at 1s, then again at 2s. That's not
> comfortable by any stretch of the imagination.
It actually is a smooth increase in deceleration, but I'm operating
the simulator on a 1s period, so it's actually an average across the
first second, and an average across the next second...
>> is that the first
>> second of brake application has an acceleration of 0.2 m/s/s, the next
>> second has 0.425 m/s/s, and thereafter full effect of 0.85 m/s/s.
... so really, it's seeking upward from 0 to 0.85 according to some
curve, the details of which I'm not familiar with, but in terms of 1s
average accelerations, it's those figures. Actually even 1s resolution
is more than we need; the overall purpose is to get a calculated time
in minutes, so calculating to sub-second resolution (when, in reality,
this is trying to predict what a human will do) is massive overkill.
>> You
>> have a state variable that says whether the brakes have just been
>> applied, have already been applied for at least two seconds, or haven't
>> yet been applied at all.
>
> I wouldn't model it that way. Especially since you've missed at least one
> state :-) I'd model the acceleration as a function of time, otherwise you
> have to convert a time into a state. Nevertheless, if you insist, we can
> use a state variable instead:
>
> 0 for state == "BRAKES NOT APPLIED YET"
> accel = { 0.2 for state == "BRAKES ON FOR BETWEEN 0 AND 1 SECOND"
> 0.425 for STATE == BRAKES ON FOR BETWEEN 1 AND 2 SECOND"
> 0.85 for state == "BRAKES ON FOR MORE THAN 2 SECONDS"
>
> Implied, but not stated, is that once the train stops, acceleration also
> goes to zero -- the train does not start moving backwards.
"Just been applied" is poorly named; that's the state where the brakes
have been applied for 1 second so far. The other state (brakes not
applied yet) could be looking at powering (which follows a similar
curve in the opposite direction) or cruising (which has acceleration
of 0.0 m/s/s).
> Haskell has nifty pattern-matching syntax for this that looks quite close
> to the mathematical hybrid function syntax, but in Python, we're limited
> to explicitly using an if. If I were coding this, and I'm not, I'd wrap
> it in a function. One advantage of a state variable rather than a
> continuous time function is that we can do this:
>
> def accel(state):
> return {NO_BRAKING: 0.0,
> LOW_BRAKING: 0.2,
> MID_BRAKING: 0.425,
> HIGH_BRAKING: 0.85}[state]
That could be done, but with .get() to allow a default. I may well do that.
>> Problem: Work out how far you'll go before the
>> brakes reach full power, and how fast you'll be going at that point.
>
> Given that problem, we actually only care about LOW_BRAKING and
> MID_BRAKING. The problem becomes quite simple:
Right. The other state is "zero distance and zero loss of speed".
> At t=0, the train is travelling at u m/s and the brakes are applied with
> acceleration of 0.2m/s^2 for one second, then 0.425m/s^2 for an
> additional one second. What is the speed of the train after those two
> seconds, and the distance travelled.
>
> This becomes a simple question for the four standard equations of motion:
>
> (1) v = u + at
> (2) s = 1/2(u + v)t
> (3) s = ut + 1/2(at^2)
> (4) v^2 = u^2 + 2as
>
> Only (1) and (3) are needed.
Okay, what's u here? Heh.
> The distance travelled in the first second is:
>
> s1 = u - 0.1 m
>
> and the speed of the train at that time becomes:
>
> v = u - 0.2 m/s
>
> Applying this for the second second gives:
>
> s2 = (u - 0.2) - 0.2125 m
>
> v = (u - 0.2) - 0.425 m/s
>
> and the total distance:
>
> s = s1 + s2
>
>
> No programming required, just a calculator :-)
>
> Given that solving the entire problem is barely five lines, writing code
> to do so is probably unnecessary.
This is one small part of a larger piece of code (which, in this
instance, is trying to answer this question: "If I apply the brakes
now and keep them on until the next curve, will I be way below the
curve's speed limit?" - if yes, don't apply the brakes now).
> The only thing I haven't done is check that the train isn't travelling so
> slowly that it comes to a complete halt within two seconds. I leave that
> as an exercise. (Hint: if the final speed is negative, the train came to
> a halt.)
Yeah. Or just let that go into the next part of the calculation, which
works out quadratically how much distance -> how much time -> how much
remaining speed, which may have no solution ie it doesn't reach that
point. That part's fine.
> Whatever you used to post this, ate the indentation.
I posted that part without indentation, yeah. Gmail eats tabs.
Normally I manually replace them with spaces for posting, but since
this whole section was at the same indentation level, I didn't bother.
It is one of the problems with Gmail, though, and if I weren't running
this account on multiple systems of different OSes, I'd probably use a
dedicated client.
>> # Already got the brakes fully on
>> if mode=="Brake2": distance_to_full_braking_power, speed_full_brake =
>> 0.0, curspeed
>> # The brakes went on one second ago, they're nearly full elif
>> mode=="Brake1": distance_to_full_braking_power, speed_full_brake =
>> curspeed - 0.2125, curspeed - 0.425 # Brakes aren't on.
>> else: distance_to_full_braking_power, speed_full_brake = (curspeed -
>> 0.1) + (curspeed - 0.4125), curspeed - 0.625 # If we hit the brakes now
>> (or already have hit them), we'll go another d meters and be going at s
>> m/s before reaching full braking power.
>
> Using sequence unpacking just to save a newline is naughty :-)
>
> dist, speed = (curspeed - 0.1) + (curspeed - 0.4125), curspeed - 0.625
>
> is an abuse of syntax, not far removed from:
>
> dist = (curspeed - 0.1) + (curspeed - 0.4125); speed = curspeed - 0.625
>
> It will be much more comprehensible written as two statements.
Fair enough. :) That's why I asked. Is it naughty enough to break into
two statements, or is it better to combine it into a single multiple
assignment?
>> But I don't like the layout. I could change it to a single assignment
>> with expression-if, but that feels awkward too. How would you lay this
>> out?
>>
>> (Note that the "else" case could have any of several modes in it, so I
>> can't so easily use a dict.)
>
> It could have, but doesn't. Is your aim to build a general purpose
> Newtonian linear motion solver, or to solve this one problem?
To solve this one problem, as part of a simulator. For any purpose
beyond what you can see in the code itself, you'd have to ask my
brother; I don't have the full details on that.
Thanks for the advice! Flamage welcome, I'm wearing the asbestos
that's just been removed from the theatre here...
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2014-04-01 07:20 +0000 |
| Message-ID | <533a68c3$0$2909$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #69467 |
On Tue, 01 Apr 2014 16:01:40 +1100, Chris Angelico wrote:
[...]
>> The scenario you describe has (effectively) infinite rate-of-change-of-
>> acceleration, often called "jerk". (A jerk is a rapid change in
>> acceleration.) Human comfort is (within reasonable limits) more
>> affected by jerk than acceleration. The passengers will feel three
>> quite distinctive jerks, one when the brakes are first applied (which
>> is probably reasonable), then one at 1s, then again at 2s. That's not
>> comfortable by any stretch of the imagination.
>
> It actually is a smooth increase in deceleration, but I'm operating the
> simulator on a 1s period, so it's actually an average across the first
> second, and an average across the next second...
Hmmm. A 1-second resolution doesn't really sound too great to me.
Suppose the deceleration increases linearly from 0 to 0.85 m/s over two
seconds. Averaging it in the way you suggested, we get a total distance
of:
2*u - 0.5125
(see my previous post for details) where u is measured in metres per
second. Multiply by seconds to get the units right. For a Japanese bullet
train where u = 320 km/hr that corresponds to
py> 2*88.888889 - 0.5125
177.26527800000002
metres.
Now let's do it properly! Given our assumption that the deceleration is
linear, the jerk will be constant:
j = Δa/Δt
= (0.85 - 0)/2
= 0.425 m/s^3
Let's start integrating!
py> from sympy import integrate
py> from sympy.abc import t
py> j = '0.425'
py> a = integrate(j, t)
py> v = 88.888889 - integrate(a, t)
py> s = integrate(v, (t, 0, 2))
py> s
177.211111333333
compared to 177.26527800000002 calculated the rough way. That's not bad,
only about 5cm off! Effectively, your rough calculation was accurate to
one decimal place.
Of course, if the equation for acceleration was more complex, the
approximation may not be anywhere near as good.
[...]
>> This becomes a simple question for the four standard equations of
>> motion:
>>
>> (1) v = u + at
>> (2) s = 1/2(u + v)t
>> (3) s = ut + 1/2(at^2)
>> (4) v^2 = u^2 + 2as
>>
>> Only (1) and (3) are needed.
>
> Okay, what's u here? Heh.
They're *standard* equations of motion. Weren't you paying attention
through the, oh, three years of high school where they teach this? :-P
s = displacement (distance)
t = time
u = initial velocity
v = final velocity
a = acceleration
[...]
> Fair enough. :) That's why I asked. Is it naughty enough to break into
> two statements, or is it better to combine it into a single multiple
> assignment?
Since they are unrelated assignments, of two different variables, they
should be written as two separate assignments, not one using sequence
unpacking.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-01 18:35 +1100 |
| Message-ID | <mailman.8778.1396337762.18130.python-list@python.org> |
| In reply to | #69478 |
On Tue, Apr 1, 2014 at 6:20 PM, Steven D'Aprano <steve@pearwood.info> wrote: > On Tue, 01 Apr 2014 16:01:40 +1100, Chris Angelico wrote: > > [...] >>> The scenario you describe has (effectively) infinite rate-of-change-of- >>> acceleration, often called "jerk". (A jerk is a rapid change in >>> acceleration.) Human comfort is (within reasonable limits) more >>> affected by jerk than acceleration. The passengers will feel three >>> quite distinctive jerks, one when the brakes are first applied (which >>> is probably reasonable), then one at 1s, then again at 2s. That's not >>> comfortable by any stretch of the imagination. >> >> It actually is a smooth increase in deceleration, but I'm operating the >> simulator on a 1s period, so it's actually an average across the first >> second, and an average across the next second... > > Hmmm. A 1-second resolution doesn't really sound too great to me. > > Suppose the deceleration increases linearly from 0 to 0.85 m/s over two > seconds. Averaging it in the way you suggested, we get a total distance > of: > > 2*u - 0.5125 > > (see my previous post for details) where u is measured in metres per > second. Multiply by seconds to get the units right. For a Japanese bullet > train where u = 320 km/hr that corresponds to > > py> 2*88.888889 - 0.5125 > 177.26527800000002 > > metres. > > Now let's do it properly! Given our assumption that the deceleration is > linear, the jerk will be constant: > > j = Δa/Δt > = (0.85 - 0)/2 > = 0.425 m/s^3 > > Let's start integrating! > > py> from sympy import integrate > py> from sympy.abc import t > py> j = '0.425' > py> a = integrate(j, t) > py> v = 88.888889 - integrate(a, t) > py> s = integrate(v, (t, 0, 2)) > py> s > 177.211111333333 > > compared to 177.26527800000002 calculated the rough way. That's not bad, > only about 5cm off! Effectively, your rough calculation was accurate to > one decimal place. 5cm when we're dealing with track distances measured in meters and usually hundreds of them? Sounds fine to me! > Of course, if the equation for acceleration was more complex, the > approximation may not be anywhere near as good. And that's the bit I can't know. I've added a comment to the code and will toss it back to my brother - hopefully he'll either know the answer or know where to look it up / who to ask. > [...] >>> This becomes a simple question for the four standard equations of >>> motion: >>> >>> (1) v = u + at >>> (2) s = 1/2(u + v)t >>> (3) s = ut + 1/2(at^2) >>> (4) v^2 = u^2 + 2as >>> >>> Only (1) and (3) are needed. >> >> Okay, what's u here? Heh. > > They're *standard* equations of motion. Weren't you paying attention > through the, oh, three years of high school where they teach this? :-P They're certainly the standard equations, but I learned that: d = v₀t + at²/2 which is the same as you had, except for the names: d for distance, v₀ (V zero, that's a subscript zero if encodings or fonts kill you here) for initial velocity (ie velocity at time zero - vₜ (that's a subscript t, U+209C, but it isn't working in this font) is velocity at time t, which is v₀+at), and a and t are the same as you have. > s = displacement (distance) > t = time > u = initial velocity > v = final velocity > a = acceleration I have to say, the one-letter variables are a lot easier to work with. Guess I learned them the hard way, heh. Although remembering that v is velocity is easier than remembering which of u and v is initial and which is final. >> Fair enough. :) That's why I asked. Is it naughty enough to break into >> two statements, or is it better to combine it into a single multiple >> assignment? > > Since they are unrelated assignments, of two different variables, they > should be written as two separate assignments, not one using sequence > unpacking. Change made. Yeah, that looks a bit cleaner. Although I would prefer a simple formula to what I have there, and I'm still not perfectly sure it's accurate. Advice appreciated. :) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2014-04-01 08:07 +0000 |
| Message-ID | <533a73a9$0$2909$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #69483 |
On Tue, 01 Apr 2014 18:35:52 +1100, Chris Angelico wrote: > Although remembering that v is > velocity is easier than remembering which of u and v is initial and > which is final. Which comes earlier in the alphabet? :-P -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-01 19:12 +1100 |
| Message-ID | <mailman.8782.1396339983.18130.python-list@python.org> |
| In reply to | #69487 |
On Tue, Apr 1, 2014 at 7:07 PM, Steven D'Aprano <steve@pearwood.info> wrote: > On Tue, 01 Apr 2014 18:35:52 +1100, Chris Angelico wrote: > >> Although remembering that v is >> velocity is easier than remembering which of u and v is initial and >> which is final. > > Which comes earlier in the alphabet? :-P So why isn't v initial velocity and w final? You start with some velocity, right? (Okay, now I'm mostly trolling. Heh. I did say your way was better, to start with.) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2014-04-01 02:18 -0600 |
| Message-ID | <mailman.8783.1396340355.18130.python-list@python.org> |
| In reply to | #69478 |
On Tue, Apr 1, 2014 at 1:35 AM, Chris Angelico <rosuav@gmail.com> wrote:
> On Tue, Apr 1, 2014 at 6:20 PM, Steven D'Aprano <steve@pearwood.info> wrote:
>> 177.211111333333
>>
>> compared to 177.26527800000002 calculated the rough way. That's not bad,
>> only about 5cm off! Effectively, your rough calculation was accurate to
>> one decimal place.
>
> 5cm when we're dealing with track distances measured in meters and
> usually hundreds of them? Sounds fine to me!
Erm, that's just the accumulated error over the first 2 seconds,
though. A train moving at 88 m/s and decelerating at a maximum of
0.85 m/s^2 is not going to stop in just 177 meters.
After the first 2 seconds, the model is the same using either method,
but the velocity after 2 seconds is different. Using the linear
deceleration integration, we get:
a(t) = {-0.425t, t <= 2;
-0.85, t > 2}
v(t) = {v0 - 0.2125t^2, t <= 2;
v0 - 0.85 - 0.85t, t > 2}
Giving v(2s) = v0 - 0.85 m/s
Using the averaging method, we get v(2s) = v0 - 0.2 - 0.425 = v0 - 0.625 m/s
For a difference of 0.225 m/s. Using Steven's formula (4), the
additional difference in stopping distance is thus:
Δs = ((0 - (88.888889 - 0.625)^2) - (0 - (88.888889 - 0.85)^2)) / -1.7
= 23.33 m
The reason the velocity is different after 2 seconds is because the
linear deceleration does not match the constraints of the problem. The
average deceleration for the first second is not 0.2 m/s, and the
average deceleration for the second second is not 0.425 m/s.
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2014-04-01 02:24 -0600 |
| Message-ID | <mailman.8785.1396340689.18130.python-list@python.org> |
| In reply to | #69478 |
On Tue, Apr 1, 2014 at 2:18 AM, Ian Kelly <ian.g.kelly@gmail.com> wrote: > The reason the velocity is different after 2 seconds is because the > linear deceleration does not match the constraints of the problem. The > average deceleration for the first second is not 0.2 m/s, and the > average deceleration for the second second is not 0.425 m/s. Which I suddenly realize after posting makes my entire point moot. It doesn't matter how much total error there is from the linear deceleration method because the linear deceleration is wrong. As long as the averaging method has the actually correct velocity at 2s and thereafter continues to have the actually correct velocity, it will only be off by that small amount of error from the first two seconds.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web