Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #58933 > unrolled thread
| Started by | John von Horn <j.h69@btinternet.com> |
|---|---|
| First post | 2013-11-09 07:08 -0600 |
| Last post | 2013-11-12 01:53 +0000 |
| Articles | 6 on this page of 46 — 23 participants |
Back to article view | Back to comp.lang.python
New user's initial thoughts / criticisms of Python John von Horn <j.h69@btinternet.com> - 2013-11-09 07:08 -0600
Re: New user's initial thoughts / criticisms of Python Ned Batchelder <ned@nedbatchelder.com> - 2013-11-09 05:22 -0800
Re: New user's initial thoughts / criticisms of Python Joshua Landau <joshua@landau.ws> - 2013-11-09 13:27 +0000
Re: New user's initial thoughts / criticisms of Python Jonathan <jtcegh@gmail.com> - 2013-11-09 14:44 -0800
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-10 10:29 +1100
Re: New user's initial thoughts / criticisms of Python MRAB <python@mrabarnett.plus.com> - 2013-11-10 00:50 +0000
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-10 11:54 +1100
Re: New user's initial thoughts / criticisms of Python Neil Cerutti <neilc@norwich.edu> - 2013-11-11 15:30 +0000
Re: New user's initial thoughts / criticisms of Python Thomas Rachel <nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915@spamschutz.glglgl.de> - 2013-11-10 13:24 +0100
Re: New user's initial thoughts / criticisms of Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2013-11-09 13:41 +0000
Re: New user's initial thoughts / criticisms of Python Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2013-11-09 16:24 +0200
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-10 01:27 +1100
Sandboxing Python [was Re: New user's initial thoughts / criticisms of Python] Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-11-09 15:25 +0000
Re: Sandboxing Python [was Re: New user's initial thoughts / criticisms of Python] Chris Angelico <rosuav@gmail.com> - 2013-11-10 02:32 +1100
Re: New user's initial thoughts / criticisms of Python Jorgen Grahn <grahn+nntp@snipabacken.se> - 2013-11-10 08:47 +0000
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-10 20:22 +1100
Re: New user's initial thoughts / criticisms of Python Ian Kelly <ian.g.kelly@gmail.com> - 2013-11-10 04:39 -0700
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-10 22:43 +1100
Re: New user's initial thoughts / criticisms of Python Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-11-10 12:12 -0500
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-11 10:29 +1100
Re: New user's initial thoughts / criticisms of Python Terry Reedy <tjreedy@udel.edu> - 2013-11-10 19:13 -0500
Re: New user's initial thoughts / criticisms of Python rusi <rustompmody@gmail.com> - 2013-11-09 07:38 -0800
Re: New user's initial thoughts / criticisms of Python Roy Smith <roy@panix.com> - 2013-11-09 10:56 -0500
Re: New user's initial thoughts / criticisms of Python rusi <rustompmody@gmail.com> - 2013-11-09 08:30 -0800
Re: New user's initial thoughts / criticisms of Python Rick Johnson <rantingrickjohnson@gmail.com> - 2013-11-10 21:36 -0800
Re: New user's initial thoughts / criticisms of Python Roy Smith <roy@panix.com> - 2013-11-11 09:01 -0500
Re: New user's initial thoughts / criticisms of Python rusi <rustompmody@gmail.com> - 2013-11-11 07:14 -0800
Re: New user's initial thoughts / criticisms of Python Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2013-11-11 21:05 -0500
Re: New user's initial thoughts / criticisms of Python Ethan Furman <ethan@stoneleaf.us> - 2013-11-12 14:38 -0800
Re: New user's initial thoughts / criticisms of Python John von Horn <j.h69@btinternet.com> - 2013-11-09 14:19 -0600
Re: New user's initial thoughts / criticisms of Python Tim Chase <python.list@tim.thechases.com> - 2013-11-09 14:39 -0600
Re: New user's initial thoughts / criticisms of Python Mark Janssen <dreamingforward@gmail.com> - 2013-11-09 12:33 -0800
Re: New user's initial thoughts / criticisms of Python Ned Batchelder <ned@nedbatchelder.com> - 2013-11-09 12:54 -0800
Re: New user's initial thoughts / criticisms of Python Mark Janssen <dreamingforward@gmail.com> - 2013-11-09 13:21 -0800
Re: New user's initial thoughts / criticisms of Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2013-11-09 21:01 +0000
Re: New user's initial thoughts / criticisms of Python Tim Chase <python.list@tim.thechases.com> - 2013-11-09 15:20 -0600
Re: New user's initial thoughts / criticisms of Python lorenzo.gatti@gmail.com - 2013-11-11 02:09 -0800
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-11 21:39 +1100
Re: New user's initial thoughts / criticisms of Python Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-11-11 11:17 +0000
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-11 22:32 +1100
Re: New user's initial thoughts / criticisms of Python Mark Janssen <dreamingforward@gmail.com> - 2013-11-11 14:29 -0800
Re: New user's initial thoughts / criticisms of Python Robert Kern <robert.kern@gmail.com> - 2013-11-11 11:53 +0000
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-11 23:07 +1100
Re: New user's initial thoughts / criticisms of Python Joshua Landau <joshua@landau.ws> - 2013-11-11 20:50 +0000
Re: New user's initial thoughts / criticisms of Python Chris Angelico <rosuav@gmail.com> - 2013-11-12 09:21 +1100
Re: New user's initial thoughts / criticisms of Python Joshua Landau <joshua@landau.ws> - 2013-11-12 01:53 +0000
Page 3 of 3 — ← Prev page 1 2 [3]
| From | Mark Janssen <dreamingforward@gmail.com> |
|---|---|
| Date | 2013-11-11 14:29 -0800 |
| Message-ID | <mailman.2402.1384208960.18130.python-list@python.org> |
| In reply to | #59064 |
On Mon, Nov 11, 2013 at 3:32 AM, Chris Angelico <rosuav@gmail.com> wrote: > On Mon, Nov 11, 2013 at 10:17 PM, Steven D'Aprano > <steve+comp.lang.python@pearwood.info> wrote: >> On Mon, 11 Nov 2013 21:39:27 +1100, Chris Angelico wrote: >>> denormalizes it into a lookup table by creating 70 entries quoting the >>> first string, 15 quoting the second, 5, and 10, respectively. >> >> Ewww :-( >> >> Imagine having to print out the dict looking for an error in the lookup >> table. Or imagine the case where you have: >> >> 0...20000: do this >> 20001...890001: do that >> 890001...890003: do something else >> >> Don't get me wrong, it's a clever and reasonable solution for your >> specific use-case. But I'd much rather have a lookup table variant that >> matches on intervals. > > Of course it's "Ewww" in isolation :) But just imagine there are piles > and piles of these tables, themselves keyed by keyword, and I want to > be able to let untrusted people create tables (which means they > basically have to be data, not code). Also, bear in mind, all the > tables are based around dice that can be physically rolled, so none > has more than 100 entries after denormalization. Quite a lot of the > tables actually have unique entries per value (eg it's a d10 roll, > with ten unique outputs), so it's simplest to just turn all the tables > into that format; that way, the main code needs worry about one type > only, and the preprocessor handles the denormalization. Hmm, I automatically think of creating a hash function, but then that's how Python implements keys in dicts, so a dict is fine solution. -- MarkJ Tacoma, Washington
[toc] | [prev] | [next] | [standalone]
| From | Robert Kern <robert.kern@gmail.com> |
|---|---|
| Date | 2013-11-11 11:53 +0000 |
| Message-ID | <mailman.2373.1384170873.18130.python-list@python.org> |
| In reply to | #59060 |
On 2013-11-11 10:39, Chris Angelico wrote:
> A 'minor weapon' is based on a roll of a 100-sided dice. If it's 01 to
> 70, "+1 weapon: 2,000gp [weapon]"; if it's 71 to 85, "+2 weapon:
> 8,000gp [weapon]"; if 86 to 90, "Specific weapon [minor specific
> weapon]"; and if 91 to 100, "Special ability [minor special weapon]
> and roll again".
>
> My code to handle that starts out with this array:
>
> "minor weapon":({
> 70,"+1 weapon: 2,000gp [weapon]",
> 85,"+2 weapon: 8,000gp [weapon]",
> 90,"Specific weapon [minor specific weapon]",
> 100,"Special ability [minor special weapon] and roll again",
> }),
>
> (that's Pike; in Python it'd be a list, or maybe a tuple of tuples),
> and denormalizes it into a lookup table by creating 70 entries quoting
> the first string, 15 quoting the second, 5, and 10, respectively. So,
> with a bit of preprocessing, a lookup table (which in this case is an
> array (list), but could just as easily be a dict) can be used to
> handle inequalities. But this is because lookup tables can be treated
> as data, where if/elif/else blocks have to be code; there are roughly
> 42 million such lookup tables in the code I snagged that from, and
> having code for each one would work out far less manageable. Normally,
> you'll want to render inequalities with code as if/elif.
Heh. I've done pretty much exactly the same thing to implement an engine[1] to
draw from the random tables on Abulafia[2] which have nearly the same structure.
It scales up reasonably well beyond d100s. It's certainly not a technique I
would pull out to replace one-off if-elif chains that you literally write, but
it works well when you write the generic code once to apply to many tables.
[1] http://rollmeup.mechanicalkern.com/
[2] http://www.random-generator.com/index.php?title=Main_Page
--
Robert Kern
"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-11-11 23:07 +1100 |
| Message-ID | <mailman.2375.1384171657.18130.python-list@python.org> |
| In reply to | #59060 |
On Mon, Nov 11, 2013 at 10:53 PM, Robert Kern <robert.kern@gmail.com> wrote: > Heh. I've done pretty much exactly the same thing to implement an engine[1] > to draw from the random tables on Abulafia[2] which have nearly the same > structure. It scales up reasonably well beyond d100s. It's certainly not a > technique I would pull out to replace one-off if-elif chains that you > literally write, but it works well when you write the generic code once to > apply to many tables. I'd trust my current code for several orders of magnitude beyond where I'm currently using it, but as Steven said, you really don't want to be manually looking at the denormalized tables. Since all the strings are referenced anyway, having a lookup array of (say) 1,000,000 object pointers is fairly cheap. >>> lst = ["Low" if i<500000 else "High" for i in range(1000000)] >>> sys.getsizeof(lst) 4348736 That's pretty close to four bytes per entry, which would be the cheapest you could hope for on a 32-bit system. 10% overhead is quite acceptable. And this is a fairly extreme example :) ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Joshua Landau <joshua@landau.ws> |
|---|---|
| Date | 2013-11-11 20:50 +0000 |
| Message-ID | <mailman.2398.1384203083.18130.python-list@python.org> |
| In reply to | #59060 |
On 11 November 2013 10:39, Chris Angelico <rosuav@gmail.com> wrote:
> On Mon, Nov 11, 2013 at 9:09 PM, <lorenzo.gatti@gmail.com> wrote:
>> Regarding the "select" statement, I think the most "Pythonic" approach is using dictionaries rather than nested ifs.
>> Supposing we want to decode abbreviated day names ("mon") to full names ("Monday"):
>
> You can't [normally], for instance, build up a
> dictionary that handles inequalities, but you can do that with elif.
> [...] Consider the following logic:
>
> A 'minor weapon' is based on a roll of a 100-sided dice. If it's 01 to
> 70, "+1 weapon: 2,000gp [weapon]"; if it's 71 to 85, "+2 weapon:
> 8,000gp [weapon]"; if 86 to 90, "Specific weapon [minor specific
> weapon]"; and if 91 to 100, "Special ability [minor special weapon]
> and roll again".
>
> My code to handle that starts out with this array:
>
> "minor weapon":({
> 70,"+1 weapon: 2,000gp [weapon]",
> 85,"+2 weapon: 8,000gp [weapon]",
> 90,"Specific weapon [minor specific weapon]",
> 100,"Special ability [minor special weapon] and roll again",
> }),
>
> (that's Pike; in Python it'd be a list, or maybe a tuple of tuples),
> and denormalizes it into a lookup table by creating 70 entries quoting
> the first string, 15 quoting the second, 5, and 10, respectively. So,
> with a bit of preprocessing, a lookup table (which in this case is an
> array (list), but could just as easily be a dict) can be used to
> handle inequalities.
The obvious way to me is a binary search:
from bisect import bisect_left
class FloorMap:
def __init__(self, dct):
self.indexes = sorted(list(dct))
self.dct = dct
def __getitem__(self, itm):
index = self.indexes[bisect_left(self.indexes, itm)]
return self.dct[index]
minor_weapon = FloorMap({
70: "+1 weapon: 2,000gp [weapon]",
85: "+2 weapon: 8,000gp [weapon]",
90: "Specific weapon [minor specific weapon]",
100: "Special ability [minor special weapon] and roll again"
})
minor_weapon[63]
#>>> '+1 weapon: 2,000gp [weapon]'
The precise details of the wrapper class here are just to make
initialisation pretty; it could be done straight from a pair of lists
too:
from bisect import bisect_left
minor_weapon_indexes = 70, 85, 90, 100
minor_weapon_descriptions = (
"+1 weapon: 2,000gp [weapon]",
"+2 weapon: 8,000gp [weapon]",
"Specific weapon [minor specific weapon]",
"Special ability [minor special weapon] and roll again"
)
minor_weapon_descriptions[bisect_left(minor_weapon_indexes, 80)]
#>>> '+2 weapon: 8,000gp [weapon]'
Compare to
if 80 <= 70:
res = "+1 weapon: 2,000gp [weapon]"
elif 80 <= 85:
res = "+2 weapon: 8,000gp [weapon]"
elif 80 <= 90:
res = "Specific weapon [minor specific weapon]"
elif 80 <= 100:
res = "Special ability [minor special weapon] and roll again"
which although shorter¹ is a lot less data-driven and much less reusable.
¹ Longer if you ignore the import and class declaration.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2013-11-12 09:21 +1100 |
| Message-ID | <mailman.2401.1384208527.18130.python-list@python.org> |
| In reply to | #59060 |
On Tue, Nov 12, 2013 at 7:50 AM, Joshua Landau <joshua@landau.ws> wrote: > The obvious way to me is a binary search: Which makes an O(log n) search where I have an O(1) lookup. The startup cost of denormalization doesn't scale, so when the server keeps running for two years or more, it's definitely worth processing it that way. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Joshua Landau <joshua@landau.ws> |
|---|---|
| Date | 2013-11-12 01:53 +0000 |
| Message-ID | <mailman.2417.1384221253.18130.python-list@python.org> |
| In reply to | #59060 |
On 11 November 2013 22:21, Chris Angelico <rosuav@gmail.com> wrote: > On Tue, Nov 12, 2013 at 7:50 AM, Joshua Landau <joshua@landau.ws> wrote: >> The obvious way to me is a binary search: > > Which makes an O(log n) search where I have an O(1) lookup. The > startup cost of denormalization doesn't scale, so when the server > keeps running for two years or more, it's definitely worth processing > it that way. log 4 is tiny so I'd expect constant factors to be far more significant here. Then you add on the better asymptotic behaviours for large n, space wise, and the simplicity of implementation. This just seems like a premature optimisation to me, I guess. I agree that your way is faster; I just don't see a single case in which I'd care. I do see several circumstances (large or floating numbers) in which I'd probably prefer my way. Feel free to disagree, I'm not really trying to convince you.
[toc] | [prev] | [standalone]
Page 3 of 3 — ← Prev page 1 2 [3]
Back to top | Article view | comp.lang.python
csiph-web