<?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-2953233889171032598</id><updated>2011-08-25T05:08:16.007-07:00</updated><category term='firefox'/><category term='circuits'/><category term='math'/><category term='obfuscation'/><category term='javascript'/><category term='tex'/><category term='git'/><category term='shell'/><category term='haskell'/><category term='perl'/><category term='vm'/><category term='script'/><category term='icfp'/><category term='postscript'/><category term='bash'/><category term='greasemonkey'/><category term='go'/><title type='text'>for(;;);</title><subtitle type='html'>A programming blog for the strange and esoteric (and sometimes mundane, too).</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-1510281216686501763</id><published>2011-03-15T14:55:00.001-07:00</published><updated>2011-03-15T15:48:48.836-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><title type='text'>Version controlling my home directory</title><content type='html'>I recently rearranged my home directories on my work machines and decided it was time to finally get my configuration under a proper version control.  I found several blogs about this, but &lt;a href='http://tensixtyone.com/perma/the-version-controlled-home-directory'&gt;one&lt;/a&gt; was particularly useful.  I've changed it a little, but here's the basic set up.&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;&lt;pre&gt;$ mkdir ~/.config.git&lt;br /&gt;$ cd ~/.config.git&lt;br /&gt;$ git init --bare&lt;br /&gt;$ git config core.worktree ../&lt;br /&gt;&lt;/pre&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;Now I have a git repository called &lt;code&gt;~/.config.git&lt;/code&gt;, but it needs special environment variables set so that accidentally calling &lt;code&gt;git&lt;/code&gt; outside a normal repository won't trigger it to do things to my config repo.  The next step is to make it easier to use this repo.  I wrote the following to &lt;code&gt;~/bin/git-home&lt;/code&gt;:&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;&lt;pre&gt;#!/bin/bash&lt;br /&gt;export GIT_DIR=$HOME/.config.git&lt;br /&gt;export GIT_WORK_TREE=$HOME&lt;br /&gt;git "$@"&lt;br /&gt;&lt;/pre&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;Now calling "&lt;code&gt;git home ...&lt;/code&gt;" explicitly sets the repository to my config repo.  But this still isn't so convenient.  So I added the following to my (now version-controlled) &lt;code&gt;.bashrc&lt;/code&gt; file, at a point &lt;i&gt;after&lt;/i&gt; completions are loaded:&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;&lt;pre&gt;alias hgit='git home'&lt;br /&gt;complete -o bashdefault -o default -o nospace -F _git hgit 2&gt;/dev/null \&lt;br /&gt;        || complete -o default -o nospace -F _git hgit&lt;br /&gt;&lt;/pre&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;This sets up &lt;code&gt;hgit&lt;/code&gt; with completions.  Finally, I don't want &lt;code&gt;hgit status&lt;/code&gt; to show tons of untracked files.  So I added the following &lt;code&gt;~/.config.git/info/exclude&lt;/code&gt;:&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;&lt;pre&gt;[^.]*&lt;br /&gt;!.*/*&lt;br /&gt;*~&lt;br /&gt;&lt;/pre&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;Beneath that is a list of specific exclusions, which I'll keep expanding as I discover files and directories I don't want to track.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-1510281216686501763?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/1510281216686501763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=1510281216686501763' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/1510281216686501763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/1510281216686501763'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2011/03/version-controlling-my-home-directory.html' title='Version controlling my home directory'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-1149235447259802641</id><published>2011-03-14T12:14:00.001-07:00</published><updated>2011-03-14T12:21:36.643-07:00</updated><title type='text'>Happy Pi Day 2011!</title><content type='html'>&lt;pre style='font-size:80%'&gt;&lt;br /&gt;                              \let~\catcode~`z0&lt;br /&gt;                        ~`'01~`,02~`406~`@11~`=13zdef&lt;br /&gt;                    =41'~`4113zgdef,=$$41'~`4113zcountdef&lt;br /&gt;                 ,=++41'~`4113zlet,=AA'B!d6l;8p/Pa5Nr.eq3Ei[&lt;br /&gt;              DSm@|H9c]o1M?TgJk-CF2*tnIj7Rf,=""'2d-NDDRIeMj|Nir&lt;br /&gt;            -n-;.g./pjkCm1Bg;J7R3Ie!kmEae9djCEe6t8Dt@lpdCcM?or8m8&lt;br /&gt;          rat]F3i.1m;[5M*agFiotMTml7a/Rd/pMe/|lB5-jca*iCIc!??9n.g!/&lt;br /&gt;        mq2etc8MfSj8rmko-SSStB21plt?et5tNNT?BliPqi51Je8l|[-p.n.9/Tp[H&lt;br /&gt;       a9[gkcTk[d/!ie5]F!iT[ri|kPDPHdaNrBp[Tp!.ra1j;.i8fd851i?BoS5||2m&lt;br /&gt;      iE.F|Mq*.EcPq*-rB812?[C|MnCHnke|D13o|l3Rt/73p-[lf-/C3|kHan[Sqi!E2&lt;br /&gt;     ltCiJEa*@]22dNng8RrpnoBk5DtH*9cH!rRdiEj|3tiBrPBBHEn8l|.e5593o3JPp;g&lt;br /&gt;    i1pkS]Dp52SilElS-mt8l.2kgD]!ac]n-JPDReD@[JP?lNT6N-dEPNnNpIkNH/1@gNFCd&lt;br /&gt;   e869SNnfCf9]*|6ni8BPeD7M519rq-;T3IPSt*6-F@@BP68D?-|/5DN?e5Hp3[BBHNk31|H&lt;br /&gt;  9ge.maeERBqTc3tp@pNIpDtEqMeS.pe5FmHJ.-eDmpmC.8P;g1!1/[PDt/JDH1Bl]@1qmlPiJ&lt;br /&gt;  N*PacC?1md;!!NE/k.S99I98gqpcn9c8NaEao[!1!kJfm99adfi1jp*/5Dea-R-1d8;I?|gPl&lt;br /&gt; ][ai-;8kgHlJ?cS3S-ic;ceE.EJn|nke2;Sa1!FIoadp1EBCig*[//9|55DJ.cqDB@6lERPP5-q&lt;br /&gt; cC.go-n3fE5;7-9faJf8Fo]gcEHa6.midi@f-/CHNHe/R7p|dqp|@do-q2qB3NEalCold3?*8B6&lt;br /&gt; D1jFq7-Ek@.icJ]l|F@-]n-HprI@pJNBCccN*;NR5lk.!5!M?M*ID;e@7ce/!Ef[ggt5jiHP/]N&lt;br /&gt; F-p1e[ESmS@g-kc;/p29[HE/MSnClCkMtn1ppHJ*g[f@Ilak6DeJM..o.;?P/19I-?!BE*]a!lq&lt;br /&gt; /an?5D7l9M]98d2M32|DJ2?5r|5Be|aa1J]|]Mn]TTqa?.k[ki2qrlfoHc@E;8R9Djime;J]M5S&lt;br /&gt; NiS;S[FPe91Ht-FR|aN..m6n99SeP7tT8qoRqecn97gHE/E!om?9]E9dPDTB*Pdt[dolk/kRj9o&lt;br /&gt; ]/RH9NfD8Rq2ra/2/N[H5J.aI3SkadJpfRDFT/mr]ECdPm|TTJDe1.;9.!mk-a.qCorTm*DfDp?&lt;br /&gt; Eqk2cI!JfNojFTPt@fSeCpaI!6C;TSd!|T?fFoNgJ@p|R8|aRHf16NPlrkiTnDgBdJ;Nn6D*ocn&lt;br /&gt;  kC8?r2TgF?68PDF7aN*9.68|1gg31.B-k3-I;5]2kRplq..]j|Eq5JmeE7iSI;;fp/25|/-gE&lt;br /&gt;  -Tdqf;D*S6RFg9@|n*mRJS?9orI/HNJiT|o!8,=[[',+]][$CC0C0$TT1T25+&amp;&amp;zadvance+*&lt;br /&gt;   *zmultiply+//zdivide+##zifnum[[+))zfi+((zifx+||zelse[[+&gt;&gt;zexpandafter+;&lt;br /&gt;    ;zxdef[[+::zgdef[[=z}}4142'&gt;;zcsname41zendcsname'42,,[[=z{{41'zcsname&lt;br /&gt;     41zendcsname,[[=!!41';]']41,,+z\\zthe[[=PP4142$'}41'\C,&amp;C1:A'42,,=V&lt;br /&gt;      V'&gt;PA$(A]|&gt;V),V=GG'TC/C10*C10&amp;T-C/C10!'\T,,[=DD414243'&gt;C{'43,*C50&lt;br /&gt;       &gt;T{'42,&amp;CT*C50&gt;T{'41,&amp;CTGGGGGzfutureletAV,=YY41',:V'(A$&gt;Y|&gt;D),!&lt;br /&gt;        3!.&gt;D"$$RR2R38$YY3Y-R&amp;Y1$XX5[[=SS4142$'41:]'42,,=OO'&gt;S]$,[[=Q&lt;br /&gt;          Q41'T41*T41&amp;CT,=HH'C0QXQYC-CQR,=BB'#X&amp;lt;RH#C&amp;lt;0P|O)&amp;X1&gt;B),=L&lt;br /&gt;            L'#Y&amp;lt;RX-Rzhbox'B,&amp;Y2&gt;L),=PP'zhskip0.5em,zvbox'zttL,[:&lt;br /&gt;              Y41',;A'bYryYge,=::41i'&gt;{&gt;'A,,~`412:stephen.hicks&lt;br /&gt;                 3.14159265358979323846264338327950288419716&lt;br /&gt;                    9399375105820974944592307816406286208&lt;br /&gt;                        99862803482534211706798214808&lt;br /&gt;                              ..........kthxbai&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For those who can't run TeX, the output is &lt;a href='http://pages.physics.cornell.edu/~shicks/pi2.pdf'&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-1149235447259802641?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/1149235447259802641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=1149235447259802641' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/1149235447259802641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/1149235447259802641'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2011/03/happy-pi-day-2011.html' title='Happy Pi Day 2011!'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-8282582676692949746</id><published>2010-11-21T14:50:00.000-08:00</published><updated>2010-11-21T15:01:52.716-08:00</updated><title type='text'>Manual dependency resolution</title><content type='html'>Sometimes the tools one has at one's disposal just aren't smart enough.  I wanted to profile a Haskell program and found out that I needed to reinstall all my libraries with profiling support, and cabal-install just wasn't smart enough to do it very well.  I would try compiling my program with profiling support and it would complain about library X.  I would try reinstalling library X and it would complain about library Y, and so on, ad nauseum.  I seem to recall having a similar problem bootstrapping cabal-install in the first place.  Here are a few shell functions I wrote that should make this process not quite so painful:&lt;pre&gt;push () { &lt;br /&gt;  STACK=("$1" "${STACK[@]}")&lt;br /&gt;  pop&lt;br /&gt;}&lt;br /&gt;pop () {&lt;br /&gt;  local TOP="${STACK[0]}";&lt;br /&gt;  run "$TOP" &amp;&amp; &lt;br /&gt;    unset STACK[0] &amp;&amp;&lt;br /&gt;    STACK=("${STACK[@]}") &amp;&amp;&lt;br /&gt;    if [ -n "${STACK[*]}" ]; then&lt;br /&gt;      pop&lt;br /&gt;    fi&lt;br /&gt;}&lt;br /&gt;run () {&lt;br /&gt;  cabal install --reinstall -p "$1"&lt;br /&gt;}&lt;/pre&gt;Obviously one would redefine "&lt;code&gt;run&lt;/code&gt;" as appropriate.  For instance, the initial cabal bootstrap might look like &lt;pre&gt;run () {&lt;br /&gt;  cd $1&lt;br /&gt;  for cmd in configure build install; do&lt;br /&gt;    runghc Setup.*hs $cmd&lt;br /&gt;  done&lt;br /&gt;}&lt;/pre&gt; and I would "&lt;code&gt;push $PWD&lt;/code&gt;" after downloading and unzipping each package.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-8282582676692949746?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/8282582676692949746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=8282582676692949746' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/8282582676692949746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/8282582676692949746'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2010/11/manual-dependency-resolution.html' title='Manual dependency resolution'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-4415348235251405799</id><published>2010-03-14T17:14:00.000-07:00</published><updated>2010-04-14T02:25:13.243-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><category scheme='http://www.blogger.com/atom/ns#' term='tex'/><category scheme='http://www.blogger.com/atom/ns#' term='math'/><title type='text'>Happy Pi Day!</title><content type='html'>&lt;pre&gt;              \let~\catcode&lt;br /&gt;          ~`z0~`'1~`,2~`q13~`z#&lt;br /&gt;       14~`46zdefq41'~`4113zgdef,q&lt;br /&gt;     QQ41'~`4113zlet,qBB415425'41-P#&lt;br /&gt;    7427,QPPzexpandafterqAA414243'H#H&lt;br /&gt;   42434341542415,qCC41742743'41i-D42#&lt;br /&gt;  434343,qww',zedefw'PPPCPBAyap!,qEE',q&lt;br /&gt; 6641'~`4113zcountdef,QNNzifnum6RR1R20E6&lt;br /&gt; YY2QAAzadvanceY-RAY1QMMzmultiply6XX3EqS&lt;br /&gt; S'Ezhskip0.5em,EQJJzjobnameEQmmwE6TT5qj&lt;br /&gt; j4142x'41zgdefm'42,,EQ!!zglobalE6CC7Eqr&lt;br /&gt; r41'T41MT41ACT,qHH'C0rXrYC-CrR,qOO'zifx&lt;br /&gt; mEPjwxEzelsePjmxzfi,qcc'NX&amp;lt;RHNC&amp;lt;0Szelse&lt;br /&gt;  OEzfiAX1PczelseE!AY2zfi,EzedefzJ'J,qv&lt;br /&gt;   v'@,zifxzJvQOO*zfiEqll'NY&amp;lt;RX-Rzhbox&lt;br /&gt;    'c,Plzfi,zttl~`z612qii41h',~`zx0i&lt;br /&gt;     3.14159265358979323846264338327&lt;br /&gt;       950288419716939937510582097&lt;br /&gt;          494459230781640628620&lt;br /&gt;              899...kthxbye&lt;/pre&gt;There's even an Easter egg (try running with &lt;code&gt;-jobname @&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;For those who can't run TeX, the outputs are &lt;a href='http://www.physics.cornell.edu/~shicks/pi.pdf'&gt;here&lt;/a&gt; and &lt;a href='http://www.physics.cornell.edu/~shicks/pi@.pdf'&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-4415348235251405799?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/4415348235251405799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=4415348235251405799' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/4415348235251405799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/4415348235251405799'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2010/03/happy-pi-day.html' title='Happy Pi Day!'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-1314789141510851989</id><published>2010-01-24T00:47:00.001-08:00</published><updated>2010-03-09T22:31:18.483-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><category scheme='http://www.blogger.com/atom/ns#' term='shell'/><category scheme='http://www.blogger.com/atom/ns#' term='script'/><title type='text'>Hostname mangling</title><content type='html'>Here's some bash code I wrote today for navigating my home network (the names have been changed to protect the innocent).  I have three computers that live on my LAN, and I've instructed my router's DHCP server to assign each computer a fixed IP address.  Thus, &lt;tt&gt;baley&lt;/tt&gt;=192.168.1.10, &lt;tt&gt;gladia&lt;/tt&gt;=192.168.1.11, and &lt;tt&gt;fastolfe&lt;/tt&gt;=192.168.1.12.  The goal is that I'd like to be able to access any of these computers from within the LAN, as well as from the outside (via a dyndns, &lt;tt&gt;sdh.yi.org&lt;/tt&gt;).&lt;br /&gt;&lt;br /&gt;First, I set up port forwarding on the router (essid &lt;tt&gt;solaria&lt;/tt&gt;) to forward 2210 to &lt;tt&gt;baley&lt;/tt&gt;, 2211 to &lt;tt&gt;gladia&lt;/tt&gt;, and 2212 to &lt;tt&gt;fastolfe&lt;/tt&gt;.  I then added the respective ports to each host's &lt;tt&gt;/etc/ssh/sshd_config&lt;/tt&gt; file (in addition to the regularly-scheduled port 22).  Ideally I could simply add these names to my &lt;tt&gt;/etc/hosts&lt;/tt&gt; file and be done with it, but because of the port issue, it's not quite that simple.  Also, I have a different user name on &lt;tt&gt;fastolfe&lt;/tt&gt; (steve) than I have on the others (sdh), and I'd rather not have to mess with that.&lt;br /&gt;&lt;br /&gt;The solution I came up with is shell functions.  I define &lt;tt&gt;ssh&lt;/tt&gt; and &lt;tt&gt;scp&lt;/tt&gt; to be functions, and parse the arguments to find any instances of these hostnames.  I then do some work to figure out which LAN I'm on, so that I can short-circuit the router if possible.  Without further ado, here's the functions:&lt;pre&gt;WIRELESS=wlan0&lt;br /&gt;function essid {&lt;br /&gt;  iwconfig $WIRELESS |&lt;br /&gt;    perl -ne 'print $1 if /ESSID:"([^"]*)"/' 2&gt; /dev/null&lt;br /&gt;}&lt;br /&gt;function ssh {&lt;br /&gt;  local args=()&lt;br /&gt;  while [ -n "$*" ]; do&lt;br /&gt;    case "$1" in&lt;br /&gt;      baley)&lt;br /&gt;        case "$(essid)" in&lt;br /&gt;          solaria)&lt;br /&gt;            args=("${args[@]}" sdh@192.168.0.10) ;;&lt;br /&gt;          *)&lt;br /&gt;            args=("${args[@]}" -p 2210 sdh.yi.org) ;;&lt;br /&gt;        esac ;;&lt;br /&gt;      gladia)&lt;br /&gt;        case "$(essid)" in&lt;br /&gt;           solaria)&lt;br /&gt;             args=("${args[@]}" sdh@192.168.0.11) ;;&lt;br /&gt;           *)&lt;br /&gt;             args=("${args[@]}" -p 2211 sdh.yi.org) ;;&lt;br /&gt;        esac ;;&lt;br /&gt;      fastolfe)&lt;br /&gt;        case "$(essid)" in&lt;br /&gt;          solaria)&lt;br /&gt;            args=("${args[@]}" steve@192.168.0.12) ;;&lt;br /&gt;          *)&lt;br /&gt;            args=("${args[@]}" -p 2212 sdh.yi.org) ;;&lt;br /&gt;        esac ;;&lt;br /&gt;      *) args=("${args[@]}" "$1") ;;&lt;br /&gt;    esac&lt;br /&gt;    shift&lt;br /&gt;  done&lt;br /&gt;  command ssh "${args[@]}"&lt;br /&gt;}&lt;br /&gt;function scp {&lt;br /&gt;  local args=()&lt;br /&gt;  while [ -n "$*" ]; do&lt;br /&gt;    local arg="$1"&lt;br /&gt;    case "$arg" in&lt;br /&gt;      baley:*)&lt;br /&gt;        case "$(essid)" in&lt;br /&gt;          solaria)&lt;br /&gt;            arg="${arg/baley/sdh@192.168.0.10}" ;;&lt;br /&gt;          *)&lt;br /&gt;            arg="${arg/baley/sdh@sdh.yi.org}"&lt;br /&gt;            args=('-P' '2210' "${args[@]}") ;;&lt;br /&gt;        esac ;;&lt;br /&gt;      gladia:*)&lt;br /&gt;        case "$(essid)" in&lt;br /&gt;          solaria)&lt;br /&gt;            arg="${arg/gladia/sdh@192.168.0.11}" ;;&lt;br /&gt;          *)&lt;br /&gt;            arg="${arg/gladia/sdh@sdh.yi.org}"&lt;br /&gt;            args=('-P' '2211' "${args[@]}") ;;&lt;br /&gt;        esac ;;&lt;br /&gt;      fastolfe:*)&lt;br /&gt;        case "$(essid)" in&lt;br /&gt;          solaria)&lt;br /&gt;            arg="${arg/fastolfe/steve@192.168.0.12}" ;;&lt;br /&gt;          *)&lt;br /&gt;            arg="${arg/fastolfe/steve@sdh.yi.org}"&lt;br /&gt;            args=('-P' '2212' "${args[@]}") ;;&lt;br /&gt;        esac ;;&lt;br /&gt;    esac&lt;br /&gt;    args=("${args[@]}" "$arg")&lt;br /&gt;    shift&lt;br /&gt;  done&lt;br /&gt;  command scp "${args[@]}"&lt;br /&gt;}&lt;/pre&gt;Now I can throw this onto any shell account I use (with appropriate modifications to the &lt;tt&gt;WIRELESS&lt;/tt&gt; variable) and source it in my .bashrc to access any of my computers as if it had its own public IP address.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-1314789141510851989?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/1314789141510851989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=1314789141510851989' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/1314789141510851989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/1314789141510851989'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2010/01/hostname-mangling.html' title='Hostname mangling'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-4459896033299021309</id><published>2009-12-01T23:46:00.000-08:00</published><updated>2009-12-02T00:00:00.465-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='go'/><title type='text'>Fibonacci in Go</title><content type='html'>I've been playing around with Go a bit.  Here's what I think is the most Go-like solution to producing the Fibonacci sequence.&lt;pre&gt;package main&lt;br /&gt;&lt;br /&gt;import "fmt"&lt;br /&gt;&lt;br /&gt;func dup3(in &lt;-chan int) (&lt;-chan int,&lt;-chan int,&lt;-chan int) {&lt;br /&gt;  a,b,c := make(chan int,2),make(chan int,2),make(chan int,2);&lt;br /&gt;  go func() { for { x := &lt;-in; a &lt;- x; b &lt;- x; c &lt;- x } }();&lt;br /&gt;  return a,b,c&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func fib() &lt;-chan int {&lt;br /&gt;  x := make(chan int,2);&lt;br /&gt;  a,b,out := dup3(x);&lt;br /&gt;  go func() { x&lt;-0; x&lt;-1; &lt;-a; for { x&lt;- &lt;-a + &lt;-b } }();&lt;br /&gt;  return out&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;func main() {&lt;br /&gt;  x := fib();&lt;br /&gt;  for i:=0; i&lt;10; i++ { fmt.Println(&lt;-x) }&lt;br /&gt;}&lt;/pre&gt;I like it because I only ever declare a single integer variable, and the rest goes through chans.  This solution is inspired by Haskell's concise "&lt;tt&gt;fib = 0:zipWith (+) fib (1:fib)&lt;/tt&gt;".  Any comments are most welcome.  In particular, if there were a way to accomplish it (in the same style) without the buffered chans, that would be pretty cool (though I'd be a bit surprised, since it doesn't seem possible at first glance).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-4459896033299021309?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/4459896033299021309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=4459896033299021309' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/4459896033299021309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/4459896033299021309'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2009/12/fibonacci-in-go.html' title='Fibonacci in Go'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-7212800742820654003</id><published>2009-11-17T17:16:00.000-08:00</published><updated>2009-11-17T21:00:25.954-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='circuits'/><title type='text'>Oscilloscope Pong</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_7-BQLQdH_p0/SwN9MDdJWaI/AAAAAAAAAzQ/HOqIJCGnRF8/s1600/scan0208.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 271px;" src="http://3.bp.blogspot.com/_7-BQLQdH_p0/SwN9MDdJWaI/AAAAAAAAAzQ/HOqIJCGnRF8/s400/scan0208.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5405301623814183330" /&gt;&lt;/a&gt;&lt;br /&gt;This was originally my final project for my undergraduate electronics lab.  Now that I've finally defended my PhD, I've got some free time and am getting around to posting it.  I'd been meaning to write up for a long time (about 7 years!).  Of course, after writing it up in LaTeX, that still doesn't help with blogging, since TeX/EPS/PDF isn't such a great format for web viewing.  Fortunately, before I hunkered down to write my thesis I somehow converted all these figures into PNG (I haven't the slightest idea how I did it anymore - anything I try lately looks terrible).  You can download the PDF version &lt;a href='http://pages.physics.cornell.edu/~shicks/pong.pdf'&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;h3&gt;Introduction&lt;/h3&gt;The very first arcade game was Pong, created in the late 1970s. In its time, it was the height of digital technology. We return to this historic video game from a slightly different point of view. In the following pages we will construct an entirely analog version of Pong that can be played using a modern oscilloscope with an X-Y setting (which draws channel 1 on the X axis and channel 2 on the Y axis).&lt;br /&gt;&lt;h3&gt;Circuits&lt;/h3&gt;Here we look at the circuit from the top-down, starting with the big picture fitting all the subcircuits together, and then analyzing each individual subcircuit.&lt;br /&gt;&lt;h2&gt;Big picture&lt;/h2&gt;In Pong, there are three objects which must be drawn: the ball and the two paddles. We select the object to draw using a very fast triangle wave. At the extents, either paddle is drawn. In the middle, the ball is drawn.  This is represented in the figure below. The lines CB, CP&lt;sub&gt;1&lt;/sub&gt;, and CP&lt;sub&gt;2&lt;/sub&gt; serve as controls, allowing the corresponding signals (B&lt;sub&gt;x,y&lt;/sub&gt;, P&lt;sub&gt;1&lt;/sub&gt;, and P&lt;sub&gt;2&lt;/sub&gt;, respectively) to pass on to the scope only when the control is high. Thus, at any time, we need exactly one of CB, CP&lt;sub&gt;1&lt;/sub&gt;, or CP&lt;sub&gt;2&lt;/sub&gt; to be high.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_7-BQLQdH_p0/SwMW99gjJvI/AAAAAAAAAyY/aQRz_1faKJ8/s1600/controls.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 303px; height: 260px;" src="http://4.bp.blogspot.com/_7-BQLQdH_p0/SwMW99gjJvI/AAAAAAAAAyY/aQRz_1faKJ8/s400/controls.png" border="0" alt="Control signals"id="BLOGGER_PHOTO_ID_5405189231513642738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The main circuit consists of two parts. We need to have an output for the scope x position and the scope y position, respectively, shown in "Scope Output" below.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7-BQLQdH_p0/SwMW91StxBI/AAAAAAAAAyg/AV-gHet7lY4/s1600/scopeoutput.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 363px; height: 400px;" src="http://2.bp.blogspot.com/_7-BQLQdH_p0/SwMW91StxBI/AAAAAAAAAyg/AV-gHet7lY4/s400/scopeoutput.png" border="0" alt="Scope Output"id="BLOGGER_PHOTO_ID_5405189229308134418" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h2&gt;Analog Switch&lt;/h2&gt;The main workhorse of an analog Pong is the analog switch, denoted in the above schematics as a crossed circle, as shown in the figure. Using a series of analog switches, we can draw multiple objects on the oscilloscope at once. The analog switch we use here is constructed from an op-amp and an nJFET shown in the figure "Analog Switch" below. It allows the input signal to pass if and only if the control lead is above +5V. The input is sufficiently blocked when the control is grounded. More discussion of this circuit is given in the next section. We can add the output from several analog switches using an op-amp addition circuit.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7-BQLQdH_p0/SwMW-DX80II/AAAAAAAAAyo/VmEd9F7mbRw/s1600/analogswitch.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://2.bp.blogspot.com/_7-BQLQdH_p0/SwMW-DX80II/AAAAAAAAAyo/VmEd9F7mbRw/s400/analogswitch.png" border="0" alt="Analog Switch"id="BLOGGER_PHOTO_ID_5405189233088188546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h2&gt;Control Signal&lt;/h2&gt;The control signals CB, CP&lt;sub&gt;1&lt;/sub&gt;, and CP&lt;sub&gt;2&lt;/sub&gt; are generated from a master control signal C. This master control signal, as explained above, is simply a fast triangle wave (I've forgotten the frequency), generated by the circuit shown in "Output Control" below.  We then generate CP1 and CP2 by comparing C to 5V, such that CP&lt;sub&gt;1&lt;/sub&gt; is high when C&lt;-5V and CP&lt;sub&gt;2&lt;/sub&gt; is high when C&gt;+5V.  We must be very careful to prevent any possible overlap in the control signals. Thus, we generate CB as CP1+CP2, as shown below.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_7-BQLQdH_p0/SwMW-oL5AAI/AAAAAAAAAyw/CNsVJGxv93g/s1600/outputcontrol.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 392px; height: 400px;" src="http://1.bp.blogspot.com/_7-BQLQdH_p0/SwMW-oL5AAI/AAAAAAAAAyw/CNsVJGxv93g/s400/outputcontrol.png" border="0" alt="Output Control"id="BLOGGER_PHOTO_ID_5405189242969718786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h2&gt;Ball Position&lt;/h2&gt;We generate the ball position from a pair of slow (1/3 to 3Hz) triangle waves, shown in "Ball Position" below.  These circuits each have a pair of potentiometers: R&lt;sub&gt;1&lt;/sub&gt; and R&lt;sub&gt;3&lt;/sub&gt; adjust the y- and x-amplitudes of the ball's motion and should be adjusted so that the ball's motion fills the oscilloscope screen, currently designed to be ±4V vertically and ±5V horizontally. R&lt;sub&gt;2&lt;/sub&gt; and R&lt;sub&gt;4&lt;/sub&gt; adjust the y- and x-speeds.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7-BQLQdH_p0/SwMW-7EtFMI/AAAAAAAAAy4/WPvkrFGmFwM/s1600/ballposition.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 334px;" src="http://2.bp.blogspot.com/_7-BQLQdH_p0/SwMW-7EtFMI/AAAAAAAAAy4/WPvkrFGmFwM/s400/ballposition.png" border="0" alt="Ball Position"id="BLOGGER_PHOTO_ID_5405189248039851202" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h2&gt;Paddles&lt;/h2&gt;The vertical paddle positions are given by the lines P&lt;sub&gt;1&lt;/sub&gt; and P&lt;sub&gt;2&lt;/sub&gt;, which we construct with a voltage divider, shown below in "Paddles". The potentiometers R&lt;sub&gt;8&lt;/sub&gt; and R&lt;sub&gt;9&lt;/sub&gt; should be large and easy to adjust (i.e., a joystick) and are used to move the paddles up and down. R&lt;sub&gt;6&lt;/sub&gt; and R&lt;sub&gt;7&lt;/sub&gt; control the vertical range of the paddles' motion (i.e. from -3V to +3V). Whlie there's no theoretical problem with using them, small potentiometers are hard to find, so we insert an op-amp buffer to decrease the output impedance instead.&lt;br /&gt;&lt;br /&gt;In order to make the paddle appear as more than a point, we add a fast (about 10kHz, so that the entire length of the paddle is drawn each time CP&lt;sub&gt;&lt;i&gt;i&lt;/i&gt;&lt;/sub&gt; is high) triangle wave signal LEN, shown also in "Paddles", to the Y output whenever we're drawing the paddles (i.e. when CB-bar is high). The potentiometer P&lt;sub&gt;5&lt;/sub&gt; controls the size of the paddles (around ±1V).&lt;br /&gt;&lt;br /&gt;The horizontal positions are fixed at ±5V, that is, either edge of the screen.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_7-BQLQdH_p0/SwMXhDTygnI/AAAAAAAAAzA/46LiD-hCX3I/s1600/paddles.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 399px;" src="http://4.bp.blogspot.com/_7-BQLQdH_p0/SwMXhDTygnI/AAAAAAAAAzA/46LiD-hCX3I/s400/paddles.png" border="0" alt="Paddles"id="BLOGGER_PHOTO_ID_5405189834366157426" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h2&gt;Power Supply&lt;/h2&gt;We assume that the breadboard setup includes ±12V and ground, but we may need to generate our own ±5V lines, which can be done cleanly with a simple voltage divider fed through a 411 op-amp buffer (shown in PDF only).&lt;br /&gt;&lt;h3&gt;Improvements&lt;/h3&gt;&lt;h2&gt;Hit detection and scoring&lt;/h2&gt;The circuit shown so far is more of an interactive movie than a game. The controls can alter the size and position of the paddles, but can't react differently if the ball is hit or missed. I attempted to add logic to deal with this case using a D-type flip flop as shown in "Hit Detection" below, where B'&lt;sub&gt;x&lt;/sub&gt; and B'&lt;sub&gt;y&lt;/sub&gt; are sent to the scope instead of B&lt;sub&gt;x&lt;/sub&gt; and B&lt;sub&gt;y&lt;/sub&gt;. As the design currently stands, it simply hides the ball until a reset button is pressed. The inputs D&lt;sub&gt;&lt;i&gt;i&lt;/i&gt;&lt;/sub&gt; must change when B&lt;sub&gt;y&lt;/sub&gt; is within a paddle length of the P&lt;sub&gt;&lt;i&gt;i&lt;/i&gt;&lt;/sub&gt;, and the clock signals CLK&lt;sub&gt;&lt;i&gt;i&lt;/i&gt;&lt;/sub&gt; should go off only at the very tips of the master control signal C. Finally, the "g" and "r" diodes should be green and red LEDs to show who missed.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_7-BQLQdH_p0/SwMXhQQSsyI/AAAAAAAAAzI/WJYFeRPB-oo/s1600/hitdetection.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 194px;" src="http://1.bp.blogspot.com/_7-BQLQdH_p0/SwMXhQQSsyI/AAAAAAAAAzI/WJYFeRPB-oo/s400/hitdetection.png" border="0" alt="Hit Detection?"id="BLOGGER_PHOTO_ID_5405189837841150754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately, this addition caused some impedance problems and smeared the whole picture terribly, and I was never able to fix it.&lt;br /&gt;&lt;h2&gt;Dynamic ball speeds&lt;/h2&gt;One other modification that would be nice would be to allow the ball speeds (at least the vertical speed) to change based on how the paddles hit it. If there was some way to lock-in a "resistance" based on, say, B&lt;sub&gt;y&lt;/sub&gt;-P&lt;sub&gt;i&lt;/sub&gt; at a certain point, rather than using semi-fixed potentiometer, then it might not be so difficult. Likely we'd want another sort of flip flop, but I never looked very far into how that might be accomplished.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-7212800742820654003?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/7212800742820654003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=7212800742820654003' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/7212800742820654003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/7212800742820654003'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2009/06/oscilloscope-pong.html' title='Oscilloscope Pong'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_7-BQLQdH_p0/SwN9MDdJWaI/AAAAAAAAAzQ/HOqIJCGnRF8/s72-c/scan0208.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-5575506926583645379</id><published>2009-06-29T20:38:00.000-07:00</published><updated>2009-06-29T21:30:02.999-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><category scheme='http://www.blogger.com/atom/ns#' term='vm'/><category scheme='http://www.blogger.com/atom/ns#' term='icfp'/><title type='text'>ICFP Contest 2009</title><content type='html'>It's been just about a year and I haven't posted anything...  I've got a few drafts of posts, so maybe I'll try to get one or two of them done this summer.  Anyway, this weekend was the ICFP contest.  I don't have near as much to say about it as last year, mainly since I only spent about 16 hours working on it, starting Sunday afternoon, along with David Roundy and some help from our friend Joanna.&lt;br /&gt;&lt;h3&gt;The problem&lt;/h3&gt;&lt;br /&gt;It was an interesting problem this year.  Teams were required to implement a virtual machine to run "OrbitVM" binaries provided by the contest organizers.  Then the interesting part was writing a controller to perform certain tasks in orbital dynamics (in 2d), ranging from doing a simple Hohmann transfer to change the radius of a circular orbit, to flying around to collect a number of satellites.  The physics seems like it would be interesting to work out, but we didn't really get around to it.  Just thinking about it, though, an orbit about a single body in 2d has four parameters: the semimajor axis (for simplicity, I'll assume it's an ellipse), the eccentricity, the orientation of the major axis, and the phase along the orbit.  These can be calculated from the position and velocity (x, y, v&lt;sub&gt;x&lt;/sub&gt;, and v&lt;sub&gt;y&lt;/sub&gt;) of a satellite.  On the controls side, there are only two "knobs" we can control: the impulses in the tangential and radial directions.  So we can see that it can't be trivial to transfer from any orbit to any other, and in fact we could probably define some sort of metric to describe how distant two particular orbits are (minimizing a cost function composed of total impulse and time required).  Of course, even with just elliptical orbits, this is well beyond the realm of tractability, but if it were implementable, it would lead to some sort of traveling salesman problem, except that the distances varied with time in incommensrate ways.  What a mess... (not to mention the real problem also had a moon to make the orbits less than elliptical, and was integrated with a large enough time step to make the integration error somewhat important)&lt;br /&gt;&lt;h3&gt;Our solution&lt;/h3&gt;&lt;br /&gt;That's enough abstraction.  I enjoyed working on the contest, although we only solved the first sub-problem of performing a Hohmann transfer.  With only one day, there really wasn't any chance to outdo last year's performance, but we decided to have some fun with it anyway. The original plan was to do it in postscript, so our team name was "Paper Jam in Tray 3".  But it turned out that rolling our own IEEE doubles was just too tedious (postscript only supports singles natively), and the extra precision was important (at least, in the Verlet integrator David wrote).  So instead we implemented all of our logic in the OrbitVM virtual machine.  It wouldn't have been completely terrible to write straight assembler, but I felt it would be more fun to write a compiler, so we embedded an OrbitVM a compiler into Haskell.  It was a pretty simple compiler, and would have benefited greatly from more developed control structures (the VM itself was rather lacking in control structures: every instruction was executed and every mutable value in memory was written to exactly once per time step; the only control structure was a conditional copy that could copy from one of two memory locations, depending on the result of a comparison).  We did implement a static data type, Vector, that simplified dealing with 2d coordinates and velocities, but the part that was most frustrating to deal with was maintaining state from one time step to the next; with some more thought I believe it could have been improved quite a bit.&lt;br /&gt;&lt;br /&gt;We also had to find some way to connect these programs together.  A perl script provided good plumbing and also allowed us to intercept the communication and visualize the trajectories with ghostscript, as well as allowing us to inspect some of the internal quantities to see what was going wrong.&lt;br /&gt;&lt;br /&gt;I spent a number of hours, after we finally got some points on the scoreboard, trying to get the second problem, but without a more sophisticated development system, it was difficult to try new ideas and we never quite managed to catch any moving satellites, although I was able to fly by them briefly (just the velocities were all wrong by the time the positions matched up).  The basic strategy I used (at least for the case of both satellites in circular orbits) was to calculate the required "phase difference" for when to start the transfer such that I landed on the second orbit just as the target was passing by.  This got me close, but not quite close enough, and I never figured out how to do the tiny tweaks of the orbit to close in.  It might be fun to make a "real-time" orbit simulator to get some intuition for how to do this.  There would be some orbiting circle and the goal would be to pilot a spacecraft into an orbit within the circle using a combination of radial and tangential burns.  Though maybe once you're looking at it in the rotating frame it would just be a piece of cake.  We never actually looked at the rotating frame, which was maybe our problem...&lt;br /&gt;&lt;h3&gt;Download&lt;/h3&gt;&lt;br /&gt;In case you're curious, our source tree is available at &lt;a href='http://pages.physics.cornell.edu/~shicks/darcs/icfp09/'&gt;http://pages.physics.cornell.edu/~shicks/darcs/icfp09/&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-5575506926583645379?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/5575506926583645379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=5575506926583645379' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/5575506926583645379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/5575506926583645379'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2009/06/icfp-contest-2009.html' title='ICFP Contest 2009'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-1086372766226029847</id><published>2008-07-16T13:12:00.000-07:00</published><updated>2009-06-13T18:05:23.987-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='icfp'/><category scheme='http://www.blogger.com/atom/ns#' term='tex'/><title type='text'>ICFP Contest 2008</title><content type='html'>(Browse or download the code at &lt;a href='http://www.physics.cornell.edu/~shicks/icfp08/'&gt;http://www.physics.cornell.edu/~shicks/icfp08&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;So, I just finished sleeping off a "double all-nighter" for the &lt;a href='http://www.icfpcontest.org/'&gt;ICFP Programming Contest&lt;/a&gt;.  The task this year was to write a controller for a Mars rover.  The program would connect to a server which would send it periodic telemetry updates and then it would send back instructions, either Accelerate, Brake, Left, or Right.  I had tried to get a team together for this contest, but it was apparently a busy weekend and all my programmer friends had other plans.&lt;br /&gt;&lt;br /&gt;After thinking about the problem (and my situation as a solo entry) for a few minutes, I decided it would be interesting to see if I could write it in TeX.  Lately I've been writing a whole lot of TeX for Andy Ruina, as well as for a macro package (&lt;a href='http://www.ctan.org/tex-archive/macros/latex/contrib/inlinedef/'&gt;inlinedef&lt;/a&gt;) I recently submitted to CTAN, so the idea didn't seem too crazy ("When all you've got is a hammer...").&lt;!--&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&gt;&lt;h3&gt;Initial Work&lt;/h3&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;The first problem that arose immediately after I decided on TeX was that TeX has no network access.  So I had to make a small concession in writing a small Perl wrapper to do the networking.  In the end, this file would be under a hundred lines, so I considered it a necessary, but minimal, evil.  On one or two occasions I thought about farming some computation out to the Perl wrapper (such as trig), but in the end decided to stay pure.  I learned about the IO::Socket::INET library and used the IPC::Open2 package to open a socket and a two-way pipe to a TeX process.  Then we just read the TeX output and wait for special commands.  Occasionally we'll write "WANT" which is a signal to Perl that TeX is ready for the next packet of information.  Or else "HERE: " which tells Perl to send the following signal back to the server.  I coded this up and found that it was really all that was needed to connect TeX to the world.  Next, we needed to interpret the data.  The server sent plain text data in the form of&lt;br /&gt;&lt;pre&gt;  I 600.0 600.0 30000 60.0 ... ;&lt;/pre&gt; with a different number of mostly-numerical arguments depending on which letter came first (this determined what kind of datum it was).  Since TeX can already parse this sort of thing, I figured the best bet would be to just make these letters all 'active characters' inside TeX so that they acted like control sequences.  This worked well because occasionally multiple commands arrived on the same line, and so we'd need to do something special to account for this otherwise, but now it was automatic.  More often, however, TeX's requests for data were more frequent than the packets were arriving (this is a good thing), but TeX's request (\read) is blocking, so we just sent an empty line in this case.&lt;!--&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&gt;&lt;h3&gt;Math&lt;/h3&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;If I were writing this in a &lt;i&gt;real&lt;/i&gt; language like C++ or &lt;a href='http://www.haskell.org/'&gt;Haskell&lt;/a&gt;, one of the first things I would do would be to find or write a convenient data type for 2d vectors, since they're all over the place here.  But TeX doesn't even really support things as simple as floating-point multiplication or (even worse) division.  So I started by kyping some fixed-point multiplication and division macros I remembered seeing on comp.text.tex a while back (posted in the mid-90's by Donald Arseneau).  I also kyped Kevin Hamlen's sqrt macro from his CDLabels package that I'd remembered him boasting about.  These simple tools in hand, I was able to start making some real progress.  I defined a bunch of counters (integer variables) and lengths (fixed-point numbers) and some booleans to keep track of what time it was, where we were and wanted to go, and which way we wanted to turn (wow, alliteration).  Then, each time we received telemetry updates, I would turn towards the target if we were off by more than 20 degrees, brake if we were off by more than 90, and accelerate otherwise.&lt;br /&gt;&lt;br /&gt;Of course, to figure out how far off from the target we were, I needed an arctangent function, and this is definitely not provided by TeX.  So I set about to write \atan (I would have called it \atan2, since that's really what it was, but names can't have numbers normally).  Really about the only thing that was feasible to do here was a polynomial expansion.  I opened up Octave and plotted tan(x) next to x+x^3/3 (naturally) from 0 to pi/4, and it didn't look that great.  But it looked like I could probably do a better job by just tweaking the cubic coefficient by hand.  In the end, I settled on atan(x)~x-.2x^2 (sure, I could have optimized it without much difficulty - in fact I just did and it turns out that -.17297x^2 works slightly better, though I would have done really better with the cubic term -.26219x^3, which I've now implemented, or even better, -.05x^2-.18796x^3 -- thanks SciPy).  So I coded this up and it seemed to get the job done, anyway.  I downloaded the sample server and maps and watched how it worked on the simplest map, with no craters to crash into and die.  It didn't quite work, but a little tweaking of the numbers made a big difference and I was able to get home.  I went to bed Saturday morning around 7am (EDT) and got 7 hours sleep before I had to wake up for sailing and then having some people over to my apartment, all of which kept me busy until about 10pm.&lt;!--&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&gt;&lt;h3&gt;An inverse heisenbug&lt;/h3&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;According to the jargon file, a heisenbug is one that disappears when you try to debug it.  In this case, my code worked okay, but when I tried to see what it was doing by turning on visualization, it suddenly stopped working as well.  It wasn't too difficult to figure out that the visualization was slowing down the server so that it didn't deliver all the telemetry data in a timely way.  so I decided that I needed better timing.  It turns out that even turning on tracing to the log file in TeX is enough to reduce the resolution beyond workability, and in my final code, in later runs when there's a long list of obstacles, that starts slowing it down too much too.  TeX doesn't have any sort of timing functions (\time returns the time to the minute that the typesetting &lt;i&gt;began&lt;/i&gt; but is in fact constant).  So again comes Perl to the rescue.  Presumably I could have measured something like distance travelled at a known speed and backed out an estimate for the amount of time spent between iterations, but this would of course changed depending on the situation, so again, I felt justified in resorting to Perl here.  Now whenever TeX asked Perl for data, we included a timestamp in the response to keep our own clock.  This gave a much better resolution and we could then estimate where we were and make decisions about 10x as often.  By 2am Sunday, the rover could make it home consistently on the easy map with no dangers, but usually fell into craters on the more complicated ones, so this was the next thing to be addressed.&lt;!--&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&gt;&lt;h3&gt;Collision avoidance&lt;/h3&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;By far the most difficult (and frustrating) part of the contest was collision avoidance.  I tried a number of things to make it smarter, but they all failed miserably.  They typically did worse than before I tried to do anything.  Generally, I tried the logic that at any time we've got a target we're shooting for, and if at any time there was a known obstacle between the current position and the target, we'd move the target to a place that wasn't hindered (now that I'm writing this, I see the error here much more clearly).  Then we issue commands to steer us toward that new target.  If ever the path home was unblocked, we'd try to go there instead.&lt;br /&gt;&lt;br /&gt;It took a long time to get this code to behave as I wanted.  Often I'd find the rover turning the wrong direction entirely, driving straight into craters, driving straight for the outside edge of the map, or once, hitting the same boulder repeatedly until time ran out.  If I knew how to do it, it would be neat to stitch together all these bloopers and make a 2-3 minute youtube video of the bloopers and then see them gradually improve to the final result (yay for &lt;a href='http://www.darcs.net/'&gt;darcs&lt;/a&gt; that that's even possible).  Most helpful in this process was Octave (a free MATlab clone) - at one point I coded up a debugging message that printed out Octave code to plot a graph with lines from the current position to the target, the new trajectory, and the obstacle in question.  Often the new trajectory was worse than the original one and I could go step-by-step to figure out why that was happening.  Eventually when all these little errors were debugged, I had a code that did exactly what I wanted it to do, but it still did no better than if I'd done nothing at all to avoid the obstacles.  This was the way it went for most of Sunday (I took an hour nap before church, but otherwise spent the whole time working).  People on the IRC channel were talking about A*-algorithms and such, but that was much too smart for me - I had a hard enough time just getting to where I wanted to go when there &lt;i&gt;weren't&lt;/i&gt; obstacles - so I just kept plugging away.  &lt;br /&gt;&lt;br /&gt;Around dinner time, Geoff called and suggested I go to his house to watch a movie.  I was trying out a new idea I had, much simpler than many of the others: implement a two-state machine.  The rover is either in the running state, where it's turning towards home, or else it's in the swerving state, where it's avoiding an object.  If the rover sees an object in the way, closer than a certain distance (determined by the time it would take to turn 90 degrees at max speed, but this foolishly ignored the unknown turning &lt;i&gt;acceleration&lt;/i&gt;, which turned out to be pretty important, and could probably have been discovered without too much difficulty... if only I had a team), then it would start swerving away from the object.  The key point here was that we were looking ahead of us, rather than looking always toward home.  So surprisingly we stopped running into things!  I eventually converged on the logic that it would keep turning until it was no longer obstructed, and then it would go into a tunnel-vision mode, heading straight forward until the object it was swerving past was directly perpendicular with its direction, so that we know it's passed before trying to turn back home.  This revealed all sorts more bugs as my dot product apparently just didn't work, but eventually I got it all worked out so that by the time I went over to Geoff and Erin's, I had a working version to show them, swerving back and forth and reaching the goal about 80% of the time.  Around this time I also called up David Roundy and told him what I was up to.  He suggested a few things, including the team name I finally settled on (actually, I think this was his sister-in-law), The Lone TeXnician, and a bit about what I should do with my README file.&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;&lt;h3&gt;The icing on top&lt;/h3&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;By early Monday morning, all I had left to do was clean it up, package it, and make sure it worked on the LiveCD environment that would be used in judging.  The latter part was actually a bit difficult and I had been working on and off the whole time to figure out how to install TeX on the system with neither internet connection (apt-get would have been too easy...) or sending in a 50MB tarball with all of the basic TeXLive ditribution in it.  I eventually figured out how to get a 2MB portion of the distribution to work by copying files from my /usr/bin/ and /usr/share/texmf/ and running `texhash` over and over again.  I spent most of the rest of my time on an extra feature I really wanted.  I would use LaTeX's picture environment to draw a map of the planet and trace the path that the rover followed.  It took a while to get this working - I started out trying to make a single picture per trial and had grouping issues.  I switched to using a separate (but overlapping) picture for each thing I wanted to draw, but they didn't line up properly.  I tried saving all the drawing commands to a token list so that I could draw the whole thing at once at the end of the trial, but token list operations are O(n) in the length, so I started lagging way behind and couldn't keep up with the server (it was real-time, remember).  Ultimately, I tracked down all but a small issue which caused misalignment only later in the process.  This was eventually fixed when I found the errors, both in the swerving code (as I should have realized when they started so late and the trajectory up until them was straight, but then it curved - if I had painted the two modes in different colors like I originally wanted to, it would have been even more blatantly obvious!).  Both errors came from putting decimal numbers where an integer was expected (stupid non-typed languages...) resulting in the fractional part being typeset instead of used mathematically, and pushing the reference point away from where it belonged.&lt;!--&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;--&gt;I ended up submitting code that I was very proud of.  It ignored the ravenous martians entirely, and had a hard time in some tight situations (and some not-so-tight), but in general it made its way home about as well as (or better than) you might expect for 1200 lines of TeX.  I ended up getting 8 hours of sleep over the course of three nights, and promptly crashed for 17 hours.&lt;br /&gt;&lt;br /&gt;You can &lt;a href='http://www.physics.cornell.edu/~shicks/icfp08/'&gt;browse or download the code&lt;/a&gt; if you like.  I've cleaned it up a little bit since submission, in particular using better trig approximations I worked out while writing this.  If you want to run it, you'll probably need a *nix system.  You'll also need to download the &lt;a href='http://smlnj.org/icfp08-contest/simulator.html'&gt;simulation server and maps&lt;/a&gt; (remember to use '-v' to get a visualization window).  Pass the '-l' option to `texsocket` to run in LaTeX and get the PDF output.  Unfortunately I don't deal with disconnecting servers very well in the version I submitted, so it doesn't actually produce the PDF (more than) half the time and never gives any hint as to why.&lt;br /&gt;&lt;br /&gt;Edit: &lt;a href="http://www.physics.cornell.edu/~shicks/icfp08/proof.png"&gt;pictures&lt;/a&gt; and &lt;a href="http://www.physics.cornell.edu/~shicks/icfp08/proof.pdf"&gt;pdf&lt;/a&gt; &lt;a href="http://www.physics.cornell.edu/~shicks/icfp08/random.pdf"&gt;documents&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Edit 2: Shortly after the contest ended, I learned of pdftex's built-in timers, which one of the commenters noted.  I also learned about /dev/tcp (although the contest LiveCD didn't have it compiled into bash anyway).  With all that working together, I could presumably have written a completely TeX solution (although blocking vs. non-blocking network access would certainly be an issue... maybe if TeX forked an extra process of itself...).  Also, since it's now public knowledge, I did indeed win the judges prize.&lt;br /&gt;&lt;br /&gt;I've turned off comments because of spam.  If you want to say something, feel free to email me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-1086372766226029847?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/1086372766226029847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=1086372766226029847' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/1086372766226029847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/1086372766226029847'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2008/07/icfp-contest-2008.html' title='ICFP Contest 2008'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-6228272541319824986</id><published>2007-06-22T20:06:00.000-07:00</published><updated>2007-06-22T23:08:10.496-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><category scheme='http://www.blogger.com/atom/ns#' term='postscript'/><title type='text'>PostScript libraries</title><content type='html'>I've been writing some PostScript lately, such as matrix multiplication routines: things that really belong in a library.  So I spent a good chunk of time today writing some software for preparing postscript files to be libraries.  I wrote a Perl script `curdle` which takes a PostScript file as input and compresses it to a binary encoding with no comments and minimal spaces.  At some point I'll add a script which will rename long internal variable names (as directed by comments).  Once the file is compacted, it can be run through encode85 (which I found on some random FTP site) and put into a resource file a big block of gibberish, which is then either included automatically by the PostScript viewer, or else pasted at the top of the PostScript file which includes it.  In any case, it should help significantly with PostScript library version control.  Especially when I automate the resource part and include a "built on" date in the header.&lt;br /&gt;&lt;br /&gt;If you're interested you can get the most up-to-date version of it with darcs (or just browse to this directory):&lt;br /&gt;&lt;br /&gt;darcs get &lt;a href="http://www.physics.cornell.edu/~shicks/darcs/pslib/"&gt;http://www.physics.cornell.edu/~shicks/darcs/pslib/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-6228272541319824986?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/6228272541319824986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=6228272541319824986' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/6228272541319824986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/6228272541319824986'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2007/06/postscript-libraries.html' title='PostScript libraries'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-5828513064423770720</id><published>2007-05-29T11:40:00.000-07:00</published><updated>2007-06-22T20:23:12.579-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='greasemonkey'/><title type='text'>Blogger pain</title><content type='html'>I get frustrated when Blogger wants to "Save as Draft" whenever I hit Ctrl+D.  I usually expect this keystroke to ask as delete.  So I hit it often, and get annoyed when it loads a new page.  So I fixed it.  Here's another &lt;a href="http://www.physics.cornell.edu/~shicks/bloggerkeys.user.js"&gt;Greasemonkey script&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-5828513064423770720?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/5828513064423770720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=5828513064423770720' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/5828513064423770720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/5828513064423770720'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2007/05/blogger-pain.html' title='Blogger pain'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-2630988512056956021</id><published>2007-05-29T09:59:00.000-07:00</published><updated>2010-11-23T18:35:22.266-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='greasemonkey'/><title type='text'>Firefox + Google Scholar + Cornell Library</title><content type='html'>So, I was sick of having to go through the CU Library homepage for every journal article I wanted to download at home. And so I wrote a quick and dirty plugin to add a link to each Google Scholar result to access it through the CU Library proxy automatically, this saving gobs of time (maybe someday as much time as I spent writing it in the first place!).&lt;br /&gt;&lt;br /&gt;One (small) issue with this is that it only works if you're logged into CUWebLogin, but checking for that each time is very slow. So I actually make two links - the "login" link goes through the official channels while the other link attempts to bypass them and go directly to the article, so it should be quicker if you're already logged in. It probably wouldn't be too tough to edit it to work for a different school with a little investigation.&lt;br /&gt;&lt;br /&gt;To use the plugin, you need to have GreaseMonkey, which is a pretty standard Firefox plugin allowing you to use any of a multitude of "user scripts" which are basically scripts people write to post-process webpages.&lt;br /&gt;&lt;br /&gt;I also wrote a standalone plugin to add a button to the (right-click) context menu to access a page through the library, in case it came from somewhere other than Google Scholar.  This one is only the slow access method, although it could be configured to access it quicker with enough demand.&lt;br /&gt;&lt;br /&gt;At some point, I may integrate all this into a standalone plugin.  And I may look into adding a configuration tool so that other university libraries will be usable (although I'd need help from others for this to work).  For now, if you're at a different school and would like to try using this, talk to me and I'll see if I can hack together a version for you.&lt;br /&gt;&lt;h3&gt;Installation&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;Install &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/748&amp;amp;h=152ed4005314c60fb406228b1c854e55"&gt;Greasemonkey&lt;/a&gt; if you haven't already.&lt;/li&gt;&lt;li&gt;Install the &lt;a href="http://www.physics.cornell.edu/%7Eshicks/googlescholarviacornell.user.js"&gt;userscript&lt;/a&gt; for Google Scholar links.&lt;/li&gt;&lt;li&gt;Install the browser plugin for the context menu:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.physics.cornell.edu/~shicks/culibrary.xpi"&gt;firefox&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.physics.cornell.edu/~shicks/culibrary.crx"&gt;chrome&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;EDIT(2010 Nov 23): Added Chrome extension.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-2630988512056956021?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/2630988512056956021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=2630988512056956021' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/2630988512056956021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/2630988512056956021'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2007/05/firefox-google-scholar-cornell-library.html' title='Firefox + Google Scholar + Cornell Library'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2953233889171032598.post-6040823570079829373</id><published>2006-10-11T08:50:00.000-07:00</published><updated>2009-09-08T23:53:20.420-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='obfuscation'/><category scheme='http://www.blogger.com/atom/ns#' term='tex'/><title type='text'>Obfuscated TeX</title><content type='html'>I just came accross the following TeX program:&lt;br /&gt;&lt;pre style='font-size:90%'&gt;\let~\catcode~`76~`A13~`F1~`j00~`P2jdefA71F~`7113jdefPALLF&lt;br /&gt;PA''FwPA;;FPAZZFLaLPA//71F71iPAHHFLPAzzFenPASSFthP;A$$FevP&lt;br /&gt;A@@FfPARR717273F737271P;ADDFRgniPAWW71FPATTFvePA**FstRsamP&lt;br /&gt;AGGFRruoPAqq71.72.F717271PAYY7172F727171PA??Fi*LmPA&amp;&amp;71jfi&lt;br /&gt;Fjfi71PAVVFjbigskipRPWGAUU71727374 75,76Fjpar71727375Djifx&lt;br /&gt;:76jelse&amp;U76jfiPLAKK7172F71l7271PAXX71FVLnOSeL71SLRyadR@oL&lt;br /&gt;RrhC?yLRurtKFeLPFovPgaTLtReRomL;PABB71 72,73:Fjif.73.jelse&lt;br /&gt;B73:jfiXF71PU71 72,73:PWs;AMM71F71diPAJJFRdriPAQQFRsreLPAI&lt;br /&gt;I71Fo71dPA!!FRgiePBt'el@ lTLqdrYmu.Q.,Ke;vz vzLqpip.Q.,tz;&lt;br /&gt;;Lql.IrsZ.eap,qn.i. i.eLlMaesLdRcna,;!;h htLqm.MRasZ.ilk,%&lt;br /&gt;s$;z zLqs'.ansZ.Ymi,/sx ;LYegseZRyal,@i;@ TLRlogdLrDsW,@;G&lt;br /&gt;LcYlaDLbJsW,SWXJW ree @rzchLhzsW,;WERcesInW qt.'oL.Rtrul;e&lt;br /&gt;doTsW,Wk;Rri@stW aHAHHFndZPqpa.rtMRrgeLinZ.irLtYer.W,:jbye&lt;/pre&gt;&lt;br /&gt;You'd never guess by looking at it that it prints the entire song of the 12 Days of Christmas.  Amazing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2953233889171032598-6040823570079829373?l=sdh33b.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sdh33b.blogspot.com/feeds/6040823570079829373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=2953233889171032598&amp;postID=6040823570079829373' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/6040823570079829373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2953233889171032598/posts/default/6040823570079829373'/><link rel='alternate' type='text/html' href='http://sdh33b.blogspot.com/2006/10/obfuscated-tex.html' title='Obfuscated TeX'/><author><name>Steve</name><uri>http://www.blogger.com/profile/17764004568545705634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://www.physics.cornell.edu/~shicks/photo.jpg'/></author><thr:total>2</thr:total></entry></feed>
