<?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-8006842399638506937</id><updated>2011-11-03T05:26:39.868-05:00</updated><category term='linux'/><category term='calendar'/><category term='math'/><category term='dehexer'/><category term='emacs'/><category term='clojure'/><category term='programming'/><category term='ASCII'/><category term='psnup'/><category term='oldposts'/><category term='lisp'/><category term='format'/><category term='syntax'/><category term='nerd'/><category term='blog'/><category term='sqrt'/><category term='misc'/><category term='publishing'/><category term='c'/><category term='modestproposal'/><category term='hexclock'/><category term='meta'/><category term='captcha'/><category term='manpage'/><category term='python'/><category term='haskell'/><category term='email'/><category term='macro'/><category term='code'/><category term='xmax'/><category term='postscript'/><category term='LaTeX'/><category term='bookbinding'/><category term='comments'/><title type='text'>Chris Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-2715874495021580948</id><published>2009-03-03T16:46:00.002-06:00</published><updated>2010-11-14T14:59:07.494-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='xmax'/><category scheme='http://www.blogger.com/atom/ns#' term='sqrt'/><category scheme='http://www.blogger.com/atom/ns#' term='calendar'/><category scheme='http://www.blogger.com/atom/ns#' term='modestproposal'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><category scheme='http://www.blogger.com/atom/ns#' term='nerd'/><title type='text'>March 5 is the Square Root of Christmas</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_BHA1C9BZJ7I/Sa2zhhbbsCI/AAAAAAAAANc/5QDy_F8vf5U/s1600-h/sqrtxmas.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 200px; height: 162px;" src="http://1.bp.blogspot.com/_BHA1C9BZJ7I/Sa2zhhbbsCI/AAAAAAAAANc/5QDy_F8vf5U/s320/sqrtxmas.png" alt="" id="BLOGGER_PHOTO_ID_5309096924230168610" border="0" /&gt;&lt;/a&gt;I just wanted to make the announcement, if anyone happened to be unaware. The reason for the holiday, if you haven't guessed already, is because sqrt(1225)&amp;nbsp;=&amp;nbsp;35. Translating those numbers into calendar dates gives us the square root of Christmas 12/25 falling on 3/5.

It just so happens that there is another big nerd holiday in March, Pi Day (3/14). Why not connect these two dates with a week(ish) long nerd celebration? I hereby declare that:
&lt;ul&gt;&lt;li&gt;March 5th shall be known as the &lt;span style="font-weight: bold;"&gt;Square Root of Christmas&lt;/span&gt; and&lt;/li&gt;&lt;li&gt;The 10-day interval between the Square Root of Christmas and Pi Day shall be known as &lt;span style="font-weight: bold;"&gt;Nerdigras&lt;/span&gt;
&lt;/li&gt;&lt;/ul&gt;

&lt;b&gt;Update (2010-11-14):&lt;/b&gt; &lt;i&gt;The official page for the &lt;a href="http://sencjw.com/the-square-root-of-christmas/"&gt;Square Root of Christmas&lt;/a&gt; and &lt;a href="http://sencjw.com/the-square-root-of-christmas/"&gt;Nerdigras&lt;/a&gt; has moved to &lt;a href="http://sencjw.com/the-square-root-of-christmas/"&gt;http://sencjw.com/the-square-root-of-christmas/"&lt;/a&gt;&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-2715874495021580948?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/2715874495021580948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=2715874495021580948' title='22 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/2715874495021580948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/2715874495021580948'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2009/03/march-5-is-square-root-of-christmas.html' title='March 5 is the Square Root of Christmas'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_BHA1C9BZJ7I/Sa2zhhbbsCI/AAAAAAAAANc/5QDy_F8vf5U/s72-c/sqrtxmas.png' height='72' width='72'/><thr:total>22</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-484572536381503777</id><published>2009-01-26T15:22:00.001-06:00</published><updated>2010-02-08T22:04:42.693-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='clojure'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='macro'/><category scheme='http://www.blogger.com/atom/ns#' term='syntax'/><title type='text'>Lisp is full of teh WIN</title><content type='html'>I know that the title is lame, verging on cringe-inducing, but I had to say it; I'm not sorry.

There has been a &lt;a href="http://news.ycombinator.com/item?id=450390"&gt;few&lt;/a&gt; &lt;a href="http://news.ycombinator.com/item?id=449345"&gt;threads&lt;/a&gt; of discussion over on &lt;a href="http://news.ycombinator.com/"&gt;Hacker News&lt;/a&gt; about what's wrong with Lisp. The argument seems to hinge on the lack of a literal syntax for "hashes" in lisp the way that there is in python or, in a more appropriate comparison, &lt;a href="http://clojure.org/"&gt;clojure&lt;/a&gt;. Clojure is great, by the way, and it is certainly deserving of its own post sometime soon. Suffice it to say that the next time I have to write something in Java I think I'm going to write it in clojure instead. Clojure has &lt;a href="http://clojure.org/jvm_hosted"&gt;great interoperability&lt;/a&gt; with Java. Amazingly, there are &lt;span style="font-style: italic;"&gt;fewer &lt;/span&gt;parenthesis in the Lisp version of that little GUI program than in the Java version!

But on to the topic of the day. In many languages you can do something like this:

&lt;pre name="code" class="python"&gt;
&gt;&gt;&gt; d = {"a":1, "b":2, "c":3}
&gt;&gt;&gt; d
{'a': 1, 'c': 3, 'b': 2}
&gt;&gt;&gt; d['b']
2
&lt;/pre&gt;

You can see that we can explicitly give a representation of that hash that python knows how to parse into the corresponding data structure. Clojure has a very similar literal syntax:

&lt;pre name="code" class="lisp"&gt;
user=&gt; (get {:a 1 :b 2 :c 3} :b)
2
&lt;/pre&gt;

So the complaint is that Common Lisp doesn't have anything like that. Using hashes in CL consists of a bunch of function calls that manage the hash:

&lt;pre name="code" class="lisp"&gt;
CL-USER&gt; (let ((hash (make-hash-table)))                                       
          (setf (gethash :a hash) 1)                                          
          (setf (gethash :b hash) 2)                                          
          (setf (gethash :c hash) 3)                                          
          (gethash :b hash))
2
T
&lt;/pre&gt;

There is never any literal representation of the hash, in fact, if we evaluate the name of the hash we'll just get something like this "#&amp;lt;HASH-TABLE :TEST EQL :COUNT 3 {AD11A99}&amp;gt;" Which basically tells the lisp reader to signal an error if the form is read.

But this doesn't have to be so verbose. We can write a really simple reader macro (with a little helper function) that gives us something like what we have in python or clojure above:

&lt;pre name="code" class="lisp"&gt;
(defun ins-hash (h vals)
  (if (oddp (length vals))
      nil
      (if (not (null vals))
          (progn
            (setf (gethash (first vals) h) (second vals))
            (ins-hash h (cddr vals)))
          h)))

(set-macro-character #\} (get-macro-character #\)))

(set-dispatch-macro-character #\# #\{
  #'(lambda (stream char1 char2)
      (let ((items (read-delimited-list #\} stream t)))
        (ins-hash (make-hash-table) items))))
&lt;/pre&gt;

With this reader macro I can now write this:

&lt;pre name="code" class="lisp"&gt;
CL-USER&gt; (gethash :b #{:a 1 :b 2 :c 3})
2
T
&lt;/pre&gt;

Lisp now interprets everything between '#{' and '}' as key, value pairs and using the helper function inserts them into a new hash. Cool!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-484572536381503777?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/484572536381503777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=484572536381503777' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/484572536381503777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/484572536381503777'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2009/01/lisp-is-full-of-teh-win.html' title='Lisp is full of teh WIN'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-2430160670165899279</id><published>2008-11-07T17:34:00.001-06:00</published><updated>2010-02-08T22:05:15.707-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ASCII'/><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>haskell and scrambled text</title><content type='html'>&lt;p&gt;I've recently been playing around with &lt;a href="http://www.haskell.org/"&gt;Haskell&lt;/a&gt;, and one of the toy applications that I like to write is a text "munger." It takes text and outputs the same text with the words labeled as to their order and then it &lt;a href="http://catb.org/jargon/html/A/ASCIIbetical-order.html"&gt;ASCIIbetizes&lt;/a&gt; them. This article (up to the end of this sentence) would look like this:&lt;/p&gt;

&lt;p&gt;"munger."[22] (up[46] ASCIIbetizes[42] Haskell,[7] I've[1] I[15] It[23] This[44] a[20] and[26] and[39] and[8] applications[13] around[5] article[45] as[35] been[3] end[49] is[19] it[41] labeled[34] like[16] like[55] look[54] of[10] of[50] one[9] order[38] outputs[27] playing[4] recently[2] same[29] sentence)[52] takes[24] text[21] text[25] text[30] that[14] the[11] the[28] the[32] the[48] their[37] them.[43] then[40] this:[56] this[51] to[17] to[36] to[47] toy[12] with[31] with[6] words[33] would[53] write[18]&lt;/p&gt;

&lt;p&gt;So you &lt;strong&gt;could&lt;/strong&gt; reconstruct that with a little work, but it is nicer to do it by feeding into the "demunge" function. Enjoy:&lt;/p&gt;

&lt;p&gt;
&lt;fieldset&gt;&lt;legend&gt;munge.hs&lt;/legend&gt;
&lt;font color="#0000ff"&gt;-- Copyright 2008 Chris Wilson&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;-- Code is licensed under the GNU GPL &lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;--&amp;nbsp;&amp;nbsp; &lt;a href="http://www.gnu.org/licenses/gpl.html"&gt;http://www.gnu.org/licenses/gpl.html&lt;/a&gt;&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;Data.List&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;-- Label each string in the order that it is encountered &lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;--&amp;nbsp;&amp;nbsp; [(&amp;quot;Word&amp;quot;, 1),..(&amp;quot;Lastword&amp;quot;, n)]&lt;/font&gt;&lt;br&gt;
label&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(Num&amp;nbsp;a,&amp;nbsp;Enum&amp;nbsp;a)&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[String]&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[(String,&amp;nbsp;a)]&lt;br&gt;
label&amp;nbsp;[]&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[]&lt;br&gt;
label&amp;nbsp;sl&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;zip&amp;nbsp;sl&amp;nbsp;[&lt;font color="#ff00ff"&gt;1&lt;/font&gt;&lt;font color="#a52a2a"&gt;&lt;b&gt;..&lt;/b&gt;&lt;/font&gt;]&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;-- Add these sequential numbers to the end of words&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;--&amp;nbsp;&amp;nbsp; [(&amp;quot;Word&amp;quot;,1)] -&amp;gt; [&amp;quot;Word[1]&amp;quot;]&lt;/font&gt;&lt;br&gt;
attachLabel&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(Num&amp;nbsp;t)&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[(String,&amp;nbsp;t)]&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[String]&lt;br&gt;
attachLabel&amp;nbsp;[]&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[]&lt;br&gt;
attachLabel&amp;nbsp;(s&lt;font color="#a52a2a"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/font&gt;ss)&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(fst&amp;nbsp;s&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;++&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;[&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;++&lt;/b&gt;&lt;/font&gt;&amp;nbsp;show&amp;nbsp;(snd&amp;nbsp;s)&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;++&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;]&amp;quot;&lt;/font&gt;)&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;:&lt;/b&gt;&lt;/font&gt;&amp;nbsp;attachLabel&amp;nbsp;ss&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;-- Compose all these functions together&lt;/font&gt;&lt;br&gt;
munge&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&lt;br&gt;
munge&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&lt;br&gt;
munge&amp;nbsp;s&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;intercalate&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot; &amp;quot;&lt;/font&gt;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;sort&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;attachLabel&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;label&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;words&amp;nbsp;s&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;-- Extract the oder from a tagged word&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;--&amp;nbsp;&amp;nbsp; &amp;quot;is[5]&amp;quot; -&amp;gt; 5&lt;/font&gt;&lt;br&gt;
getOrder&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;Int&lt;br&gt;
getOrder&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#ff00ff"&gt;0&lt;/font&gt;&lt;br&gt;
getOrder&amp;nbsp;s&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#ff00ff"&gt;0&lt;/font&gt;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;+&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(read&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;reverse&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;tail&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;fst&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;span&amp;nbsp;(&lt;font color="#a52a2a"&gt;&lt;b&gt;/=&lt;/b&gt;&lt;/font&gt;&lt;font color="#ff00ff"&gt;'['&lt;/font&gt;)&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;reverse&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;s)&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;-- Extract the word-part of a tagged word&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;--&amp;nbsp;&amp;nbsp; &amp;quot;is[5]&amp;quot; -&amp;gt; &amp;quot;is&amp;quot;&lt;/font&gt;&lt;br&gt;
getWord&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&lt;br&gt;
getWord&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&lt;br&gt;
getWord&amp;nbsp;s&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;reverse&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;tail&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;snd&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;span&amp;nbsp;(&lt;font color="#a52a2a"&gt;&lt;b&gt;/=&lt;/b&gt;&lt;/font&gt;&lt;font color="#ff00ff"&gt;'['&lt;/font&gt;)&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;.&lt;/b&gt;&lt;/font&gt;&amp;nbsp;reverse&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;$&lt;/b&gt;&lt;/font&gt;&amp;nbsp;s&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;-- Put the words into a list of tuples: (order, word)&lt;/font&gt;&lt;br&gt;
reconstruct&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[(Int,&amp;nbsp;String)]&lt;br&gt;
reconstruct&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[]&lt;br&gt;
reconstruct&amp;nbsp;s&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;[&amp;nbsp;(getOrder&amp;nbsp;item,&amp;nbsp;getWord&amp;nbsp;item)&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;|&lt;/b&gt;&lt;/font&gt;&amp;nbsp;item&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;&amp;lt;-&lt;/b&gt;&lt;/font&gt;&amp;nbsp;words&amp;nbsp;s&amp;nbsp;]&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;-- Put all the extraction functions together&lt;/font&gt;&lt;br&gt;
demunge&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;::&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;-&amp;gt;&lt;/b&gt;&lt;/font&gt;&amp;nbsp;String&lt;br&gt;
demunge&amp;nbsp;[]&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot;&amp;quot;&lt;/font&gt;&lt;br&gt;
demunge&amp;nbsp;xs&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;=&lt;/b&gt;&lt;/font&gt;&amp;nbsp;intercalate&amp;nbsp;&lt;font color="#ff00ff"&gt;&amp;quot; &amp;quot;&lt;/font&gt;&amp;nbsp;[&amp;nbsp;snd&amp;nbsp;item&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;|&lt;/b&gt;&lt;/font&gt;&amp;nbsp;item&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;&amp;lt;-&lt;/b&gt;&lt;/font&gt;&amp;nbsp;sort&amp;nbsp;(reconstruct&amp;nbsp;xs)&amp;nbsp;]&lt;br&gt;
&lt;/fieldset&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-2430160670165899279?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/2430160670165899279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=2430160670165899279' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/2430160670165899279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/2430160670165899279'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/11/haskell-and-scrambled-text.html' title='haskell and scrambled text'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-8994923489780352887</id><published>2008-08-30T12:33:00.001-05:00</published><updated>2010-02-08T22:06:55.000-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='captcha'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='modestproposal'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>A plan for CAPTCHAs</title><content type='html'>I had the idea (&lt;a href="http://www.captcha.net/captcha_crypt.pdf"&gt;I'm uncertain if it is original&lt;/a&gt; [pdf]) of mixing two distinct elements to make a better &lt;a href="http://en.wikipedia.org/wiki/Captcha"&gt;CAPTCHA&lt;/a&gt;.

The problem is that there are essentially two ways to solve a CAPTCHA. The first is by designing some kind of image recognition system, this is an OCR problem and there are indications that nearly every major CAPTCHA has &lt;a href="http://www.google.com/search?q=captcha+broken"&gt;been broken&lt;/a&gt;.

The other main avenue of attack seems to come down to &lt;a href="http://blogs.zdnet.com/security/?p=1835"&gt;paying people to crack them&lt;/a&gt;. This is a much tougher nut to crack because CAPTCHAs are not designed to prevent humans from cracking them; in some sense, this attack isn't a break of the system at all, but a design goal of CAPTCHAs. But much like the mathematician in that &lt;a href="http://www-users.cs.york.ac.uk/~susan/joke/3.htm#fence"&gt;old joke&lt;/a&gt;, this definition of acceptable wouldn't sit well with some.

The solution is to pose a question in such a way that is &lt;i&gt;very hard&lt;/i&gt; for a computer to perceive but at the same time hard for a person to &lt;i&gt;solve&lt;/i&gt; by herself. As an example, imagine a cryptographically &lt;a href="http://en.wikipedia.org/wiki/Discrete_logarithm#Cryptography"&gt;hard problem&lt;/a&gt; posed in a way that a computer couldn't readily interpret, and a person would find difficult (or impossible) to solve by hand. This could be the source code for a simple &lt;a href="http://en.wikipedia.org/wiki/Discrete_logarithm"&gt;discrete logarithm&lt;/a&gt; solver. The code would be obscured in the normal way that a CAPTCHA is (wavy text, visual noise, etc.) The user is instructed to type the code into a text box (where a built-in solver, client-side, can operate on it), and then use the result for entry into the protected resource. It would be easy to tune the toughness of the discrete log problem (randomly chosen of course) to generate any &lt;i&gt;penalty&lt;/i&gt; you want. This penalty would cost an attacker any amount of CPU time that the challenger desires.

By mixing a character-recognition task (that a human is good at) with a number-crunching task (which a computer is good at, but can be made arbitrarily CPU-intensive and thus slow) you protect from both types of attacks:
&lt;ol&gt;
&lt;li&gt;If an OCR program can read your text, they still must compute a computationally expensive value.&lt;/li&gt;
&lt;li&gt;If humans are being used to circumvent the OCR task, a computer must be used to compute the expensive task as well, still incurring most of the penalty (by tweaking the exact type and hardness of the &lt;a href="http://en.wikipedia.org/wiki/One-way_function"&gt;one-way function&lt;/a&gt;, this part can come to dominate the time needed for a successful break).&lt;/li&gt;
&lt;/ol&gt;

Some ideas on how to make the computation time more palatable for a legitimate user:
&lt;ul&gt;
&lt;li&gt;Make this be the first question on a form that the user has to fill out.&lt;/li&gt;
&lt;li&gt;Grant the user &lt;i&gt;provisional&lt;/i&gt; access to the site while the computation proceeds in the background.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-8994923489780352887?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/8994923489780352887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=8994923489780352887' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/8994923489780352887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/8994923489780352887'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/08/plan-for-captchas.html' title='A plan for CAPTCHAs'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-9057254288665472261</id><published>2008-08-15T15:38:00.001-05:00</published><updated>2010-02-08T22:07:23.190-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='modestproposal'/><category scheme='http://www.blogger.com/atom/ns#' term='hexclock'/><title type='text'>Hex Clock</title><content type='html'>I was reading Hal's blog the other day when I thought that I'd try and implement a clock that uses the hexadecimal time that he talks about. I have seen a bunch of these so-called binary clocks that display the time is some nifty format (blinkenlights). The thing is, what they display is usually &lt;a href="http://en.wikipedia.org/wiki/Binary-coded_decimal"&gt;binary coded decimal&lt;/a&gt; (i.e. 1100:111011 = 12:59). Sometimes they even code each digit: 0001 0010:0101 1001!

Hal defined the hexadecimal second to be 1/2^16 of a day, making 65,536 "hexeconds" per day. Since there are 86,400 seconds in a day, there are about 1.318 sec/hxs. Naturally, there are FF hexeconds in a "hexinute." A hexinute is 1/2^8 of a day, making each 337.5 seconds long, or 5.625 minutes (5 min, 37.5 sec). This leads to a nice property (besides being easily convertible to binary), A day then is recursive, there are 256 hxm per day and there are 256 hxs per hxm. Much better than 24 hours, with 60 minutes with 60 seconds! Who could remember that? You just have to get used to your clock displaying a time like: BE|EF (~64,440 seconds into your day or 5:54 PM, clearly not a vegetarian dinner time).

Another thing that I thought about was the "stability" of a given digit. Each digit "stays put" for 16 times as long as the digit to it's right. The fastest-changing digit advances each ~1.318 second, to its left the 16's place advances each 16*1.318 = ~21 seconds. In the one's place in the hexinutes each advances 337.5 seconds (or 5.625 minutes), lastly, the most stable digit advances each every 90 minutes. That's great for measuring the &lt;a href="http://www.astronomycafe.net/qadir/q725.html"&gt;orbital period of the space shuttle&lt;/a&gt;, each orbit is &lt;tt&gt;10|00&lt;/tt&gt; long! That's my proposal for writing the time, by the way, for the programmers out there it will be evocative of a bitwise OR; if you think of the time as something like &lt;tt&gt;0xAB00 | 0xCD&lt;/tt&gt;.

Without further ado:

&lt;fieldset&gt;&lt;legend&gt;hexclock.py&lt;/legend&gt;
&lt;font color="#0000ff"&gt;#!/usr/bin/env python&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Based on discussion here: &lt;a href="http://halcanary.org/vv/2007/10/31/706/"&gt;http://halcanary.org/vv/2007/10/31/706/&lt;/a&gt;&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Copyright 2008 Chris Wilson. &lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# This program is free software: you can redistribute it and/or modify it&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# under the terms of the GNU General Public License as published by the&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Free Software Foundation, either version 3 of the License, or (at your&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# option) any later version.&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# This program is distributed in the hope that it will be useful, but&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&amp;nbsp;&amp;nbsp;See the GNU General&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Public License for more details.&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# You should have received a copy of the GNU General Public License along&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# with this program.&amp;nbsp;&amp;nbsp;If not, see &amp;lt;&lt;a href="http://www.gnu.org/licenses/"&gt;http://www.gnu.org/licenses/&lt;/a&gt;&amp;gt;.&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color="#a020f0"&gt;from&lt;/font&gt;&amp;nbsp;Tkinter &lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;*&lt;br&gt;
&lt;font color="#a020f0"&gt;from&lt;/font&gt;&amp;nbsp;random &lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;random&lt;br&gt;
&lt;font color="#a020f0"&gt;from&lt;/font&gt;&amp;nbsp;time &lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;sleep&lt;br&gt;
&lt;font color="#a020f0"&gt;from&lt;/font&gt;&amp;nbsp;hs &lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;hexarray, hexdisplay&lt;br&gt;
&lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;sys&lt;br&gt;
&lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;math&lt;br&gt;
&lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;getopt&lt;br&gt;
&lt;br&gt;
master = Tk()&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;usage&lt;/font&gt;():&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&amp;quot;&amp;quot;&amp;quot;&lt;font color="#6a5acd"&gt;\n&lt;/font&gt;&lt;font color="#ff00ff"&gt;Dislpay a Tk-based animated binary clock. The fastest pixel&lt;/font&gt;&lt;br&gt;
&lt;font color="#ff00ff"&gt;blinks about once every 1.318 seconds, there are 2^16 such transitions&lt;/font&gt;&lt;br&gt;
&lt;font color="#ff00ff"&gt;per day.&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color="#ff00ff"&gt;%s [options]&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;-h&amp;nbsp;&amp;nbsp;--help This message &lt;/font&gt;&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;-s --size SIZE. make the display SIZE pixels on a side &lt;/font&gt;&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;-d --digits display digits in addition to the graphical binary &lt;/font&gt;&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;representation of the time.&lt;/font&gt;&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;-f --foreground COLOR. the &amp;quot;lit up&amp;quot; pixels are this color.&amp;nbsp;&amp;nbsp;&lt;/font&gt;&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;-b --background COLOR. the background pixels are this &lt;/font&gt;&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;color.&lt;/font&gt;&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;-t --textcolor COLOR. the text will appear this color. Obviously, &lt;/font&gt;&lt;br&gt;
&lt;font color="#6a5acd"&gt;\t&lt;/font&gt;&lt;font color="#ff00ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this option only makes sense with -d&lt;/font&gt;&amp;quot;&amp;quot;&amp;quot;&amp;nbsp;% sys.argv[0]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sys.exit(1)&lt;br&gt;
&lt;br&gt;
digits = False&lt;br&gt;
HEIGHT = WIDTH = 400&lt;br&gt;
on = &amp;quot;&lt;font color="#ff00ff"&gt;blue&lt;/font&gt;&amp;quot;&lt;br&gt;
off = &amp;quot;&lt;font color="#ff00ff"&gt;black&lt;/font&gt;&amp;quot;&lt;br&gt;
textcolor = &amp;quot;&lt;font color="#ff00ff"&gt;white&lt;/font&gt;&amp;quot;&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;try&lt;/b&gt;&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;opts, args = getopt.getopt(sys.argv[1:], &lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;&lt;font color="#ff00ff"&gt;hs:df:b:t:&lt;/font&gt;&amp;quot;, [&amp;quot;&lt;font color="#ff00ff"&gt;help&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color="#ff00ff"&gt;size=&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color="#ff00ff"&gt;digits&lt;/font&gt;&amp;quot;, &lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&lt;font color="#ff00ff"&gt;foreground&lt;/font&gt;&amp;quot;,&amp;quot;&lt;font color="#ff00ff"&gt;background&lt;/font&gt;&amp;quot;,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;&lt;font color="#ff00ff"&gt;textcolor&lt;/font&gt;&amp;quot;])&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;except&lt;/b&gt;&lt;/font&gt;&amp;nbsp;getopt.GetoptError, err:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/font&gt;&amp;nbsp;str(err)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;usage()&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/font&gt;&amp;nbsp;o, a &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;opts:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/font&gt;&amp;nbsp;o &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&amp;quot;&lt;font color="#ff00ff"&gt;-d&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color="#ff00ff"&gt;--digits&lt;/font&gt;&amp;quot;):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digits = True&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;elif&lt;/b&gt;&lt;/font&gt;&amp;nbsp;o &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&amp;quot;&lt;font color="#ff00ff"&gt;-s&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color="#ff00ff"&gt;--size&lt;/font&gt;&amp;quot;):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;try&lt;/b&gt;&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HEIGHT = WIDTH = int(a)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;except&lt;/b&gt;&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;usage()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;elif&lt;/b&gt;&lt;/font&gt;&amp;nbsp;o &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&amp;quot;&lt;font color="#ff00ff"&gt;-f&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color="#ff00ff"&gt;--foreground&lt;/font&gt;&amp;quot;):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;on = a&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;elif&lt;/b&gt;&lt;/font&gt;&amp;nbsp;o &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&amp;quot;&lt;font color="#ff00ff"&gt;-b&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color="#ff00ff"&gt;--background&lt;/font&gt;&amp;quot;):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;off = a&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;elif&lt;/b&gt;&lt;/font&gt;&amp;nbsp;o &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&amp;quot;&lt;font color="#ff00ff"&gt;-h&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color="#ff00ff"&gt;--help&lt;/font&gt;&amp;quot;):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;usage()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;elif&lt;/b&gt;&lt;/font&gt;&amp;nbsp;o &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;(&amp;quot;&lt;font color="#ff00ff"&gt;-t&lt;/font&gt;&amp;quot;, &amp;quot;&lt;font color="#ff00ff"&gt;--textcolor&lt;/font&gt;&amp;quot;):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;textcolor = a&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;usage()&lt;br&gt;
&lt;br&gt;
fs = int(math.sqrt(HEIGHT))&lt;br&gt;
&lt;br&gt;
w = Canvas(master, width=WIDTH, height=HEIGHT)&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;create_grid&lt;/font&gt;(canvas, grid, height, width):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ulx = 0&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uly = 0&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xdimen = width/4&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ydimen = height/4&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item_array = list()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/font&gt;&amp;nbsp;square &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;grid:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/font&gt;&amp;nbsp;square == 1:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i = canvas.create_rectangle(ulx, uly, ulx+xdimen, uly+ydimen,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fill=on)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i = canvas.create_rectangle(ulx, uly, ulx+xdimen, uly+ydimen,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fill=off)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item_array.append(i)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/font&gt;&amp;nbsp;ulx == (width-xdimen):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uly = uly + ydimen&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ulx = 0&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ulx = ulx + xdimen&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;item_array&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;update&lt;/font&gt;(canvas, items, grid):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/font&gt;&amp;nbsp;i &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;range(len(items)):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/font&gt;&amp;nbsp;grid[i] == 1:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;canvas.itemconfig(items[i], fill=on)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;canvas.itemconfig(items[i], fill=off)&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/font&gt;&amp;nbsp;digits:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;create_timestamp&lt;/font&gt;(canvas,h,w):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;canvas.create_text(h/2,w/2,text=hexdisplay(),fill=textcolor,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;justify=CENTER, font=&amp;quot;&lt;font color="#ff00ff"&gt;Courier %d bold&lt;/font&gt;&amp;quot;&amp;nbsp;% fs)&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;update_time&lt;/font&gt;(canvas,text_handle):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;canvas.itemconfig(text_handle, text=hexdisplay())&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/font&gt;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;create_timestamp&lt;/font&gt;(canvas,h,w): &lt;font color="#a52a2a"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;update_time&lt;/font&gt;(canvas,text_handle): &lt;font color="#a52a2a"&gt;&lt;b&gt;pass&lt;/b&gt;&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;br&gt;
items = create_grid(w, hexarray(), HEIGHT, WIDTH)&lt;br&gt;
text = create_timestamp(w, HEIGHT, WIDTH)&lt;br&gt;
w.pack()&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/font&gt;&amp;nbsp;True:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;update(w, items, hexarray())&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;update_time(w,text)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w.update_idletasks()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;# redraw&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w.update()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;# process events&lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sleep(1)&lt;br&gt;
mainloop()&lt;br&gt;

&lt;/fieldset&gt;

&lt;fieldset&gt;&lt;legend&gt;hs.py&lt;/legend&gt;
&lt;font color="#0000ff"&gt;#!/usr/bin/env python&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Based on blog post on: &lt;a href="http://halcanary.org/vv/2007/10/31/706/"&gt;http://halcanary.org/vv/2007/10/31/706/&lt;/a&gt;&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Copyright 2008 Chris Wilson&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# This program is free software: you can redistribute it and/or modify it&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# under the terms of the GNU General Public License as published by the&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Free Software Foundation, either version 3 of the License, or (at your&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# option) any later version.&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# This program is distributed in the hope that it will be useful, but&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# WITHOUT ANY WARRANTY; without even the implied warranty of&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&amp;nbsp;&amp;nbsp;See the GNU General&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Public License for more details.&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;#&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# You should have received a copy of the GNU General Public License along&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# with this program.&amp;nbsp;&amp;nbsp;If not, see &amp;lt;&lt;a href="http://www.gnu.org/licenses/"&gt;http://www.gnu.org/licenses/&lt;/a&gt;&amp;gt;.&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;math, time&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;# hex timekeeping&lt;/font&gt;&lt;br&gt;
hs = 86400.0/(2**16)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;# there are 65,536 hexeconds in a day ~1.318 sec.&lt;/font&gt;&lt;br&gt;
hm = 86400.0/(2**8) &lt;font color="#0000ff"&gt;# there are 256 hexeconds in hexinute&amp;nbsp;&amp;nbsp;~337.5 sec&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color="#0000ff"&gt;# I'm not defining an hour since there wouldn't be many of them (and they'd&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# be redundant, with a hexinute being ~5.6 mins, these are pretty stable.&lt;/font&gt;&lt;br&gt;
&lt;font color="#0000ff"&gt;# Plus, hackers are more precise anyway ;) ).&lt;/font&gt;&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;day_secs&lt;/font&gt;():&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h, m, s = time.localtime()[3:6]&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;h*3600 + m * 60 + s&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;hextime&lt;/font&gt;():&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;s = day_secs()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hexmin = int(math.floor(s/hm))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;s = s - (hexmin*hm)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hexsec = int(math.floor(s/hs))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;hexmin,hexsec&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;hexarray&lt;/font&gt;():&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hexmin, hexsec = hextime()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total = (hexmin &amp;lt;&amp;lt; 8) + hexsec&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out = list()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/font&gt;&amp;nbsp;x &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;range(16):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.append(total &amp;amp; 1)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;total = total&amp;gt;&amp;gt;1&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.reverse()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;out&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;hexdisplay&lt;/font&gt;():&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&amp;quot;&lt;font color="#ff00ff"&gt;%02X:%02X&lt;/font&gt;&amp;quot;&amp;nbsp;% hextime()&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;bindisplay&lt;/font&gt;():&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hm, hs = hextime()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;n1, n2 = nybbles(hm)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;n3, n4 = nybbles(hs)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;format_args = map(to_bin, (n1, n2, n3, n4))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&amp;quot;&lt;font color="#ff00ff"&gt;%s&lt;/font&gt;&lt;font color="#6a5acd"&gt;\n&lt;/font&gt;&lt;font color="#ff00ff"&gt;%s&lt;/font&gt;&lt;font color="#6a5acd"&gt;\n&lt;/font&gt;&lt;font color="#ff00ff"&gt;%s&lt;/font&gt;&lt;font color="#6a5acd"&gt;\n&lt;/font&gt;&lt;font color="#ff00ff"&gt;%s&lt;/font&gt;&amp;quot;&amp;nbsp;%&amp;nbsp;&amp;nbsp;tuple(format_args)&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;nybbles&lt;/font&gt;(byte):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lower = byte&amp;amp;15&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;upper = (byte&amp;gt;&amp;gt;4)&amp;amp;15&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;upper, lower&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;to_bin&lt;/font&gt;(nybble):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out = list()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;for&lt;/b&gt;&lt;/font&gt;&amp;nbsp;x &lt;font color="#a52a2a"&gt;&lt;b&gt;in&lt;/b&gt;&lt;/font&gt;&amp;nbsp;range(4):&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.append(str(1 &amp;amp; nybble))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nybble = nybble&amp;gt;&amp;gt;1&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out.reverse()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&amp;quot;&lt;font color="#ff00ff"&gt;&amp;nbsp;&lt;/font&gt;&amp;quot;.join(out)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;_test&lt;/font&gt;():&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&amp;quot;&lt;font color="#ff00ff"&gt;16&lt;/font&gt;&amp;quot;, nybbles(16)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;u, l = nybbles(16)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&amp;quot;&lt;font color="#ff00ff"&gt;bin:&lt;/font&gt;&amp;quot;,u,l, to_bin(u), to_bin(l)&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;def&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&lt;font color="#008b8b"&gt;run_clock&lt;/font&gt;():&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a020f0"&gt;import&lt;/font&gt;&amp;nbsp;os&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/font&gt;&amp;nbsp;True:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;os.system(&amp;quot;&lt;font color="#ff00ff"&gt;clear&lt;/font&gt;&amp;quot;)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/font&gt;&amp;nbsp;bindisplay()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#a52a2a"&gt;&lt;b&gt;print&lt;/b&gt;&lt;/font&gt;&amp;nbsp;&amp;quot;&lt;font color="#ff00ff"&gt;(&lt;/font&gt;&amp;quot;+hexdisplay()+&amp;quot;&lt;font color="#ff00ff"&gt;)&lt;/font&gt;&amp;quot;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;time.sleep(1)&lt;br&gt;
&lt;br&gt;
&lt;font color="#a52a2a"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/font&gt;&amp;nbsp;__name__ == &amp;quot;&lt;font color="#ff00ff"&gt;__main__&lt;/font&gt;&amp;quot;:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;font color="#0000ff"&gt;#_test()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;run_clock()&lt;br&gt;

&lt;/fieldset&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-9057254288665472261?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/9057254288665472261/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=9057254288665472261' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/9057254288665472261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/9057254288665472261'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/08/hex-clock.html' title='Hex Clock'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-5929255398133128640</id><published>2008-06-27T17:24:00.001-05:00</published><updated>2010-02-08T22:00:25.839-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Everything cool has already been done</title><content type='html'>I guess I shouldn't be surprised by anything that turns up within a &lt;a href="http://psung.blogspot.com/2008/06/million-lines-of-lisp.html"&gt;million-line&lt;/a&gt; codebase, but I was.

I had been looking around for a way to keep contacts, you know, collections of vital stats: name, e-mail address and if I have it postal address. I've had such a file hanging around for years now my nickname for it is &lt;span style="font-style: italic;font-size:100%;" &gt;snailmail&lt;/span&gt;. I know that the term has traditionally meant more or less: "things one can send through the postal service." But seeing as how &lt;a href="http://news.cnet.com/2009-1032_3-6197242.html"&gt;e-mail is dead&lt;/a&gt; (&lt;acronym title="tounge-in-cheek"&gt;TIC&lt;/acronym&gt;), it grows increasingly apropos. But anyway, I digress.

I have this file of info and I wanted to keep it up to date, generate lists of names, generate those &lt;span style="font-style: italic;"&gt;mailto:&lt;/span&gt; links and etc. In keeping with what I feel is the the *NIX way, I thought I should create a bunch of shell scripts that operate on my flat file in various ways. So I wrote a few scripts that would dig through the file and spit out whatever it was that I wanted. Okay, I can't resist, I wanted to include one of the ones that I wrote in scheme (guile):

&lt;fieldset&gt;&lt;legend&gt;&lt;b&gt;snails.scm&lt;/b&gt;&lt;/legend&gt;
&lt;pre&gt;#!/usr/bin/guile -s
!#
(use-modules (ice-9 rdelim))

(define (unpack-snailmail line)
"Currently, this is just &lt;lastname&gt;:&lt;firstname&gt;:e-mail"
(let ((line-elts (string-split line #\:)))
(format #t "\"~a ~a\" &lt;~a&gt;~%" (cadr line-elts) (car line-elts)
   (caddr line-elts))))

(define (read-lines port f)
"Read all the lines of a file found at port &lt;port&gt;, applying f"
(let ((current-line (read-line port)))
(if (not (eof-object? current-line))
(begin
 (f current-line)
 (read-lines port f)))))

; rudimentary error-checking on the command line
(if (&lt; (length (command-line)) 2)
    (display "Usage: snail snailmail.db\n")
    (read-lines (open-file (cadr (command-line)) "r") 
                unpack-snailmail))
&lt;/pre&gt;&lt;/fieldset&gt;


So it is cake to read out the lines of this file. What I wondered more about was how to update and tend this file?

Emacs to the rescue! I found out about &lt;span style="font-style: italic;"&gt;forms-mode &lt;/span&gt;this does what you would expect, that is to create and fill out forms. There are two components to the form, the first is your data file. In my case it looks like this

&lt;fieldset&gt;&lt;legend&gt;&lt;b&gt;.snails&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;
Lastname0:Firstname0:E-mail_address0
Lastname1:Firstname1:E-mail_address1
&lt;/pre&gt;&lt;/fieldset&gt;

And so on. Next we need an emacs lisp file to tell Emacs how to parse that file and what the form should look like:


&lt;fieldset&gt;&lt;legend&gt;&lt;b&gt;sform.el&lt;/b&gt;&lt;/legend&gt;&lt;pre&gt;
;; -*- mode: forms -*-
;; This is the 'Control file' (see 'info forms') for .snails
(setq forms-file "~/.snails")
(setq forms-format-list
 (list
  ",------------------,\n"
  "| Snail Mail Ver 1 |\n"
  "'------------------'\n\n"
  "First:   " 2 "\n"
  "Last:    " 1 "\n"
  "E-mail:  " 3 "\n"))
(setq forms-number-of-fields 3)
(setq forms-field-sep ":")
&lt;/pre&gt;&lt;/fieldset&gt;

When you launch emacs and point it at that file &lt;tt&gt;emacs -nw sform.el&lt;/tt&gt;, emacs will ask if you want parse it (answer 'yes') And then there are helpful commands at the bottom of the screen. The only basic one omitted is the one to create new entries, &lt;tt&gt;C-c C-o&lt;/tt&gt; does the trick.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-5929255398133128640?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/5929255398133128640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=5929255398133128640' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/5929255398133128640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/5929255398133128640'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/06/everything-cool-has-already-been-done.html' title='Everything cool has already been done'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-7346424394574151321</id><published>2008-05-16T16:07:00.001-05:00</published><updated>2010-02-08T22:09:45.509-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='ASCII'/><category scheme='http://www.blogger.com/atom/ns#' term='format'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>webindent.c</title><content type='html'>&lt;p&gt;Sometimes I want to post code to a website, but they have utterly broken filters (I'm looking at you &lt;a href="http://answers.yahoo.com"&gt;Yahoo! Answers&lt;/a&gt;). So that when I paste nicely indented code it goes from this:&lt;/p&gt;
&lt;p&gt;def double(x):&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return x+x&lt;/p&gt;
&lt;p&gt;to this:&lt;/p&gt;
&lt;p&gt;def double(x):&lt;br /&gt;
return x+x&lt;/p&gt;
&lt;p&gt;
It is annoying in C or Lisp, but it is &lt;i&gt;wrong&lt;/i&gt; in python where the syntax relies on proper indentation. When websites do this it is &lt;a href="http://www.catb.org/jargon/html/B/brain-dead.html"&gt;broken&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
So I wrote a little program to rectify the situation. It processes a source file so that it looks the same or similar on the web as in your text editor.
&lt;/p&gt;
&lt;p&gt;
&lt;tt&gt;usage:&amp;nbsp;webindent&amp;nbsp;&amp;lt;&amp;nbsp;source.c&amp;nbsp;&amp;gt;&amp;nbsp;page.html&lt;/tt&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;div style="border: 1px solid; padding: 1em;"&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#define true 1&lt;br /&gt;
#define false 0&lt;br /&gt;
&lt;br /&gt;
/* main(): get characters from stdin, replace&lt;br /&gt;
&amp;nbsp;*  leading spaces with '&amp;amp;nbsp;'&lt;br /&gt;
&amp;nbsp;*  and replace leading tabs with 4 '&amp;amp;nbsp;'s&lt;br /&gt;
&amp;nbsp;*  This code is donated to the public domain */&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int start = true;       /* we're at the start of a line */&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char *space = "&amp;amp;nbsp;";&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char *fourspaces = "&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;";&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char c;                 /* the current char */&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while ((c = getchar()) != EOF) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (c == ' ') {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (start)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;printf(space);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;putchar(c);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else if (c == '\t') {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (start)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;printf(fourspaces);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;putchar(c);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else if (c == '&amp;lt;') {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;printf("&amp;amp;lt;");&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else if (c == '&amp;gt;') {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;printf("&amp;amp;gt;");&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else if (c == '\n') {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;printf("&amp;lt;br /&amp;gt;");&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;putchar(c);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;start = true;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else if (c == '&amp;amp;') {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;printf("&amp;amp;amp;");&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (start)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;start = false;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;putchar(c);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;
It does a bit more than is stated in that comment, because it has to remove '&amp;amp;', '&amp;lt;' and '&amp;gt;' for it to be a well-formed HTML fragment. Note that I used this program to process itself.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-7346424394574151321?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/7346424394574151321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=7346424394574151321' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/7346424394574151321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/7346424394574151321'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/05/webindentc.html' title='webindent.c'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-5854392886755437498</id><published>2008-05-12T17:05:00.001-05:00</published><updated>2010-02-08T22:10:26.294-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='psnup'/><category scheme='http://www.blogger.com/atom/ns#' term='publishing'/><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><category scheme='http://www.blogger.com/atom/ns#' term='postscript'/><category scheme='http://www.blogger.com/atom/ns#' term='bookbinding'/><title type='text'>Make a book</title><content type='html'>I had been wondering about how to create a printed book from the novel that I had written a couple of years ago and I just now got it in my head to put everything together. I'll list the steps that I took from a big ASCII file to the printed page.
&lt;ol&gt;
&lt;li&gt;Convert ASCII to LaTeX: (&lt;a href="http://www.google.com/search?q=not+so+short+introduction+to+latex"&gt;beyond the scope&lt;/a&gt; of this article)&lt;/li&gt;
&lt;li&gt;Produce a postscript file from the LaTeX source:
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;latex novel.tex&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;dvips novel.dvi&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Alternatively, if you're starting from an existing PDF (which is what I had to do, I had lost the LaTeX source) you can run pdftops to get to this step.&lt;/li&gt;
&lt;li&gt;Run &lt;tt&gt;psbook -q -s 8 novel.ps &gt; novel_bookorder.ps&lt;/tt&gt; &amp;mdash; this rearranges the postscript file so that pages are in the following order 8, 1, 2, 7, 6, 3, 4, and 5. The &lt;tt&gt;-s 8&lt;/tt&gt; means use a &lt;a href="http://en.wikipedia.org/wiki/Bookbinding#Modern_commercial_binding"&gt;signature&lt;/a&gt; of size 8. This will be useful during the next step.&lt;/li&gt;
&lt;li&gt;Run &lt;tt&gt;psnup -q -n 2 -p letter novel_bookorder.ps &gt; novel_book.ps&lt;/tt&gt; this puts two pages onto each 8.5x11 output page. Print the pages &lt;i&gt;back to back&lt;/i&gt;. We will now have 4 pages on each sheet, two on the front and two on the back. The page will be in landscape orientation, but the printing will be side-by-side portrait. Coupled with the previous command we can now fold over two pages to form an 8-page signature&lt;/li&gt;
&lt;li&gt;Combine the signatures (sewing, stapling, choose your method)&lt;/li&gt;
&lt;li&gt;clamp the sewn signatures and run hot glue along the spine of the book, this would be the time to add a cover.&lt;/li&gt;
&lt;/ol&gt;
This should work reasonably well. Though I have not had much luck with staples, they seem to contribute too much thickness to the spine and make clamping awkward. Sewing would likely work much better but I don't have any good suggestions for technique.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-5854392886755437498?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/5854392886755437498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=5854392886755437498' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/5854392886755437498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/5854392886755437498'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/05/make-book.html' title='Make a book'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-6270411362602365548</id><published>2008-04-20T15:57:00.002-05:00</published><updated>2010-02-08T22:11:07.231-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='manpage'/><category scheme='http://www.blogger.com/atom/ns#' term='dehexer'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>manpage</title><content type='html'>&lt;p&gt;If anyone is actually intending on installing dehexer, here is the manpage:&lt;/p&gt;
&lt;div style="border: 1px solid; padding: 1em;"&gt;
&lt;pre&gt;.\" Dehexer
.TH dehexer 1 "20 April 2008" "1.0" "dehexer"
.SH NAME
.B dehexer 
is a simple program that converts a file of ascii characters into
the equivalent binary file. Any character not in the range 0-9 or
letters not A-F or a-f are simply ignored.
.SH EXAMPLES
dehexer &lt; 
.I ASCII_FILE 
&gt; 
.I BINARY_FILE
.SH DESCRIPTION
dehexer is used to convert a human-readable (i.e. description of
the bytes) into an actual binary file. Thus we get "0a" is
transformed into the byte 00001010 on disk (of course, it would
actually be the bits themselves).
.SH OPTIONS
None, just do normal I/O redirection.
.SH FILES
.P 
.I /usr/share/man/man1/dehexer.1.gz
.SH SEE ALSO
.BR hexer(1)
.SH BUGS
No known bugs at this time. 
.SH AUTHOR
.nf
Chris Wilson (christopher.j.wilson@gmail.com)
This program is dedicated to the public domain.
.fi
.SH HISTORY
2008 - Written as a compliment to Hal Canary's hexer program.
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Gzip the above text and store it in &lt;pre&gt;/usr/share/man/man1/&lt;/pre&gt; (at least on my system).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-6270411362602365548?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/6270411362602365548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=6270411362602365548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/6270411362602365548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/6270411362602365548'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/04/manpage.html' title='manpage'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-6387264040452457023</id><published>2008-04-19T18:08:00.001-05:00</published><updated>2010-02-08T22:11:42.422-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dehexer'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='c'/><title type='text'>dehexer</title><content type='html'>&lt;p&gt;I was looking through &lt;a href="http://halcanary.org/vv/"&gt;Hal&lt;/a&gt;'s blog when I came across his &lt;a href="http://halcanary.org/vv/2007/03/11/676/"&gt;hexer&lt;/a&gt; program. I thought that I should write the complimentary program, that is, given an ascii file of hex characters (e.g. "01CAFEBABE") it will write actual bytes to stdout.
&lt;pre&gt;
chris@papaya:c$ cc helloworld.c
chris@papaya:c$ ./a.out 
Hello World!
chris@papaya:c$ cat a.out | ./hexer | ./dehexer &gt; helloworld
chris@papaya:c$ chmod a+x helloworld
chris@papaya:c$ ./helloworld 
Hello World!
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
It seems to work (I changed the name to 'helloworld' because doing 
&lt;pre&gt;cat a.out | ./hexer | ./dehexer &gt; a.out&lt;/pre&gt;
seems to clobber the file in a bad way.&lt;/p&gt;

Without further ado:
&lt;div style="border: 1px solid; padding: 1em;"&gt;
&lt;pre&gt;
/* dehexer - Convert an ascii file of hex characters into the
   corresponding binary file. Any non-hex characters are silently
   skipped (newlines, tabs, etc.)
   Copyright 2008 Christopher Wilson, based in part on hexer by Hal
   Canary (also DTPD)
   Dedicated to the Public Domain */
/* cc -o dehexer dehexer.c */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
int main (int argc, char *argv[])
{
  char x;
  int char_out = 0;
  int low = 0; // LSBs, 1 for true
  while (fread(&amp;x, sizeof(x), 1, stdin) == 1) {
    if (x &gt; 47 &amp;&amp; x &lt; 58) { 
      // digit is 0-9
      x = x - 48;
      handle_byte(x, &amp;char_out, low);
    } else if (x &gt; 64 &amp;&amp; x &lt; 71) {
      // digit is A-F
      x = x - 55;
      handle_byte(x, &amp;char_out, low);
    } else if (x &gt; 96 &amp;&amp; x &lt; 103) {
      // digit a-f
      x = x - 87;
      handle_byte(x, &amp;char_out, low);
    } else {
      // skip anything that isn't 0-9A-Z, or a-z
      continue;
    }
    low = (low + 1) % 2; // flip the high/low bit marker
  }
  return(0);
}

/* handle_byte - if low is true then it prints the full byte. If low
     is false, set char_out to 16 times x.
*/
int handle_byte(int x, char *char_out, int low)
{
  if(low) {
    *char_out += x;
    putc(*char_out, stdout);
  } else {
    *char_out = x * 16;
  }
  return 0;
}
/* EOF */
&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-6387264040452457023?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/6387264040452457023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=6387264040452457023' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/6387264040452457023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/6387264040452457023'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/04/dehexer.html' title='dehexer'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-5496013015350042838</id><published>2008-04-13T18:18:00.001-05:00</published><updated>2010-02-08T22:12:30.030-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comments'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='modestproposal'/><title type='text'>Comments</title><content type='html'>So I've had this idea bouncing around in my head and I'm not sure why. Well that's not true, if I were so unsure I don't think that I'd post this. Maybe it is the idea of what's going on with a project called &lt;a href="http://stupidfilter.org/main/"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;StupidFilter&lt;/span&gt;&lt;/a&gt;. It is pretty much what its name would suggest. Its aim is to create a software filter that would remove &lt;span style="font-style: italic;"&gt;stupid&lt;/span&gt; blog comments (or any other content that you'd like to filter). Note that by my use of 'stupid' above, I'm not really talking about stupidity &lt;span style="font-style: italic;"&gt;per &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;se&lt;/span&gt;, &lt;/span&gt;(because that's very likely a &lt;a href="http://www.google.com/search?q=hard+problem"&gt;hard problem)&lt;/a&gt;. No, what I'm talking about may be more akin to a &lt;i&gt;symptom&lt;/i&gt; of stupidity? Or maybe just gross violations of proper &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_2"&gt;English&lt;/span&gt;, which doesn't really speak to a person's intelligence...

I had been thinking about what would be the simplest, most brain-dead method for identifying stupidity in text. The first thing that sprang to mind was &lt;a href="http://en.wikipedia.org/wiki/Information_entropy"&gt;entropy&lt;/a&gt;. Entropy is the measure of how much uncertainty there is in something (at least as it applies to information theory). A coin toss has 1 bit of entropy, it is calculated like so:
&lt;center&gt;&lt;img src="http://upload.wikimedia.org/math/1/3/7/137b5b84854f98251322fdd8d325e018.png" /&gt;&lt;/center&gt;
So we get -1/2 * log(1/2) + -1/2 * log(1/2) = 1

I wrote the following code: &lt;a href="http://codepad.org/cqB5DgEn"&gt;here&lt;/a&gt; (which you can actually run, thanks &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;codepad&lt;/span&gt;!). You'll notice that the text from a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;YouTube&lt;/span&gt; comment has a higher entropy than some text that I typed in. I'm actually just going by the letters, no punctuation is included. My hypothesis here is that badly mangled text will have a higher entropy than normal &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_5"&gt;English&lt;/span&gt;. Perfectly random text (i.e. text with all 26 letters equally likely) has an entropy of 4.7 bits. This makes sense, since if you'd want to encode all the letters of the alphabet in binary, you'd need at least 5 bits (2^5 = 32, first power of two greater than 26). I think if I include punctuation and all that I may get a better "reading" because an exclamation point, being rare in normal text at least, would have a longer &lt;a href="http://en.wikipedia.org/wiki/Huffman_coding"&gt;Huffman coding&lt;/a&gt; (I haven't really thought about this, could be wrong) and thus lend more to the entropy.

My next idea was taken from my cryptography class. English has a certain frequency distribution for the letters (and numbers, punctuation etc.) that we can exploit. A string of 25 '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;z's&lt;/span&gt; in a row doesn't "look" like any standard sentence. We expect, roughly, that as the length of an English text increases the frequencies of the letters should approach 13% 'e', 9% 't', 8% 'a', and so on (&lt;a href="http://en.wikipedia.org/wiki/Letter_frequencies#Relative_frequencies_of_letters_in_the_English_language"&gt;List here&lt;/a&gt;). I wrote a very simple program &lt;a href="http://codepad.org/XNUIM2aP"&gt;here&lt;/a&gt;. I took the sum of the squared differences from the "normal" distribution as a "distance" measurement. We would expect a very long text to get very close to zero (i.e. the frequency distributions will tend to match).

Both of these are really simple and would need a lot of work (multiplying together, weighting?) to be in in any way practical. But both constitute a very simple test of English-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;ness&lt;/span&gt;, basically, does the target text resemble English (at least statistically).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-5496013015350042838?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/5496013015350042838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=5496013015350042838' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/5496013015350042838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/5496013015350042838'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/04/comments.html' title='Comments'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8006842399638506937.post-273207934612882641</id><published>2008-04-11T17:27:00.001-05:00</published><updated>2010-02-08T22:13:47.515-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='misc'/><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><category scheme='http://www.blogger.com/atom/ns#' term='oldposts'/><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Catching up!</title><content type='html'>&lt;span style="font-weight: normal;"&gt;Here are some posts that I've done recently. I'm moving them here because of the simplicity of using Blogger.&lt;/span&gt;
&lt;h3&gt;Fri, 04 Apr 2008&lt;/h3&gt; &lt;div class="entry"&gt; &lt;b&gt;&lt;a name="demise"&gt;Stories of the Earth's Demise...&lt;/a&gt;&lt;/b&gt; &lt;p&gt;It may be the case that the Earth  &lt;a href="http://backreaction.blogspot.com/2008/04/black-holes-at-lhc-what-can-happen.html"&gt;isn't doomed&lt;/a&gt; if the &lt;a href="http://lhc.web.cern.ch/lhc/"&gt;LHC&lt;/a&gt; produces a tiny  black hole as the product of a high-energy collision. Read about the &lt;a href="http://news.google.com/news?hl=en&amp;amp;q=cern+lawsuit&amp;amp;btnG=Search"&gt;lawsuit&lt;/a&gt; that sparked the rebuttal.&lt;/p&gt;  &lt;p&gt;&lt;small&gt;Posted 2008-Apr-04 18:27&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;&lt;h3&gt;Wed, 02 Apr 2008&lt;/h3&gt; &lt;div class="entry"&gt; &lt;b&gt;&lt;a name="bilingual"&gt;Learning a new language can be hard&lt;/a&gt;&lt;/b&gt; &lt;p&gt;I decided that I needed to try and pick up a new "language." Language deserves the scare quotes here because I'm referring to  &lt;a href="http://vim.sourceforge.net/index.php"&gt;Vim&lt;/a&gt;. I know that emacs will probably remain my editor of choice, but I didn't want the whole vi side of the earth to remain an editor of last resort. I should be able to get around in vimopolis even if I can't converse fluently with the locals.&lt;/p&gt;  &lt;p&gt;That said. I do find some of its features pretty appealing. It just seems to get out of your way in a fashion that emacs doesn't do. And I like the idea that if you know a movement command, say 'w' for moving over a &lt;em&gt;w&lt;/em&gt;ord and 'c' for &lt;em&gt;c&lt;/em&gt;hanging something then you can put them together to have vim delete the word that you're sitting on and drop the cursor right in place to type a new one.&lt;/p&gt;  &lt;p&gt;So it is nice to see how &lt;a href="http://en.wikipedia.org/wiki/Editor_war"&gt;the other half&lt;/a&gt; lives.&lt;/p&gt;  &lt;p&gt;&lt;small&gt;Posted 2008-Apr-02 13:42&lt;/small&gt; &lt;/p&gt;&lt;/div&gt; &lt;h3&gt;Fri, 28 Mar 2008&lt;/h3&gt; &lt;div class="entry"&gt; &lt;b&gt;&lt;a name="streetview"&gt;I've been googled!&lt;/a&gt;&lt;/b&gt; &lt;p&gt;I just saw that my house is now (sort of) visible with Google street view. You can check it out &lt;a href="http://maps.google.com/maps?f=q&amp;amp;hl=en&amp;amp;geocode=&amp;amp;q=306+s.+yellowstone+dr.+madison,+wi&amp;amp;sll=37.0625,-95.677068&amp;amp;sspn=48.240201,82.265625&amp;amp;ie=UTF8&amp;amp;ll=43.065455,-89.493384&amp;amp;spn=0.010942,0.020084&amp;amp;z=16&amp;amp;layer=c&amp;amp;cbll=43.062022,-89.492663&amp;amp;cbp=1,226.87369415653313,,0,-1.7143089794735504"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The driveway in the foreground leads up to my place. This will be nice for hosting parties, or anytime someone needs to know what the area around my house looks like. I have one of those places that is tucked away off the main road and so is usually hard to find.&lt;/p&gt;  &lt;p&gt;&lt;small&gt;Posted 2008-Mar-28 15:41&lt;/small&gt; &lt;/p&gt;&lt;/div&gt; &lt;h3&gt;Tue, 25 Mar 2008&lt;/h3&gt; &lt;div class="entry"&gt; &lt;b&gt;&lt;a name="entropy"&gt;Entropy function&lt;/a&gt;&lt;/b&gt; &lt;p&gt;I find myself re-typing this into lisp all the time, so here it is, chiseled into digital stone:&lt;/p&gt;&lt;pre&gt;
(defun entropy (probs)                                                
         (* -1 (apply #'+ (mapcar #'(lambda (p) (* p (log p 2))) probs))))
&lt;/pre&gt;
Usage:
&lt;pre&gt;CL-USER&gt; (entropy '(0.5 0.5))1.0
1.0&lt;/pre&gt;

&lt;p&gt;Just don't expect it to make sure the probabilities sum to 1!&lt;/p&gt;  &lt;p&gt;&lt;small&gt;Posted 2008-Mar-25 23:16&lt;/small&gt; &lt;/p&gt;&lt;/div&gt; &lt;h3&gt;Mon, 24 Mar 2008&lt;/h3&gt; &lt;div class="entry"&gt; &lt;b&gt;&lt;a name="encryption"&gt;Affine cipher&lt;/a&gt;&lt;/b&gt; &lt;p&gt;I wrote a little program &lt;a href="http://pages.cs.wisc.edu/%7Ecwilson/progs/encrypt.py"&gt;here&lt;/a&gt; to do simple affine encryption. I saw something very much like it elsewhere (can't think of where right now). It gives you the option to do a simple &lt;a href="http://en.wikipedia.org/wiki/Affine_cipher"&gt;affine cipher&lt;/a&gt;, but be careful it will take the function &lt;em&gt;y = ax + b&lt;/em&gt; (mod 26) so you can very easily find an &lt;em&gt;a&lt;/em&gt; with no &lt;a href="http://en.wikipedia.org/wiki/Multiplicative_inverse"&gt;multiplicative inverse&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Caveat_emptor"&gt;caveat emptor&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;If you're interested, and really how could you not be, here is the source code:&lt;/p&gt;  &lt;pre&gt;&lt;code&gt;#!/usr/bin/env python
from sys import argv, exit

letters = "abcdefghijklmnopqrstuvwxyz"

def usage():
 print """affine
 Do affine encryption (y = ax + b (mod 26)). Case insensitive."""

def to_num(c):
 """
 &gt;&gt;&gt; to_num('a')
 0
 &gt;&gt;&gt; to_num('z')
 25
 """
 c = c.lower()
 if c in letters:
  return letters.find(c)
 else:
  return -1

def to_letter(num):
 """
 &gt;&gt;&gt; to_letter(0)
 'a'
 &gt;&gt;&gt; to_letter(25)
 'z'
 &gt;&gt;&gt; to_letter(34)
 """
 if num &gt;= 0 and num &lt;= 25:   return str(letters[num])  else:   return None  def e(a,b,msg):  """  &gt;&gt;&gt; e(1,1,"cat")
 'dbu'
 """
 out = ""
 for c in msg:
  x = to_num(c)
  if x == -1:
    out = out + c
  else:
    out = out + to_letter( (to_num(c) * a + b) % 26 )
 return out

def main():
 if len(argv) != 4:
  usage()
  exit(0)
 a = int(argv[1])
 b = int(argv[2])
 message = str(argv[3])
 print e(a,b,message)

def _test():
 import doctest
 doctest.testmod()

if __name__ == "__main__":
 #_test()
 main()
&lt;/code&gt;&lt;/pre&gt;&lt;a&gt;&lt;b&gt;  &lt;/b&gt;&lt;/a&gt;&lt;p&gt;&lt;a&gt;&lt;b&gt;&lt;small&gt;Posted 2008-Mar-24 19:28&lt;/small&gt; &lt;/b&gt;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;a&gt;&lt;b&gt; &lt;/b&gt;&lt;/a&gt;&lt;h3&gt;&lt;a&gt;&lt;b&gt;Thu, 20 Mar 2008&lt;/b&gt;&lt;/a&gt;&lt;/h3&gt;&lt;a&gt;&lt;b&gt; &lt;/b&gt;&lt;/a&gt;&lt;div class="entry"&gt;&lt;a&gt;&lt;b&gt; &lt;/b&gt;&lt;/a&gt;&lt;a name="emacs"&gt;Emacs autosave&lt;/a&gt; &lt;p&gt;Emacs, the best text editor in the world, has this distressing habit of making backup files all over the place. If I'm writing something about the &lt;em&gt;Square Root of Christmas&lt;/em&gt;, say &lt;code&gt;sqrtxmas.txt&lt;/code&gt;, then I'll get a little file like &lt;code&gt;sqrtxmas.txt~&lt;/code&gt; in the same directory. It is nice if I lose the file for some reason, but otherwise it can be something of a nuisance.&lt;/p&gt;  &lt;p&gt;I found &lt;a href="http://snarfed.org/space/gnu%20emacs%20backup%20files"&gt;this&lt;/a&gt; website with the remedy. Props to you dude for making the best text editor in the &lt;strike&gt;world&lt;/strike&gt; universe even betterer. You can visit the website for more details, but just to reproduce this little gem in one more place, here it is:&lt;/p&gt;  &lt;pre&gt;;; Put autosave files (ie #foo#) in one place, *not*
;; scattered all over the file system!
(defvar autosave-dir
(concat "/tmp/emacs_autosaves/" (user-login-name) "/"))

(make-directory autosave-dir t)

(defun auto-save-file-name-p (filename)
(string-match "^#.*#$" (file-name-nondirectory filename)))

(defun make-auto-save-file-name ()
(concat autosave-dir
(if buffer-file-name
(concat "#" (file-name-nondirectory buffer-file-name) "#")
(expand-file-name
(concat "#%" (buffer-name) "#")))))

;; Put backup files (ie foo~) in one place too. (Thebackup-directory-alist
;; list contains regexp=&gt;directory mappings; filenames matching a regexp are
;; backed up in the corresponding directory. Emacs will mkdir it if necessary.)
(defvar backup-dir (concat "/tmp/emacs_backups/" (user-login-name) "/"))
(setq backup-directory-alist (list (cons "." backup-dir)))
&lt;/pre&gt;  &lt;p&gt;&lt;small&gt;Posted 2008-Mar-20 10:56&lt;/small&gt; &lt;/p&gt;&lt;/div&gt; &lt;div class="entry"&gt; &lt;a name="vote"&gt;Voting machines&lt;/a&gt; &lt;p&gt;I have a bit of a problem with voting machines. Not the paper system because that seems to be a &lt;a href="http://www.cnonline.net/%7ETheCookieJar/math_jokes_02.html"&gt;problem that has already been solved&lt;/a&gt;. What concerns me is the seeming lack of transparency of electronic voting machines. There is a recent &lt;a href="http://www.nj.com/news/index.ssf/2008/03/voting_machine_maker_threatens.html"&gt;story&lt;/a&gt; about New Jersey voting officials being told that they may not seek independent security audits of their voting machines. Over on &lt;a href="http://en.wikipedia.org/wiki/Ed_Felten"&gt;Ed Felten&lt;/a&gt;'s blog, &lt;em&gt;&lt;a href="http://www.freedom-to-tinker.com/?p=1265"&gt;Freedom to Tinker&lt;/a&gt;&lt;/em&gt; he has posted the e-mail that the voting company sent him. He has previouly demonstrated that some voting machines can be &lt;a href="http://www.youtube.com/watch?v=8JESZiLpBLE"&gt;hacked&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;small&gt;Posted 2008-Mar-20 10:41&lt;/small&gt; &lt;/p&gt;&lt;/div&gt; &lt;h3&gt;Wed, 19 Mar 2008&lt;/h3&gt; &lt;div class="entry"&gt; &lt;a name="first"&gt;YACB&lt;/a&gt; &lt;p&gt;Yet another "chris blog"? What's up? &lt;/p&gt;  &lt;p&gt;I guess I've decided that I write enough stuff on my &lt;a href="http://www.facebook.com/"&gt;Facebook&lt;/a&gt;, &lt;a href="http://myspace.com/"&gt;Myspace&lt;/a&gt; and even &lt;a href="http://www.orkut.com/"&gt;Orkut&lt;/a&gt; (remember that?) that it justifies just keeping a semi-regular blog. Besides, my cs account allows for cgi scripts and an easy shell-access so that it allows me to write in my favorite &lt;acronym title="Content Management System"&gt;CMS&lt;/acronym&gt;, &lt;a href="http://www.blosxom.com/"&gt;Blosxom&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I'll see how long I keep at it, but if my past record is anything to go by, I've done okay.&lt;/p&gt;  &lt;p&gt;&lt;small&gt;Posted 2008-Mar-19 19:47&lt;/small&gt; &lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8006842399638506937-273207934612882641?l=twopoint718.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://twopoint718.blogspot.com/feeds/273207934612882641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8006842399638506937&amp;postID=273207934612882641' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/273207934612882641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8006842399638506937/posts/default/273207934612882641'/><link rel='alternate' type='text/html' href='http://twopoint718.blogspot.com/2008/04/catching-up.html' title='Catching up!'/><author><name>Chris</name><uri>http://www.blogger.com/profile/03097657129811885396</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://myspace-102.vo.llnwd.net/00610/20/14/610964102_l.jpg'/></author><thr:total>1</thr:total></entry></feed>
