<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9318222</id><updated>2012-01-20T12:29:13.019-08:00</updated><title type='text'>Connelly - Technical</title><subtitle type='html'>Public domain code.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>43</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9318222.post-6712509486579415852</id><published>2009-07-07T02:27:00.000-07:00</published><updated>2009-07-07T02:35:17.156-07:00</updated><title type='text'>Allegro 'libgif' animation library</title><content type='html'>From 2001, an Allegro library for loading GIF animations as a BITMAP pointer that automatically animates (due to an installed timer callback routine).  Simplifies animation to the point of:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;BITMAP *bmp = load_gif(filename, 0);&lt;br /&gt;...&lt;br /&gt;draw_sprite(screen, bmp, x, y);    /* BITMAP automatically changes with time. */&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/c/animate-0.2.zip"&gt;Source&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;The original code is by Paul Bartrum.  My changes are in the public domain.  Thanks to Marco Antônio for helping me find my own code...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-6712509486579415852?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/6712509486579415852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=6712509486579415852' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/6712509486579415852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/6712509486579415852'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2009/07/allegro-libgif-animation-library.html' title='Allegro &apos;libgif&apos; animation library'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-7660279209121331058</id><published>2008-07-23T14:59:00.000-07:00</published><updated>2008-07-23T15:15:14.616-07:00</updated><title type='text'>forkmap, threadmap</title><content type='html'>I have an 8 core machine, so vanilla Python increasingly annoys me by running roughly 200*8 times slower than optimized C code (I use OpenMP), rather than 200 times slower than C.&lt;br /&gt;&lt;br /&gt;To use more cores, I occasionally use these parallel map functions in Python:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.connellybarnes.com/code/python/threadmap"&gt;threadmap&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.connellybarnes.com/code/python/forkmap"&gt;forkmap&lt;/a&gt;&lt;br /&gt;&lt;/ul&gt;&lt;code&gt;threadmap&lt;/code&gt; spawns a number of threads equal to the number of cores, and distributes work across threads.  &lt;code&gt;forkmap&lt;/code&gt; requires Cygwin, Mac, or Unix, and does the same thing with fork() and pipe(), basically to get around GIL restrictions in regular Python.  Probably a better solution is to use a Python implementation such as IronPython which doesn't have the GIL, but the FFIs for CPython libraries seem spotty in these other Python implementations.&lt;br /&gt;&lt;br /&gt;Merely using parallel map() functions is rather limiting; OpenMP-style syntax should probably be added to Python at some point, after the GIL is removed.  (As the number of processor cores goes to infinity, either the GIL will be removed or Python will become irrelevant, as languages with similar syntax and fine-grain locking will take over.)&lt;br /&gt;&lt;br /&gt;There are &lt;a href="http://wiki.python.org/moin/ParallelProcessing"&gt;libraries&lt;/a&gt; which implement parallelism by using spawn() instead of fork() to get Windows compatibility without Cygwin, but I couldn't figure out how exactly these libraries were spawning new copies of my code, so due to lack of documentation on this point I used other solutions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-7660279209121331058?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/7660279209121331058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=7660279209121331058' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/7660279209121331058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/7660279209121331058'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2008/07/forkmap-threadmap.html' title='forkmap, threadmap'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-8211166668249842504</id><published>2008-03-15T19:14:00.001-07:00</published><updated>2008-03-18T13:07:09.586-07:00</updated><title type='text'>C++ foreach</title><content type='html'>I can never remember the C++ for-each loop syntax.  Thus, a helper macro I use:&lt;br /&gt;&lt;ul&gt;&lt;code&gt;#define for_each(type, it, L) for (type::iterator (it) = (L).begin(); (it) != (L).end(); ++(it))&lt;/code&gt;&lt;/ul&gt;If L has type T, usage is:&lt;ul&gt;&lt;pre&gt;for_each(T, it, L) {&lt;br /&gt;  printf("%d\n", (*it));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;If you're only using gcc, one can use __typeof__ &lt;a href="http://anthony.liekens.net/index.php/Computers/CppForeach"&gt;[1]&lt;/a&gt; to simplify this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-8211166668249842504?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/8211166668249842504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=8211166668249842504' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/8211166668249842504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/8211166668249842504'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2008/03/c-foreach.html' title='C++ foreach'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-3989230376278660987</id><published>2007-11-04T09:28:00.000-08:00</published><updated>2007-11-04T15:29:38.878-08:00</updated><title type='text'>RK45 in Python</title><content type='html'>Runge-Kutta 4th and 5th order adaptive ODE integrator.  Generally the &lt;a href="http://www.scipy.org/"&gt;scipy&lt;/a&gt; integrators will be easier to use, unless you specifically need RK45.&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/python/rk45"&gt;Code&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-3989230376278660987?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/3989230376278660987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=3989230376278660987' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/3989230376278660987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/3989230376278660987'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/11/rk45-in-python.html' title='RK45 in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-8458717374579537910</id><published>2007-09-12T21:53:00.000-07:00</published><updated>2007-12-21T15:25:41.933-08:00</updated><title type='text'>Filter numpy images with FFT, Python</title><content type='html'>Generic linear filter support is not currently built into the Python Imaging Library.  This module lets you filter a numpy array against an arbitrary kernel:&lt;ul&gt;&lt;code&gt;&gt;&gt;&gt; I = numpy.asarray(Image.open('test.jpg'))&lt;br /&gt;&gt;&gt;&gt; I = filter(I, [[-1,0,1],[-2,0,2],[-1,0,1]])/8+128&lt;br /&gt;&gt;&gt;&gt; Image.fromarray(numpy.uint8(I)).show()&lt;br /&gt;&lt;/ul&gt;&lt;/code&gt;The Fast Fourier Transform (FFT) is used.  The FFT routine included with numpy isn't particularly fast (c.f. FFTW &lt;a href="http://www.fftw.org/"&gt;[1]&lt;/a&gt;), and in any case using the transform isn't as efficient as applying the filter naively for small filter sizes.  Also, for separable kernels (e.g. the Gaussian kernel), it is often faster to perform two 1D convolutions in sequence.  However, for large images and filters, using an FFT for convolution is often faster than other approaches.  (If an image and filter contain a total of N pixels, then this algorithm takes O(&lt;i&gt;N&lt;/i&gt;log&lt;i&gt;N&lt;/i&gt;) time, which is the fastest known time complexity algorithm for the general problem.)  Public domain.&lt;br /&gt;&lt;br /&gt;Update: A number of image filtering operations are provided in &lt;code&gt;numarray&lt;/code&gt; (in the module &lt;code&gt;numpy.numarray.nd_image&lt;/code&gt;), such as filtering, image morphology, distance transforms, and segmentation; see &lt;a href="http://structure.usc.edu/numarray/module-numarray.ndimage.html"&gt;[2]&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/python/filterfft"&gt;Source&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-8458717374579537910?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/8458717374579537910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=8458717374579537910' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/8458717374579537910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/8458717374579537910'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/09/filter-numpy-images-with-fft-python.html' title='Filter numpy images with FFT, Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-8965514771579271491</id><published>2007-06-04T15:51:00.000-07:00</published><updated>2007-06-04T19:26:24.685-07:00</updated><title type='text'>framecap - Capture camera input with Allegro, C++</title><content type='html'>Requires OpenCV, Allegro, and pthreads.  Captures frames from a webcam.  Usage:&lt;ul&gt;&lt;pre&gt;CAPTURE *cap = create_capture();&lt;br /&gt;BITMAP *bmp = capture_frame(cap);&lt;/pre&gt;&lt;/ul&gt;Use &lt;code&gt;capture_frame_nb&lt;/code&gt; to capture a frame in nonblocking mode (a NULL pointer is returned if no frame is available).  Should work on Mac OS X, Linux, Windows; only tested on Windows.&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/c/framecap-0.2.0.zip"&gt;Source&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-8965514771579271491?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/8965514771579271491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=8965514771579271491' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/8965514771579271491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/8965514771579271491'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/06/framecap-capture-camera-input-with.html' title='framecap - Capture camera input with Allegro, C++'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-5945491510199770754</id><published>2007-04-30T18:44:00.000-07:00</published><updated>2007-05-04T14:03:51.047-07:00</updated><title type='text'>pfm - Read/write 1 and 3 channel PFM files</title><content type='html'>PFM files are &lt;i&gt;m&lt;/i&gt;x&lt;i&gt;n&lt;/i&gt;x1 or &lt;i&gt;m&lt;/i&gt;x&lt;i&gt;n&lt;/i&gt;x3 arrays of floats.  C++ code to read/write the format (public domain).&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/c/pfm-1.0.0.zip"&gt;Source&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-5945491510199770754?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/5945491510199770754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=5945491510199770754' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/5945491510199770754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/5945491510199770754'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/04/pfm-readwrite-1-and-3-channel-pfm-files.html' title='pfm - Read/write 1 and 3 channel PFM files'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-1901540739500094334</id><published>2007-04-04T16:37:00.000-07:00</published><updated>2007-04-10T18:47:31.360-07:00</updated><title type='text'>OpenCV camera and AVI input</title><content type='html'>To convert a video to a format that OpenCV can read:&lt;br /&gt;&lt;pre&gt;  $ mencoder in.avi -ovc raw -vf format=i420 -o out.avi&lt;/pre&gt;This is necessary because OpenCV uses platform specific video libraries, and the intersection of their supported formats is DIB/I420/IYUV.  To capture input from a camera or an AVI file, use the following C++ code: &lt;a href="http://www.connellybarnes.com/code/c/opencv_input.cpp"&gt;[1]&lt;/a&gt;.  To capture frames in a nonblocking manner in Python, use: &lt;a href="http://www.connellybarnes.com/code/python/nonblocking_showcam.zip"&gt;[2]&lt;/a&gt; with Gary Bishop's &lt;code&gt;cvtypes&lt;/code&gt; &lt;a href="http://wwwx.cs.unc.edu/~gb/wp/blog/2007/02/04/python-opencv-wrapper-using-ctypes/"&gt;[3]&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-1901540739500094334?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/1901540739500094334/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=1901540739500094334' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/1901540739500094334'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/1901540739500094334'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/04/opencv-camera-and-avi-input.html' title='OpenCV camera and AVI input'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-8311189641778545942</id><published>2007-04-03T11:24:00.000-07:00</published><updated>2007-09-13T05:23:29.321-07:00</updated><title type='text'>Burrows-Wheeler transform in Python</title><content type='html'>&lt;pre&gt;def bwt(s):&lt;br /&gt;  s = s + '\0'&lt;br /&gt;  return ''.join([x[-1] for x in&lt;br /&gt;         sorted([s[i:] + s[:i] for i in range(len(s))])])&lt;br /&gt;&lt;br /&gt;def ibwt(s):&lt;br /&gt;  L = [''] * len(s)&lt;br /&gt;  for i in range(len(s)):&lt;br /&gt;    L = sorted([s[i] + L[i] for i in range(len(s))])&lt;br /&gt;  return [x for x in L if x.endswith('\0')][0][:-1]&lt;/pre&gt;The Burrows-Wheeler transform &lt;a href="http://en.wikipedia.org/wiki/Burrows-Wheeler_transform"&gt;[1]&lt;/a&gt; is an invertible mathematical transformation which tends to clump related sequences of data together; hence it is useful as a pre-pass for some compression algorithms.  The BWT domain in the above code excludes the null character; to include the null character, modify the transformation to also output the row of &lt;code&gt;sorted([s[i:] + s[:i]...])&lt;/code&gt; on which &lt;code&gt;s&lt;/code&gt; occurs, then in IBWT simply return this row after the for loop.  The Python code above is not particularly fast.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-8311189641778545942?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/8311189641778545942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=8311189641778545942' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/8311189641778545942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/8311189641778545942'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/04/burrows-wheeler-transform-in-python.html' title='Burrows-Wheeler transform in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-7268865066616559766</id><published>2007-04-01T17:12:00.000-07:00</published><updated>2007-04-01T17:13:16.054-07:00</updated><title type='text'>How to put a video on the Web</title><content type='html'>Install FFMPEG &lt;a href="http://ffdshow.faireal.net/mirror/ffmpeg/"&gt;[1]&lt;/a&gt;, use &lt;code&gt;ffmpeg -i in.avi out.swf&lt;/code&gt;, then place &lt;code&gt;&amp;lt;embed src="out.swf" width="400" height="300" loop="false" quality="high"&amp;gt;&amp;lt;/embed&amp;gt;&lt;/code&gt; in your HTML.  Optionally, use the &lt;code&gt;-s&lt;/code&gt; argument after &lt;code&gt;-i&lt;/code&gt; in FFMPEG to change the resolution.  If you want playback controls, output to a &lt;code&gt;.flv&lt;/code&gt; file instead, download FlowPlayer &lt;a href="http://flowplayer.sourceforge.net/"&gt;[1]&lt;/a&gt;, and modify their example HTML to point to your &lt;code&gt;.flv&lt;/code&gt; video.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-7268865066616559766?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/7268865066616559766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=7268865066616559766' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/7268865066616559766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/7268865066616559766'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/04/how-to-put-video-on-web_01.html' title='How to put a video on the Web'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-117173354715779799</id><published>2007-02-17T09:24:00.000-08:00</published><updated>2007-02-19T02:30:38.506-08:00</updated><title type='text'>Ubuntu Linux postinstall notes</title><content type='html'>After installing an operating system, there are always a zillion changes I have to make to get the operating system &lt;i&gt;operational&lt;/i&gt;.  I'm new to Linux, so I thought I'd post up a list of changes I made after installing Ubuntu to help out others.  These are mostly basic changes such as enabling all software packages, choosing a fast repository, mounting FAT32 drives, making Ctrl+Alt+Del bring up a task manager, installing multimedia software, changing the system DPI, trying to disable the trash feature, and adding an Open Terminal option to the desktop.&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/documents/linux_postinstall_notes.txt"&gt;Document&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-117173354715779799?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/117173354715779799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=117173354715779799' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/117173354715779799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/117173354715779799'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/02/ubuntu-linux-postinstall-notes.html' title='Ubuntu Linux postinstall notes'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-117107277565502454</id><published>2007-02-09T17:56:00.000-08:00</published><updated>2007-02-09T18:07:08.243-08:00</updated><title type='text'>Eigenvectors of 3x3 symmetric matrix</title><content type='html'>A C++ source and header file to compute eigenvectors/values of a 3x3 symmetric matrix.  Potentially easier than installing EISPACK, LAPACK, or Gandalf if you only need this single function.  Takes about 6000 clock cycles per call on my Pentium 4.  Public domain.  &lt;a href="http://www.connellybarnes.com/code/c/eig3-1.0.0.zip"&gt;[1]&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-117107277565502454?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/117107277565502454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=117107277565502454' title='20 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/117107277565502454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/117107277565502454'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2007/02/eigenvectors-of-3x3-symmetric-matrix.html' title='Eigenvectors of 3x3 symmetric matrix'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-116091522851503992</id><published>2006-10-15T05:08:00.000-07:00</published><updated>2008-10-27T15:00:11.767-07:00</updated><title type='text'>Incremental flash backup tool</title><content type='html'>I recently decided that I would back up my documents to a high capacity flash disk.  Thus I wrote a backup tool.&lt;br /&gt;Features:&lt;ul&gt;&lt;li&gt;Dead simple.  Something you'd write in an hour, so it won't mess you up by having volumes of code, weird interfaces, complicated man pages, or obscure back up formats.&lt;br /&gt;&lt;li&gt;The flash disk is a mirrored filesystem, so no special tools are required to read the backup.&lt;br /&gt;&lt;li&gt;The existing backed-up filesystem is updated if the backup command is re-issued.&lt;br /&gt;&lt;li&gt;Specified directories are recursively copied; hidden files are not copied.  Thus one can flag large files that should not be backed up: make them hidden.&lt;br /&gt;&lt;li&gt;Eventually needs support for checksums, but I'm not too worried at the moment.&lt;br /&gt;&lt;/ul&gt;The program is public domain.  Download and run it.  Copy its example backup command line into a shell script.  In my case, I use something similar to:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;% python backup.py D:\ D:\Documents D:\Code G:\Backup&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/python/backup"&gt;Source Code&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-116091522851503992?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/116091522851503992/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=116091522851503992' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/116091522851503992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/116091522851503992'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2006/10/incremental-flash-backup-tool.html' title='Incremental flash backup tool'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-115485897254525103</id><published>2006-08-06T02:35:00.000-07:00</published><updated>2008-10-27T14:59:15.505-07:00</updated><title type='text'>Intelligent Minesweeper</title><content type='html'>A game of Minesweeper, with moves suggested by the &lt;code&gt;entail&lt;/code&gt; module I posted earlier.  The &lt;code&gt;entail&lt;/code&gt; module contains a propositional logic inference algorithm: it lets one determine whether any given expression of binary variables follows logically from a set of assumptions:&lt;br /&gt;&lt;ul&gt;&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; s = AssumptionSet(['a =&gt; b =&gt; c &lt;=&gt; a'])&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; s.implies('a &lt;=&gt; b')&lt;br /&gt;True&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; s.assume('c')&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; s.implies('a')&lt;br /&gt;True&lt;br /&gt;&lt;/pre&gt;&lt;/ul&gt;It is rather uncanny how complicated mathematical relationships can be derived &lt;i&gt;ex nihilo&lt;/i&gt; using only the &lt;code&gt;entail&lt;/code&gt; module.  For the Minesweeper game, when the user chooses "Suggest Move," I add only the knowledge that the player possesses to an &lt;code&gt;AssumptionSet&lt;/code&gt;, and then suggest a move if the logic algorithm can deduce that any given square is free of a mine.  The result is a perfect deterministic minesweeper AI: if any given move on the board can be made safely, then the AI will suggest that square.  If no move can be made safely, then no suggestion will be made.  Note that this is also an experiment with using HTML widgets in lieu of using a widget toolkit such as wxPython, so bear with the strange appearance of the window.&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/python/mine-screen.png"&gt;Screenshot&lt;/a&gt;) (&lt;a href="http://www.connellybarnes.com/code/python/mine-exe.zip"&gt;EXE&lt;/a&gt;) (&lt;a href="http://www.connellybarnes.com/code/python/mine-src.zip"&gt;Source&lt;/a&gt;) (&lt;a href="http://www.connellybarnes.com/code/python/entail"&gt;Module entail&lt;/a&gt;) (All public domain).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-115485897254525103?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/115485897254525103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=115485897254525103' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/115485897254525103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/115485897254525103'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2006/08/intelligent-minesweeper.html' title='Intelligent Minesweeper'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-115044560079593848</id><published>2006-06-16T01:03:00.000-07:00</published><updated>2008-10-27T14:57:46.801-07:00</updated><title type='text'>Real-time hair animation</title><content type='html'>I used the Verlet integration and relaxation method described by Thomas Jakobsen in "Advanced Character Physics" &lt;a href="http://www.teknikus.dk/tj/gdc2001.htm"&gt;[1]&lt;/a&gt; coupled with the animation techniques suggested by Chang, Jin, and Yu in &lt;a href="http://www-sal.cs.uiuc.edu/~yyz/research/hair/"&gt;[2]&lt;/a&gt; to make a fast hair simulation.  My resulting video &lt;a href="http://www.princeton.edu/~csbarnes/documents/hair/connelly_hair_movie.avi"&gt;[3]&lt;/a&gt; was captured in real-time.  The program can actually be sped up significantly by placing bounding boxes around individual quads, vertices, and segments; however, I ran into bugs when I tried to do this, so I left that optimization out for now.  The results are interesting because they indicate that in video games, hair can be animated in real-time with relative ease.  The source code has been placed in the public domain.&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/documents/hair/connelly_hair_movie.avi"&gt;Video&lt;/a&gt;) (&lt;a href="http://www.connellybarnes.com/documents/hair/"&gt;Writeup&lt;/a&gt;) (&lt;a href="http://www.connellybarnes.com/documents/hair/connelly_source.zip"&gt;Source Code&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-115044560079593848?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/115044560079593848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=115044560079593848' title='29 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/115044560079593848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/115044560079593848'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2006/06/real-time-hair-animation.html' title='Real-time hair animation'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>29</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-115001100299213738</id><published>2006-06-10T21:48:00.000-07:00</published><updated>2008-10-27T14:56:56.064-07:00</updated><title type='text'>Automatic Python imports with autoimp</title><content type='html'>I got sick of writing "&lt;code&gt;import X&lt;/code&gt;" in Python.  So, I created the public domain module &lt;code&gt;autoimp&lt;/code&gt;, which imports all modules automatically:&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; from autoimp import *&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; os.stat('.')&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; Image.open('test.bmp')&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; pylab.plot([1,2],[3,4])&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; scipy.linalg.eig([[1,2],[3,4]])&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; ...&lt;/pre&gt;Thus one no longer needs to write "&lt;code&gt;import X&lt;/code&gt;".  It would take too long to load every module when one writes "&lt;code&gt;from autoimp import *&lt;/code&gt;", so the imported modules are actually proxy objects which lazily load when they are first used.&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/autoimp/"&gt;Module Website&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-115001100299213738?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/115001100299213738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=115001100299213738' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/115001100299213738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/115001100299213738'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2006/06/automatic-python-imports-with-autoimp.html' title='Automatic Python imports with autoimp'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-114800235065827985</id><published>2006-05-18T17:26:00.000-07:00</published><updated>2008-10-27T14:56:12.148-07:00</updated><title type='text'>Programming Language Productivity</title><content type='html'>Norvig &lt;a href="http://www.norvig.com/java-lisp.html"&gt;[1]&lt;/a&gt; commented on two productivity studies by Prechelt &lt;a href="http://page.mi.fu-berlin.de/~prechelt/Biblio/jccpprtTR.pdf"&gt;[2]&lt;/a&gt; and Garret &lt;a href="http://www.flownet.com/gat/papers/lisp-java.pdf"&gt;[3]&lt;/a&gt;.  The results for the productivity of the languages isn't immediately apparent, so I extracted the relevant information as a "productivity summary" &lt;a href="http://www.connellybarnes.com/documents/language_productivity.pdf"&gt;[4]&lt;/a&gt;.  The results strongly indicate that programmers who solve a problem with fewer lines of code are more productive, irrespective of the language used.  Thus languages which are more succinct could be said to be more productive.&lt;br /&gt;&lt;br /&gt;For entertainment purposes, I solved the given problem in Python; it took me 1 hour 10 minutes, with 31 lines of code.  I spent 10 minutes reading the problem, and 40 minutes fixing mistakes that I had made due to not reading the problem carefully enough.  There is a lesson here...&lt;br /&gt;&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/documents/language_productivity.pdf"&gt;Productivity Summary&lt;/a&gt;)  (&lt;a href="http://www.connellybarnes.com/code/python/prechelt"&gt;My Solution&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-114800235065827985?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/114800235065827985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=114800235065827985' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/114800235065827985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/114800235065827985'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2006/05/programming-language-productivity.html' title='Programming Language Productivity'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-114730622631808477</id><published>2006-05-10T17:06:00.000-07:00</published><updated>2008-10-27T14:55:27.880-07:00</updated><title type='text'>Eight queens in Python</title><content type='html'>An elegant way to find all solutions to the 8-queens problem: generate all 8-castles solutions by a permutations() generator and filter the diagonals by checking that the set of diagonals represented has 8 elements.  I implemented this algorithm in Python (17 lines) and C++ (66 lines).&lt;br /&gt;(&lt;a href="http://www.connellybarnes.com/code/python/queens"&gt;Python Code&lt;/a&gt;) (&lt;a href="http://www.connellybarnes.com/code/python/queens.cpp"&gt;C++ Code&lt;/a&gt;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-114730622631808477?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/114730622631808477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=114730622631808477' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/114730622631808477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/114730622631808477'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2006/05/eight-queens-in-python.html' title='Eight queens in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-114627440828332151</id><published>2006-04-28T18:27:00.000-07:00</published><updated>2008-10-27T14:54:43.280-07:00</updated><title type='text'>Shedskin benchmarks</title><content type='html'>Shedskin &lt;a href="http://sourceforge.net/projects/shedskin/"&gt;[1]&lt;/a&gt; is an experimental Python to C++ compiler.  I benchmarked it for some of the microbenchmarks in The Computer Language Shootout &lt;a href="http://shootout.alioth.debian.org/"&gt;[2]&lt;/a&gt;.  The results are interesting: for some benchmarks, the compiled Python code runs at nearly the speed of C.&lt;br /&gt;(These benchmarks are out of date, so I removed the link).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-114627440828332151?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/114627440828332151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=114627440828332151' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/114627440828332151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/114627440828332151'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2006/04/shedskin-benchmarks.html' title='Shedskin benchmarks'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113801420486687453</id><published>2006-01-23T02:52:00.000-08:00</published><updated>2007-11-19T03:02:36.858-08:00</updated><title type='text'>rencode -- Reduced length encodings</title><content type='html'>A space-efficient Python serialization module based on bencode,&lt;br /&gt;which can be used to decode strings from untrusted sources.  Works well for complex, heterogeneous data structures with many small elements.  The encodings take considerably less space than bencode, gherkin, and Recipe 415503 &lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/415503"&gt;[1]&lt;/a&gt; for that use case, and this module is faster, too.  (&lt;a href="http://www.connellybarnes.com/code/python/rencode"&gt;Source code&lt;/a&gt;), (&lt;a href="http://www.connellybarnes.com/code/python/rencode_compare.txt"&gt;Comparison&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113801420486687453?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113801420486687453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113801420486687453' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113801420486687453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113801420486687453'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2006/01/rencode-reduced-length-encodings.html' title='rencode -- Reduced length encodings'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113480751080995614</id><published>2005-12-17T00:15:00.000-08:00</published><updated>2008-10-27T14:47:41.726-07:00</updated><title type='text'>Allegro Quick Reference in Japanese</title><content type='html'>The Allegro Quick Reference guide that I wrote in 2002 &lt;a href="http://www.connellybarnes.com/documents/quick_reference.html"&gt;[1]&lt;/a&gt; has been translated into Japanese &lt;a href="http://www.ayu.ics.keio.ac.jp/~osawa/allegro/reference.html"&gt;[2]&lt;/a&gt; by Ohsawa Hirotaka.  Cool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113480751080995614?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113480751080995614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113480751080995614' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113480751080995614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113480751080995614'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/12/allegro-quick-reference-in-japanese.html' title='Allegro Quick Reference in Japanese'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113480553461464942</id><published>2005-12-16T23:43:00.000-08:00</published><updated>2008-10-27T13:41:45.125-07:00</updated><title type='text'>Search the Web in Python</title><content type='html'>Query 6 search engines in Python.  (&lt;a href="http://www.connellybarnes.com/code/web_search/"&gt;Module website&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113480553461464942?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113480553461464942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113480553461464942' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113480553461464942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113480553461464942'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/12/search-web-in-python.html' title='Search the Web in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113399595854748619</id><published>2005-12-07T14:41:00.000-08:00</published><updated>2008-10-27T13:40:08.895-07:00</updated><title type='text'>MPI matrix multiplication and inversion</title><content type='html'>MPI matrix multiplication and inversion routines, written for a physics class that I took last year.  The code is modular, and more flexible than the matrix multiplication codes I found on the Web (I couldn't find any simple MPI matrix inversion routines on the Web).  The PDF document is public domain.  (&lt;a href="http://www.connellybarnes.com/documents/ph417_mpi_project.pdf"&gt;Algorithms and Code&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;See also: &lt;a href="http://www.netlib.org/scalapack/"&gt;ScaLAPACK&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113399595854748619?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113399595854748619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113399595854748619' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113399595854748619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113399595854748619'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/12/mpi-matrix-multiplication-and.html' title='MPI matrix multiplication and inversion'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113193362255727394</id><published>2005-11-13T15:07:00.000-08:00</published><updated>2008-10-27T13:39:20.972-07:00</updated><title type='text'>Moore's law</title><content type='html'>For the past 5 years, CPU speeds have been &lt;a href="http://www.connellybarnes.com/documents/cpu_speed.pdf"&gt;increasing roughly linearly&lt;/a&gt;.  That's right, for processor speeds, Moore's law does not currently apply.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113193362255727394?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113193362255727394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113193362255727394' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113193362255727394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113193362255727394'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/11/moores-law.html' title='Moore&apos;s law'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113186340453101548</id><published>2005-11-12T22:03:00.000-08:00</published><updated>2008-10-27T13:38:04.499-07:00</updated><title type='text'>FFT polynomial multiplication</title><content type='html'>It's easier than you might think:&lt;pre&gt;&gt;&gt;&gt; def fft_mul(C1, C2):&lt;br /&gt;...   d = len(C1)+len(C2)-1&lt;br /&gt;...   c1 = FFT.fft(list(C1) + [0] * (d-len(C1)))&lt;br /&gt;...   c2 = FFT.fft(list(C2) + [0] * (d-len(C2)))&lt;br /&gt;...   return list(FFT.inverse_fft(c1*c2)[:d].real)&lt;br /&gt;...&lt;br /&gt;&gt;&gt;&gt; fft_mul([1,2,3],[4,5]) # (1+2*x+3*x**2)*(4+5*x)&lt;br /&gt;[4.0, 13.0, 22.0, 15.0]&lt;/pre&gt;Takes O(&lt;i&gt;n&lt;/i&gt; log&lt;i&gt;n&lt;/i&gt;) time.  The idea is to right pad each polynomial with enough zeros so that the cyclic convolution becomes a noncyclic convolution.  For more speed, pad &lt;code&gt;c1&lt;/code&gt; and &lt;code&gt;c2&lt;/code&gt; so each has power-of-2 length.  (&lt;a href="http://www.connellybarnes.com/code/python/poly_mul"&gt;Source Code&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I posted the algorithm &lt;a href="http://en.wikipedia.org/wiki/Discrete_Fourier_transform#Outline_of_DFT_polynomial_multiplication_algorithm"&gt;[1]&lt;/a&gt; on Wikipedia (alternate link: &lt;a href="http://en.wikipedia.org/w/index.php?title=Discrete_Fourier_transform&amp;oldid=31278814#Outline_of_DFT_polynomial_multiplication_algorithm"&gt;[2]&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113186340453101548?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113186340453101548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113186340453101548' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113186340453101548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113186340453101548'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/11/fft-polynomial-multiplication.html' title='FFT polynomial multiplication'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113133768160981796</id><published>2005-11-06T19:54:00.000-08:00</published><updated>2008-10-27T13:37:06.203-07:00</updated><title type='text'>Trigonometry proved</title><content type='html'>Common trigonometric identities, &lt;a href="http://www.connellybarnes.com/documents/trigonometry.pdf"&gt;proved&lt;/a&gt; in one page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113133768160981796?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113133768160981796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113133768160981796' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113133768160981796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113133768160981796'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/11/trigonometry-proved.html' title='Trigonometry proved'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113132451491080172</id><published>2005-11-06T16:47:00.000-08:00</published><updated>2005-11-06T16:49:16.383-08:00</updated><title type='text'>pysam -- Python I2P SAM library</title><content type='html'>A Python &lt;a href="http://www.i2p.net"&gt;I2P&lt;/a&gt; SAM library, emulates the Python &lt;code&gt;socket&lt;/code&gt; module.  I haven't updated it in a while, but it works.  (&lt;a href="http://dev.i2p.net/contrib/apps/sam/python/index.html"&gt;Main Page&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113132451491080172?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113132451491080172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113132451491080172' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113132451491080172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113132451491080172'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/11/pysam-python-i2p-sam-library.html' title='pysam -- Python I2P SAM library'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113132089742826528</id><published>2005-11-06T15:21:00.000-08:00</published><updated>2005-11-06T16:00:34.873-08:00</updated><title type='text'>Hogwarts Security</title><content type='html'>Wow.  I thought I'd seen it all.  Then I find the world's &lt;a href="http://www.schneier.com/blog/archives/2005/09/hogwarts_securi.html"&gt;most famous cryptographer&lt;/a&gt; talking about security in the sixth Harry Potter book. Yes, I'm talking about Bruce Schneier, author of Applied Cryptography. That made me smile. The guy is also a judge for a proposed &lt;a href="http://tor.eff.org/"&gt;Tor&lt;/a&gt; GUI.  Which makes me wonder: is he now interested in anonymous networks?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113132089742826528?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113132089742826528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113132089742826528' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113132089742826528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113132089742826528'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/11/hogwarts-security.html' title='Hogwarts Security'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113057280684466909</id><published>2005-10-29T00:49:00.000-07:00</published><updated>2008-10-27T13:33:32.074-07:00</updated><title type='text'>Propositional logic in Python</title><content type='html'>Propositional logic inference via compressed truth tables.  Module &lt;code&gt;entail&lt;/code&gt; is presumably slower than your industrial-grade C inference algorithm, but logical statements are given as Python expressions, and entailment can be checked at the interactive prompt.  This makes the module easy to use, and fun.  (&lt;a href="http://www.connellybarnes.com/code/python/entail"&gt;Source Code&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113057280684466909?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113057280684466909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113057280684466909' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113057280684466909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113057280684466909'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/propositional-logic-in-python.html' title='Propositional logic in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-113013660850059947</id><published>2005-10-23T23:04:00.000-07:00</published><updated>2005-10-23T23:50:08.516-07:00</updated><title type='text'>Ventiloquate</title><content type='html'>Hyperventilate + loquacious = ventiloquate, to freak out and speak too much, too fast, and use way more breath than is actually needed to explain the idea. I assumed that this word existed, but I guess it actually doesn't.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-113013660850059947?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/113013660850059947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=113013660850059947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113013660850059947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/113013660850059947'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/ventiloquate.html' title='Ventiloquate'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112932921964943507</id><published>2005-10-14T15:30:00.000-07:00</published><updated>2008-09-03T15:22:45.737-07:00</updated><title type='text'>Basic factorization algorithms</title><content type='html'>A paper which gives pseudocode and the reasoning behind some basic factorization algorithms: Fermat factorization, Pollard rho, Pollard p-1, and Brent's method.  Public domain.  (&lt;a href="http://www.connellybarnes.com/documents/factoring.pdf"&gt;PDF document&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112932921964943507?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112932921964943507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112932921964943507' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112932921964943507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112932921964943507'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/basic-factorization-algorithms.html' title='Basic factorization algorithms'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112882153239733174</id><published>2005-10-08T18:29:00.000-07:00</published><updated>2005-10-08T18:32:12.403-07:00</updated><title type='text'>Memoization with cache clear on return of last function call</title><content type='html'>Memoization is nice, but in dynamic programming, it can eat up ever-increasing amounts of memory as your memoized function is called with various arguments.  A simple solution is to clear the cache when the last function call returns.  (&lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440678"&gt;Python Recipe&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112882153239733174?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112882153239733174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112882153239733174' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112882153239733174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112882153239733174'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/memoization-with-cache-clear-on-return.html' title='Memoization with cache clear on return of last function call'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112865735035279144</id><published>2005-10-06T20:49:00.000-07:00</published><updated>2008-10-27T13:20:08.225-07:00</updated><title type='text'>mw2html -- Export Mediawiki to static, traditional website</title><content type='html'>&lt;code&gt;mw2html&lt;/code&gt; is a Python program which exports a Mediawiki site to a traditional-looking HTML site.  No indices are generated, and Wikipedia sidebars and extra formatting are removed to give a simple, streamlined site (you can substitute in your own sidebars if you wish).  The outputted HTML source code is Monobook-specific and rather verbose at the moment.  But the sites thus exported don't look bad. (&lt;a href="http://www.connellybarnes.com/code/python/mw2html"&gt;Source code&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112865735035279144?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112865735035279144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112865735035279144' title='44 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112865735035279144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112865735035279144'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/mw2html-export-mediawiki-to-static.html' title='mw2html -- Export Mediawiki to static, traditional website'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>44</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112848849202009851</id><published>2005-10-04T21:56:00.000-07:00</published><updated>2008-10-27T13:31:36.818-07:00</updated><title type='text'>List of bits in Python</title><content type='html'>A memory compacted list of bits (uses 1 byte per every 8 elements).  Instantiate from a list or string of bits.  Otherwise behaves just like the builtin Python list class.  Uses the ListMixin class also published on this page.  (&lt;a href="http://www.connellybarnes.com/code/python/bitlist"&gt;Source code&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112848849202009851?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112848849202009851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112848849202009851' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112848849202009851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112848849202009851'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/list-of-bits-in-python.html' title='List of bits in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112831626410732636</id><published>2005-10-02T22:10:00.000-07:00</published><updated>2005-10-02T22:11:04.106-07:00</updated><title type='text'>Why books suck</title><content type='html'>An essay.  Click comments for the text.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112831626410732636?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112831626410732636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112831626410732636' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112831626410732636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112831626410732636'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/why-books-suck_02.html' title='Why books suck'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112830588075601852</id><published>2005-10-02T19:13:00.000-07:00</published><updated>2008-10-27T13:32:22.755-07:00</updated><title type='text'>Timing a function (pytime)</title><content type='html'>Python's timing facilities are...unPythonic.  Module &lt;code&gt;timeit&lt;/code&gt; requires you to specify the number of iterations for the timing loop.  But that number varies according to the speed of the machine you're running on, level of optimization of your code, etc.  It's more Pythonic to calculate the number of iterations in the timing procedure.  As so: (&lt;a href="http://www.connellybarnes.com/code/python/pytime"&gt;Source code&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112830588075601852?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112830588075601852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112830588075601852' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830588075601852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830588075601852'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/timing-function.html' title='Timing a function (pytime)'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112830490249506198</id><published>2005-10-02T19:00:00.000-07:00</published><updated>2008-10-27T13:30:28.606-07:00</updated><title type='text'>Python htmldata module</title><content type='html'>Extract and modify URLs in an HTML/XHTML/CSS document.  Translate HTML/XHTML documents to and from list data structures.  Use cases: robots, proxy CGI scripts, filtering of HTML and CSS, and flexible wget-like mirroring.  (&lt;a href="http://www.connellybarnes.com/code/htmldata/"&gt;Module website&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112830490249506198?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112830490249506198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112830490249506198' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830490249506198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830490249506198'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/python-htmldata-module.html' title='Python htmldata module'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112830474599029279</id><published>2005-10-02T18:50:00.000-07:00</published><updated>2008-10-27T13:31:07.699-07:00</updated><title type='text'>List mixin for Python</title><content type='html'>You can use &lt;code&gt;UserDict.DictMixin&lt;/code&gt; to create custom dictionary classes.  Now you can use &lt;code&gt;listmixin.ListMixin&lt;/code&gt; to create custom list classes.  (&lt;a href="http://www.connellybarnes.com/code/python/listmixin"&gt;Source code&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112830474599029279?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112830474599029279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112830474599029279' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830474599029279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830474599029279'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/list-mixin-for-python.html' title='List mixin for Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112830423802557632</id><published>2005-10-02T18:48:00.000-07:00</published><updated>2005-10-02T18:50:38.026-07:00</updated><title type='text'>Infinity in Python</title><content type='html'>Negative infinity:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; None &lt; -1e308&lt;br /&gt;True&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Positive infinity:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; () &gt; 1e308&lt;br /&gt;True&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112830423802557632?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112830423802557632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112830423802557632' title='25 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830423802557632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830423802557632'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/infinity-in-python.html' title='Infinity in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>25</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112830386156467475</id><published>2005-10-02T18:32:00.000-07:00</published><updated>2005-10-02T19:18:43.553-07:00</updated><title type='text'>Modified Dijkstra's algorithm in Python</title><content type='html'>Algorithm: perform a breadth-first search, always expand the vertex with the smallest cost, and don't remove duplicate vertices in the cost-priority-queue.&lt;br /&gt;&lt;br /&gt;This algorithm turns out to be nearly equivalent to Dijkstra's algorithm.  For &lt;i&gt;n&lt;/i&gt; vertices and &lt;i&gt;m&lt;/i&gt; edges, it requires O(&lt;i&gt;n&lt;/i&gt;+&lt;i&gt;m&lt;/i&gt;) space, O(&lt;i&gt;m&lt;/i&gt;*log(&lt;i&gt;m&lt;/i&gt;)) time, and always finds the shortest path.&lt;br /&gt;&lt;br /&gt;The strategy of not removing duplicate vertices is particularly helpful in Python, where the builtin priority queue class doesn't support the DECREASE-KEY operation.  See my comment at &lt;a href="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/119466"&gt;David Eppstein's&lt;/a&gt; recipe (the comment is public domain).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112830386156467475?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112830386156467475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112830386156467475' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830386156467475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830386156467475'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/modified-dijkstras-algorithm-in-python.html' title='Modified Dijkstra&apos;s algorithm in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-112830307758349490</id><published>2005-10-02T18:26:00.000-07:00</published><updated>2008-10-27T13:28:05.616-07:00</updated><title type='text'>AI algorithms in Python</title><content type='html'>Uninformed search algorithms: breadth-first, depth-first, depth-limited, uniform cost, iterative deepening DFS, and bidirectional (in both tree and graph modes).  (&lt;a href="http://connellybarnes.com/code/python/ai/uninformed_search"&gt;Source code&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Informed search algorithms: greedy best-first, beam, A* (in both tree and graph modes).  (&lt;a href="http://connellybarnes.com/code/python/ai/informed_search"&gt;Source code&lt;/a&gt;).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-112830307758349490?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/112830307758349490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=112830307758349490' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830307758349490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/112830307758349490'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2005/10/ai-algorithms-in-python.html' title='AI algorithms in Python'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-110181020429655208</id><published>2004-11-30T02:14:00.000-08:00</published><updated>2004-11-30T02:38:28.493-08:00</updated><title type='text'>Literary warfare against the end of history</title><content type='html'>The author &lt;a href="http://www.elitism.info/journal/"&gt;dpa&lt;/a&gt; has some thoughts on the &lt;a href="http://www.elitism.info/journal/texts/2004/11/13/140/literary-warfare-against-the-end-of-history/"&gt;end of literacy&lt;/a&gt;.  I posted a lengthy response to his writing.  See dpa's blog, or my &lt;a href="http://oregonstate.edu/~barnesc/blog/mirror/2004-11-30-literary.html"&gt;mirrored copy&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-110181020429655208?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/110181020429655208/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=110181020429655208' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/110181020429655208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/110181020429655208'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2004/11/literary-warfare-against-end-of.html' title='Literary warfare against the end of history'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9318222.post-110137694396752755</id><published>2004-11-25T01:59:00.000-08:00</published><updated>2004-11-30T02:36:41.116-08:00</updated><title type='text'>Political commentary</title><content type='html'>I posted some commentary on 3rd political parties in the United States to &lt;a href="http://party3united.blogspot.com/2004/11/looking-for-right-third-party.html"&gt;1&lt;/a&gt;.  Or see my &lt;a href="http://oregonstate.edu/~barnesc/blog/mirror/2004-11-25-party3.html"&gt;mirrored copy&lt;/a&gt;.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9318222-110137694396752755?l=barnesc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://barnesc.blogspot.com/feeds/110137694396752755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9318222&amp;postID=110137694396752755' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/110137694396752755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9318222/posts/default/110137694396752755'/><link rel='alternate' type='text/html' href='http://barnesc.blogspot.com/2004/11/political-commentary.html' title='Political commentary'/><author><name>Connelly Barnes</name><uri>http://www.blogger.com/profile/02568908952592933174</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
