Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
fart simpson
Jul 2, 2005

DEATH TO AMERICA
:xickos:


:aaa: This is amazing and I simultaneously need to and don't want to look at the source code

Adbot
ADBOT LOVES YOU

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
It's the same trick I used for gwfal.

https://github.com/magcius/toenail/blob/master/gwfal_example.py
https://github.com/magcius/toenail/blob/master/gwfal.py

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord

Dren posted:

I think what you'll have to do here is unpack the array in your overloaded __getitem__ method and feed it to np.ndarray.__getitem__() one value at a time.

Thanks, this got me in the right path!

Python code:
import numpy as np

class defaultarray(np.ndarray):
    def __getitem__(self, index):
        if hasattr(index, '__iter__'):
            return np.array([self.__getitem__(x) 
                             if x >= 0
                             else 0
                             for x in index]).view(defaultarray)
        else:
            try:
                return np.ndarray.__getitem__(self, index)
            except IndexError:
                return 0
But uh... :stare:

Other than pure curiosity, here's my motivation for this:

A lot of numpy code seems to revolve around passing arrays as indices and when you get an array with crazy values you use np.clip and limit those values so you don't get errors and still keep going.

The thing is though that this kind of interpolation sometimes gives you some silly results, like look at this guy:




So I'm thinking instead of passing through np.clip just using some sort of "defaultarray" and then get a result like this:



Without really needing to rethink the whole "passing arrays as indices" approach.

EDIT: The code doesn't actually work on higher dimensional arrays and oh god this looks like a nightmare to get right.

Symbolic Butt fucked around with this message at 19:45 on Sep 30, 2013

Nippashish
Nov 2, 2005

Let me see you dance!

Pollyanna posted:

Cool, thanks. I updated it:

tick_world is still doing the mutate-its-argument thing.

Pollyanna posted:

Now I'm trying to figure out how to make it return an image of the array.

PIL has an Image.fromarray function for creating an image out of a numpy array. Alternatively you can use matplotlib.

salisbury shake
Dec 27, 2011

Dren posted:

I mostly like this but I think you should move _step() and tick() out of your Universe class. That way Universe is a representation of the game board and there would be a clean separation between the model (Universe) and the business logic (_step() and tick()). Also, why is _step() a property?

_step calculates the cells that should be set to live/die by tick(), I wanted to be able to access the points before calling tick() so I could throw a quick view with pygame together. I wasn't familiar with the GoL so I wrote the tests for the requirements first, and in writing the code I took that intention of _step() returning the next state and not applying it too literally. In the process of cleaning it up, I made _step() a method that returns the next frame for tick() and made _live_points() and _dead_points() methods with the current live/dead points, and scrapped writing a getter/setter to make them a property.

Didn't think python would choke so easily on the naive method I posted, so I cleaned it up a bit so it can handle 100x100 Universe instances without chugging along. Pulled out the subfuncs out of _step() and neighbors() so that they aren't created/destroyed a dozen a times a tick. Also using sets/frozensets sped things up considerably.
I'll play with numpy arrays when I have some time at work, just running the script through pypy almost triples the speed it takes to tick().

Anyone want to pick this apart and tell me what I could do better? Where would _step() and tick() better be implemented?

https://gist.github.com/thismachinechills/6767584 game logic
https://gist.github.com/thismachinechills/6767628 pygame (this was just thrown together)

edit: For future reference: is there a way to interface a module running in Pypy with the standard interpreter? Could I run my model through pypy and have the view layer run in pygame? In this case, numpy + removing redundant cruft will probably speed things up, but I'm still curious. If it isn't feasible, what about setting up a shared resource in memory that the Pypy module writes to and the standard python interpreter can read from? help babby use computer

double edit: How do I initialize a 2-d numpy array of booleans? Never mind, figured it out.
code:
 np.array(np.zeros_like((np.arange(x*y).reshape((x,y)))), dtype=bool)

Accomplishes what I want. Its actually slower than pythons built in types. Pypy flies through the original

salisbury shake fucked around with this message at 02:29 on Oct 1, 2013

QuarkJets
Sep 8, 2008

Pollyanna posted:

I actually think PyCharm automatically handles tabs and spaces and whatnot already, cause tabbing puts in four spaces for me. Easy enough.

Also, is there a tutorial for Tkinter out there that doesn't suck?

TKinter in general sucks. I have had some experience with PyQt and wxpython, and they both have some good tutorials out there

Dren
Jan 5, 2001

Pillbug
I was unable to resist writing my own game of life implementation.

salisbury shake, I benchmarked both of ours and my computation of the next gameboard state is roughly twice as fast as yours. I benchmarked our implementations using the same randomly seeded 200x200 game board and made sure I only benchmarked the methods for computing the next board iteration.

Here is my grid class, https://github.com/robwiss/gameoflife_py/blob/master/grid.py. I was pleased with my implementation of _num_alive_neighbors.

I also included unit tests and two frontends for the game. One reads/writes to a file every time it is run, https://github.com/robwiss/gameoflife_py/blob/master/flatfile_gol.py. It generates a file like this (you can hand edit it if you like):
code:
+----------+
| **** ****|
|*   *    *|
|** *  ** *|
|*   ** * *|
|**     * *|
|     *** *|
|****** * *|
|*         |
|    ** ** |
|    ** ** |
+----------+
The other is an adaptation of your pygame gist scaled by a factor of 4, https://github.com/robwiss/gameoflife_py/blob/master/pygame_gol.py. Maybe there is a better way to scale by 4? I have never used pygame before.

With a bit more effort I could get the pygame implementation to initialize from one of the text files but I didn't do that. I also didn't spend too much time thinking about making it efficient and I was kind of surprised that it doesn't run faster.

salisbury shake
Dec 27, 2011
code:
alex@macbuntu:~/Projects/game_of_py$ time pypy gol.py
1000 frames generated.
real	0m17.120s
user	0m16.694s
sys	0m0.063s
alex@macbuntu:~/Projects/game_of_py$ time python gol.py
1000 frames generated.
real	2m22.885s
user	2m22.389s
sys	0m0.022s
alex@macbuntu:~/Projects/game_of_py$ time python gol_np.py
1000 frames generated.
real	2m45.567s
user	2m45.000s
sys	0m0.039s

Last one is using numpy arrays instead of lists. I didn't abuse inheritence this time and just made the array a class attribute. I also pulled out the double calling of _living_points() and _dead_points() in both gol.py and play.py, so now _step() calls them once and assigns the output to class attributes from which play.py reads.

Is the expected speed up inherent to the design of numpy's array data structure compared to the standard ones? Or are the numpy arrays supposed to be used in conjunction with the numpy functions/operations to achieve the boost? This leads me to think the bottleneck isn't the data structures but my inefficient operations. I'm also probably abusing the numpy array just instantiating it, that could lend to the poo poo time

edit: just saw your post now, Dren. checking out your code now

salisbury shake fucked around with this message at 03:04 on Oct 1, 2013

Dren
Jan 5, 2001

Pillbug
I just tried pypy, it is stupidly faster than cpython.

code:
$ pypy -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 28.9 msec per loop

$ python -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 443 msec per loop
game.txt is a random 200x200 grid.

salisbury shake
Dec 27, 2011
It seems that some of my slow down was yet again borne of my tests:
:downs:
Python code:
def test_step_two_three_neighbors_live(self):
		live_points = [(0, 0), (0, 1), (0, 2), (1, 1)]
		should_live = live_points[1:]

		for point in live_points:
			self.u.live(point)

		neighbors = self.u.neighbors((0, 1))
		live_neighbors = [neighbor for neighbor in neighbors if self.u.val(neighbor)]
		self.assertEqual(3, len(live_neighbors))

		to_live, to_die = self.u._step

		for should in should_live:
			self.assertTrue(should in to_live)
It's passing around the exact neighbors and testing their truth value with a bunch of set comprehensions a few times a tick(). It just needs the amount:
code:
alex@macbuntu:~/Projects/game_of_py$ python -m cProfile -s time play.py 
^C         9827536 function calls (9827173 primitive calls) in 6.135 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   209000    1.464    0.000    3.791    0.000 gol.py:50(neighbors)

Dren posted:

I just tried pypy, it is stupidly faster than cpython.

code:
$ pypy -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 28.9 msec per loop

$ python -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 443 msec per loop
game.txt is a random 200x200 grid.

Yea, I was surprised at the numbers.

Unfortunately pygame isn't supported by pypy, but I'm not having any luck finding out if there is a solution to that problem though. I don't want to have to generate the frames save them to a file and load them to display them with pygame, as I added some click-to-toggle action for the cells. :colbert: But I'm coming up dry on sources on how to interface a pypy module/instance/anything with a standard python script.

edit: V thanks, I'll give the numpy docs a better look. Trying out numba now

salisbury shake fucked around with this message at 05:30 on Oct 1, 2013

BigRedDot
Mar 6, 2008

salisbury shake posted:

Or are the numpy arrays supposed to be used in conjunction with the numpy functions/operations to achieve the boost?
Yes. Numpy operations dispatch to tight, type-appropriate C loops that vectorize over whole views of the array at a time. If you aren't using them, you are missing the biggest benefit Numpy provides. In fact indexing with square brackets into Numpy arrays will actually be slower than with lists, since the array __getitem__ has to do more work. If you are using square brackets everywhere inside loops you can easily end off worse.

Another interesting comparison (especially against pypy) would be to jit your code with Numba. I am traveling this week otherwise I would give it a go myself.

BigRedDot fucked around with this message at 05:07 on Oct 1, 2013

Nippashish
Nov 2, 2005

Let me see you dance!
Since we're all comparing GOL implementations now here's mine: http://pastebin.com/zLu8eNWc. I've included the interface Dren's flatfile_gol.py expects for reading/writing grids, but everything of interest happens in tick().

Some times for different sized grids:
code:
50x50
1000 loops, best of 3: 1.82 msec per loop
200x200
10 loops, best of 3: 26.2 msec per loop
1000x1000
10 loops, best of 3: 652 msec per loop
For comparison, Dren's code takes 325 msec per loop on with a 200x200 grid on my machine.

Pollyanna
Mar 5, 2005

Milk's on them.


Oh god, I've got a ways to go, don't I? :negative:

QuarkJets posted:

TKinter in general sucks. I have had some experience with PyQt and wxpython, and they both have some good tutorials out there

Qt isn't free and I keep hearing bad things about wxpython.

Pollyanna fucked around with this message at 05:44 on Oct 1, 2013

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Pollyanna posted:

Oh god, I've got a ways to go, don't I? :negative:


Qt isn't free and I keep hearing bad things about wxpython.

Just use PySide.

Man, now I want to get out of bed and do a GoL implementation.

Posting Principle
Dec 10, 2011

by Ralp
Qt is free as in beer and free as in freedom.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Qt didn't used to be free, but it's been free ever Qt 4.5 came out in 2008 (I think?)

I know Tkinter sucks, but it really helps if you want to distribute a quick and dirty app to somebody who does not want to install PySide.

Posting Principle
Dec 10, 2011

by Ralp
2009 it was released under the LGPL. It had been GPL'd since 2000.

nonathlon
Jul 9, 2004
And yet, somehow, now it's my fault ...
Taking a break from GoL implementations:

Am I right that Biopython isn't working under Python3 as yet? That's the main obstacle to me moving across to v3. I've looked at lists of "3 ready" libraries and it seems like most of the big, useful things have gone across: Numpy, elementtree, lxml. Any notable exceptions I might have missed?

Lysidas
Jul 26, 2002

John Diefenbaker is a madman who thinks he's John Diefenbaker.
Pillbug
I've been using Biopython with 3.x for about two years, both 3.2 and 3.3. I keep a clone of their Git repository and just updated my local installation to release 162. setup.py build used to say something like "Python 3 support is still experimental" before it ran 2to3, but that message seems to have disappeared so maybe it's considered production-ready now.

I've never had any problems with it on Python 3, but I've probably only used a third of the functionality that the package provides.

Dren
Jan 5, 2001

Pillbug

Nippashish posted:

Since we're all comparing GOL implementations now here's mine: http://pastebin.com/zLu8eNWc. I've included the interface Dren's flatfile_gol.py expects for reading/writing grids, but everything of interest happens in tick().

Some times for different sized grids:
code:
50x50
1000 loops, best of 3: 1.82 msec per loop
200x200
10 loops, best of 3: 26.2 msec per loop
1000x1000
10 loops, best of 3: 652 msec per loop
For comparison, Dren's code takes 325 msec per loop on with a 200x200 grid on my machine.

I like the approach of using a convolution kernel. The thought didn't even cross my mind. Can you modify it to also output the indices of the cells that changed and their new values? That way it would work with the pygame frontend. I gave it a shot but I'm not sure if I did it in the fastest way possible. Here it is: https://gist.github.com/robwiss/6781310

I updated the unit tests I wrote to work on the public API of the Grid class. Your stuff passes the tests (I found an error in my stuff). I also made the from_str stuff in flatfile_gol.py a bit more robust.

Here's the benchmarks on a 200x200 random grid:
code:
# modified numpy implementation
$ python -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 44.3 msec per loop

# my code on pypy
$ pypy -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 31.9 msec per loop

# my code on cpython
$ python -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 448 msec per loop
1000x1000 grid:
code:
# modified numpy implementation
$ python -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 1.14 sec per loop

# my code on pypy
$ pypy -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 795 msec per loop

# my code on cpython
$ python -m timeit "import flatfile_gol; f = open('game.txt', 'r'); grid = flatfile_gol.grid_from_str(f.read())" "grid.tick()"
10 loops, best of 3: 11.1 sec per loop
The straight python implementation w/ pypy seems to be the fastest by ~40% but the numpy implementation works with the pygame frontend.

I was going to try to get it to compile with numba but wow, llvmpy is a pain in the dick to install.

Dren fucked around with this message at 19:13 on Oct 1, 2013

nonathlon
Jul 9, 2004
And yet, somehow, now it's my fault ...

Lysidas posted:

I've been using Biopython with 3.x for about two years, both 3.2 and 3.3. I keep a clone of their Git repository and just updated my local installation to release 162. setup.py build used to say something like "Python 3 support is still experimental" before it ran 2to3, but that message seems to have disappeared so maybe it's considered production-ready now.

I've never had any problems with it on Python 3, but I've probably only used a third of the functionality that the package provides.

Excellent - I couldn't find anything explicitly saying it was okay and biopython is missing from a lot of the "works with 3" lists, so I assumed the news was bad.

Another question: pythonbrew seems to have been recently abandoned. Which was a pity, because it worked well. Pyenv is suggested as a replacement, but pyenv suggests you install it via homebrew which complains about the packages you installed using macports ... Since pythonbrew worked, I'll probably just install it. But has anyone else been through this process recently?

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
The Game of Life occurs on an infinite plane, so given that you don't have enough memory to keep the whole thing in memory, how do you get around that limitation? I appreciate that there are other ways to manage things than a simple two-dimensional array of on/off values, for example you could instead have a list of cells that are "on", but (1) the number of cells that are "on" can still grow without bound, (2) your implementation is still incomplete on some level if it doesn't support an arbitrary, potentially infinite set of "on" cells in the initial state.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
You don't play it on an infinite plane. Or you make it wrap.

Dren
Jan 5, 2001

Pillbug
Who cares how you would play it on an infinite plane? On an infinite plane it would take infinitely long to process an iteration of the game and ain't nobody got infinity time for a game of life iteration to compute.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Dren posted:

Who cares how you would play it on an infinite plane? On an infinite plane it would take infinitely long to process an iteration of the game and ain't nobody got infinity time for a game of life iteration to compute.

Well, everybody was baldly stating that they were implementing "the game of life". They didn't state that they were implementing variants of the game of life that don't take place on an infinite plane. I was curious.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Use a defaultdict with keys that are tuples holding coordinates and values of True/False or 1/0 to represent the board. Yeah, that runs out of memory or overflows (built-in wrapping!) at some point in reality, but on magic infinite hardware it works.

E: to limit memory you could, say decrement every empty cell on a tick and delete the ones under some threshold, but you can probably make a initial board that grows to consume all memory if you try. You need magical hardware, basically.

Munkeymon fucked around with this message at 20:28 on Oct 1, 2013

peepsalot
Apr 24, 2007

        PEEP THIS...
           BITCH!

Dren posted:

Who cares how you would play it on an infinite plane? On an infinite plane it would take infinitely long to process an iteration of the game and ain't nobody got infinity time for a game of life iteration to compute.
It is possible to populate an infinite plane with a finite number of "living" cells.

Vulture Culture
Jul 14, 2003

I was never enjoying it. I only eat it for the nutrients.

Hammerite posted:

The Game of Life occurs on an infinite plane, so given that you don't have enough memory to keep the whole thing in memory, how do you get around that limitation? I appreciate that there are other ways to manage things than a simple two-dimensional array of on/off values, for example you could instead have a list of cells that are "on", but (1) the number of cells that are "on" can still grow without bound, (2) your implementation is still incomplete on some level if it doesn't support an arbitrary, potentially infinite set of "on" cells in the initial state.
You're possibly looking at a sparse matrix, which is the data structure typically used to implement spreadsheets. Since your growth is unbounded, though, this will eventually consume all the memory in your system beyond a certain number of iterations.

Vulture Culture fucked around with this message at 20:20 on Oct 1, 2013

Malcolm XML
Aug 8, 2009

I always knew it would end like this.

Misogynist posted:

You're possibly looking at a sparse matrix, which is the data structure typically used to implement spreadsheets. Since your growth is unbounded, though, this will eventually consume all the memory in your system beyond a certain number of iterations.

A certain number is astronomically large if you use good algorithms like HashLife (see Golly)

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
I've got a form that allows somebody to upload a CSV file, and then I want to read it and display it back to them so they can enter some additional information about what is in each column. What sorts of things do I need to be concerned about for validating the file and displaying it back to them? I was looking at csvvalidator but it seems to be more geared to already knowing the structure of the CSV, which I will not know. Also looked at python-magic but the first random CSV I tried it on came back as assembler source, UTF-8 Unicode text, so that didn't seem like the way to go. So should I just not do any validation before loading it up with unicodecsv? I was just gonna make the assumption that it's UTF-8 encoded, reliably detecting the encoding seems like a big pain in the rear end.

Dren
Jan 5, 2001

Pillbug
What things do you want to validate?

As far as UTF-8 checking goes, you can check if something is valid UTF-8 but that doesn't tell you if it's gobbledy-gook or not.

FoiledAgain
May 6, 2007

I just moved over to Python 3 and all my stuff is working, except that the interactive mode in PyScripter is broken. I can't access things inside of list comprehensions when debugging:

code:
[Dbg]>>> limit
.5
[Dbg]>>>
[Dbg]>>> [token for token in self.feature_space['voc'] if token.value > limit]
Traceback (most recent call last):
  File "<string>", line 293, in runcode
  File "<interactive input>", line 1, in <module>
  File "<interactive input>", line 1, in <listcomp>
NameError: global name 'limit' is not defined
Debugging Aborted
>>> limit = 5
>>> [n for n in range(10) if n > limit]
[6,7,8,9]
Does anyone else here use PyScripter? What is that weird <listcomp> thing?

salisbury shake
Dec 27, 2011

Dren posted:

pypy words

I just quickly threw together a pyglet script while at work. You can import pyglet from pypy. I've never used pyglet before so beware, but this works and flies w/ pypy.
https://gist.github.com/thismachinechills/6785816

edit: im almost positive the x/y axes are all hosed
edit edit: theres a distinct lack of these guys: https://upload.wikimedia.org/wikipedia/commons/9/95/Game_of_life_blinker.gif in the pyglet version, where the pygame one generates all the oscillators. Just looking at the table on wikipedia, it seems pyglet version lacks all period 2 oscillators. I'm all GoL'd out to care though. it's probably the increased framerate
also import numpypy :)

salisbury shake fucked around with this message at 02:20 on Oct 2, 2013

Dren
Jan 5, 2001

Pillbug

salisbury shake posted:

I just quickly threw together a pyglet script while at work. You can import pyglet from pypy. I've never used pyglet before so beware, but this works and flies w/ pypy.
https://gist.github.com/thismachinechills/6785816

edit: im almost positive the x/y axes are all hosed

Your thrown together pyglet implementation seems to run much nicer than your thrown together pygame one, pypy aside. Plus, it's easy to play with the colors in pyglet. Nice!

It might be interesting to extend the display to render text in a chosen font as the starting point for the game. Or to have cells with different colors where the colors combine from the surrounding cells when new cells are born.

Dunno what you mean about the x/y axes being broken. Your x/y maps perfectly into my row/col.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Dren posted:

What things do you want to validate?

As far as UTF-8 checking goes, you can check if something is valid UTF-8 but that doesn't tell you if it's gobbledy-gook or not.

I dunno, I'm always paranoid about anything user supplied, and trying to prevent them from causing any harm. I suppose all I can do in this case is make sure I can read the whole file with UTF-8 encoding, and let them know if there was a problem.

tzec
Oct 6, 2003

HAMMERTIME!
Always late to the GoL party.

code:
from collections import Counter

def life(pattern, generations=1):
    """Take a Life pattern in standard ASCII format, with * for cell on, non-* for cell off, 
    newlines to separate rows. Returns a string in the same format after applying 
    the Game of Life rule 'generations' times."""
    
    kernel = (-1,0,1)    # Moore neighbourhood is a separable kernel

    # convert ASCII format to set of x,y cells
    cells = {(y,x) for y,line in enumerate(pattern.splitlines()) for x,v in enumerate(line) if v=='*'}
        
    for generation in range(generations):
        # count each neighbour in 3x3 grid
        neighbours = Counter([(y+i,x+j) for y,x in cells for i in kernel for j in kernel])
        # we've counted the centre cell itself each time, so B3/S23 rule becomes B3/S34
        cells = {l for l in neighbours if neighbours[l]==3 or (neighbours[l]==4 and l in cells)}            
        
    # convert back to ASCII
    cells = sorted(cells)
    mx, y = min(c[1] for c in cells), cells[0][0]
    x = mx
    result = []    
    for j,i in cells:               
        # new row started
        if j!=y:
            result += ['\n' * (j-y)]
            x,y = mx,j            
        # line up x position and emit a live cell
        result += [' ' * (i-x)] + ['*']                
        x = i + 1        
    # join the string together
    return ''.join(result) 
code:
print life("""
 **
 **              
 
     ***
     *   
      *
 """,4)

Dren
Jan 5, 2001

Pillbug
Nice. You only have to process the currently alive cells and the gameboard can grow until it is limited by memory. I think you win until someone implements your approach with a gpu accelerated convolution. Using enumerate() to get indices for the string is a nice trick, too.

SurgicalOntologist
Jun 17, 2004

Are there any free, preferably open-source libraries similar to the proprietary Vizard? It's a virtual reality library, where you can (e.g.) create objects from 3D models, then link a camera object to an external input (e.g., motion tracker) to let the user explore a virtual space. It's very simple to use, but also very expensive (I'd be looking at $4k for a single-use academic license).

SurgicalOntologist fucked around with this message at 19:00 on Oct 2, 2013

sharktamer
Oct 30, 2011

Shark tamer ridiculous
While we're posting python implementations of games, here's the Countdown numbers round game I started yesterday evening. It's the first real application I've written in python outside of work.

https://github.com/sharktamer/numbersround.py

It has almost all the rules implemented. One I've thought of just now that I know I missed is not being able to use anything other than integers in your solution, but I haven't thought of how I would implement that. It works perfectly for all cases I have tried. If you lot could try it, break it and poo poo all over the rubbish code, that would be great. If any suggested changes were made as pull requests, that would be cool, just because I haven't seen that done before.

Also, some kind of countdown that would interrupt the user if they haven't answered would be nice, but I have no idea how I'd do that in python given its concurrency issues.

sharktamer fucked around with this message at 22:46 on Oct 2, 2013

Adbot
ADBOT LOVES YOU

more like dICK
Feb 15, 2010

This is inevitable.
I did a Words and Numbers Countdown game in Java for an Android app. If you're looking to expand your app, try implementing a "Rachel Riley" to explain the solution if the player misses it.

  • Locked thread