{"id":805,"date":"2009-09-10T12:41:21","date_gmt":"2009-09-10T12:41:21","guid":{"rendered":"http:\/\/scientopia.org\/blogs\/goodmath\/2009\/09\/10\/two-dimensional-pathological-beauty-snusp\/"},"modified":"2009-09-10T12:41:21","modified_gmt":"2009-09-10T12:41:21","slug":"two-dimensional-pathological-beauty-snusp","status":"publish","type":"post","link":"http:\/\/www.goodmath.org\/blog\/2009\/09\/10\/two-dimensional-pathological-beauty-snusp\/","title":{"rendered":"Two Dimensional Pathological Beauty: SNUSP"},"content":{"rendered":"<p><em>I&#8217;m currently away on a family vacation, and as soon as vacation is over, I&#8217;m off on a business trip for a week. And along the way, I&#8217;ve got some deadlines for my book. So to fill in, I&#8217;m recycling some old posts. I decided that it&#8217;s been entirely too long since there was any pathological programming &#8217;round these parts, so I&#8217;m going to repost some of my favorites.<\/em><\/p>\n<p>Todays programming language insanity is a real delight &#8211; it&#8217;s one<br \/>\nof my all-time favorites. It&#8217;s a language<br \/>\ncalled SNUSP. You can find the language specification <a href=\"http:\/\/www.deepwood.net\/~drlion\/snusp\/snusp-1.0-spec-wd1.pdf\">here<\/a>,<br \/>\na <a href=\"http:\/\/www.baumanfamily.com\/john\/esoteric.html\">compiler<\/a>, and<br \/>\n<a href=\"http:\/\/www.quirkster.com\/snusp\/snusp-js.html\">an interpreter embedded<br \/>\nin a web page<\/a>. It&#8217;s sort of like a cross between <a href=\"http:\/\/scienceblogs.com\/goodmath\/2009\/09\/two-dimensional_pathology_befu.php\">Befunge<\/a><br \/>\nand <a href=\"http:\/\/scienceblogs.com\/goodmath\/2009\/09\/the_one_the_only_brainfck.php\">Brainfuck<\/a>,<br \/>\nexcept that it also allows subroutines. (And in a variant, <em>threads<\/em>!) The<br \/>\nreal beauty of SNUSP is its beauty: that is, programs in SNUSP are actually<br \/>\nreally quite pretty, and watching them run can be positively entrancing.<\/p>\n<p><!--more--><\/p>\n<p>SNUSP keeps its data on a tape, like Brainfuck. The basic instructions are<br \/>\nvery Brainfuck like:<\/p>\n<dl>\n<dt><code>&lt;<\/code><\/dt>\n<dd> move the data tape pointer one cell to the left.<\/dd>\n<dt><code>&gt;<\/code><\/dt>\n<dd> move the data tape pointer one cell to the right.<\/dd>\n<dt><code>+<\/code><\/dt>\n<dd> add one to the value in the current data tape cell.<\/dd>\n<dt><code>-<\/code><\/dt>\n<dd>subtract one from the value of the current data tape cell.<\/dd>\n<dt><code>,<\/code><\/dt>\n<dd> read a byte from stdin to the current tape cell.<\/dd>\n<dt><code>.<\/code><\/dt>\n<dd>write a byte from the current tape cell to stdout.<\/dd>\n<\/dl>\n<p> As I said, very Brainfuck-like when it comes to handling data. The interesting<br \/>\npart is next, when we get to its idea of two-dimensional control flow.<br \/>\nThere aren&#8217;t many instructions here &#8211; but they end up providing something that I find<br \/>\nmuch more fascinating that Befunge.<\/p>\n<dl>\n<dt><code>\/<\/code><\/dt>\n<dd>bounce the current control flow direction as if the &#8220;\/&#8221; were a mirror: if<br \/>\nthe program is flowing up, switch to right; if it&#8217;s flowing down, switch to<br \/>\nleft; if it&#8217;s flowing left, switch to down; and if its flowing right, switch<br \/>\nto up.<\/dd>\n<dt><code><\/code><\/dt>\n<dd> bounce the other way; also just like a mirror.<\/dd>\n<dt><code>=<\/code><\/dt>\n<dd> noop for drawing a path flowing left\/right.<\/dd>\n<dt><code>|<\/code><\/dt>\n<dd> noop for drawing a path flowing up\/down.<\/dd>\n<\/dl>\n<p> Those control flow operators are pretty much trivial. Conditionals are,<br \/>\nobviously, written using a &#8220;?&#8221; test followed by a mirror. Loops are,<br \/>\nliterally, loops. The no-ops allow you to actually draw paths, which makes<br \/>\nSNUSP programs <em>look<\/em> really cool, but so far, it&#8217;s not particularly<br \/>\nfunctionally different from Befunge with a Brainfuck tape. What makes SNUSP<br \/>\nboth brilliant and twisted is the last two instructions, which provide<br \/>\nsubroutines. In addition to the playfield and the data tape, SNUSP also<br \/>\nhas a call stack. Each entry on the call stack consists of a pair of<br \/>\n(location,direction). The two subroutine instructions are:<\/p>\n<dl>\n<dt><code>@<\/code><\/dt>\n<dd>push the current program location and the current direction onto the stack.<\/dd>\n<dt><code>#<\/code><\/dt>\n<dd> means pop the top of the stack, set the location<br \/>\nand direction, and *skip* one cell. If there is nothing on the stack, then<br \/>\nexit (end program).<\/dd>\n<\/dl>\n<p> The final thing you need to know to read a SNUSP program<br \/>\nis that program execution starts out wherever there is a &#8220;$&#8221;, with the PC<br \/>\nmoving to the right.<\/p>\n<p> For our first example, here&#8217;s a program that reads a number and then<br \/>\nprints it out twice:<\/p>\n<pre>\n\/==!\/===.===#\n|   |\n$====,===@\/==@\/====#\n<\/pre>\n<p> So, it starts at the &#8220;$&#8221; flowing right. Then gets to the &#8220;,&#8221;, and reads a<br \/>\nvalue into the current tape cell. It hits the first &#8220;@&#8221;, records the location<br \/>\nand direction on the stack. Then it hits the &#8220;\/&#8221; mirror, and goes up until it<br \/>\nhits the &#8220;\/&#8221; mirror, and turns right. It gets to the &#8220;!&#8221; and skips over the<br \/>\n&#8220;\/&#8221; mirror, then the &#8220;.&#8221; prints, and the &#8220;#&#8221; pops the stack. So it returns to<br \/>\nthe first &#8220;@&#8221;, skips over the &#8220;\/&#8221; mirror, and gets to the second &#8220;@&#8221;, which<br \/>\npushes the stack, etc.\n<\/p>\n<p> Here&#8217;s a simple subroutine for adding 48 to a cell:<\/p>\n<pre>\n=++++++++++++++++++++++++++++++++++++++++++++++++#\n<\/pre>\n<p>Or a slight variant:<\/p>\n<pre>\n\/=+++++++++++++++++++++++++\n| #+++++++++++++++++++++++\/\n|\n$\n<\/pre>\n<p>Or (copying from the language manual), how about this one? This one starts<br \/>\nto give you an idea of what I like about this bugger; the programs can be<br \/>\nreally beautiful; writing a program in SNUSP can be as much art as it is programming.\n<\/p>\n<pre>\n#\/\/\n$===!++++\n\/++++\/\n\/=++++\n!\/\/\/\n<\/pre>\n<p>One last +48 subroutine, <\/p>\n<pre>\n123 4\n\/=@@@+@+++++#\n|\n$\n<\/pre>\n<p> This last one is very clever, so I&#8217;ll walk through it. The &#8220;1234&#8221; on the top<br \/>\nare comments; any character that isn&#8217;t an instruction is ignored. They&#8217;re<br \/>\nthere to label things for me to explain.<\/p>\n<ol>\n<li> The program goes to @1.<\/li>\n<li> At @1, itt pushes the loc\/dir on the stack.<\/li>\n<li> Then it gets to @2, and pushes again. (So now the stack is &#8220;@1right,@2right&#8221;). <\/li>\n<li> Then it gets to @3, and pushes again, and the stack is &#8220;@1right,@2right,@3right&#8221;.<\/li>\n<li> Then add one to the cell, and push again (stack=@1right,@2right,@3right,@4right&#8221;).<\/li>\n<li> Then 5 &#8220;+&#8221;s, so add 5 to the cell; with the earlier &#8220;+&#8221;, we&#8217;ve now added 6 to the cell.<\/li>\n<li> Then we hit &#8220;#&#8221;, so pop, return to @4, and skip forward one cell. So 4 &#8220;+&#8221;s<br \/>\nget executed, and we&#8217;ve now added 10 to the tape cell.<\/p>\n<li> Then we pop again (so the stack is &#8220;@1right,@2right&#8221;), return to @3,<br \/>\nand skip one instruction. That puts us back at @4, so we push (stack=@1right,@2right,@4right).<\/li>\n<li> Now there are the five &#8220;+&#8221;s (so we&#8217;ve added +15), and then another pop,<br \/>\nwhich brings us back to @4.<\/li>\n<li> We skip a cell, since we just popped back; so now we execute 4 &#8220;+&#8221;s (+19), and<br \/>\npop again. (stack=@1right), and we&#8217;re at @2.<\/li>\n<li> As usual, we skip one instruction since we just popped &#8211; so we<br \/>\njump over @3. Then we add one (+20), and repeat what happened before when<br \/>\nwe first got to &#8220;@4&#8221;, adding another 9 (+29). <\/li>\n<li> Pop again (so stack is empty), skip one instruction, so we&#8217;re at @3.<br \/>\nSkip, push, repeat from @4 (+38). <\/li>\n<li> Pop back to @2, skip @3, add one (+39), push @4, repeat the same thing from @4<br \/>\nagain (+48).<\/li>\n<\/ol>\n<p> Here&#8217;s a real beauty: Multiplication, with documentation. If you look at<br \/>\nit carefully, it&#8217;s actually reasonably clear how it works! Given this<br \/>\ninstruction set, that&#8217;s <em>truly<\/em> an amazing feat.\n<\/p>\n<pre>\nread two characters    ,&gt;,==  *    \/=================== ATOI   ----------\nconvert to integers \/=\/@&lt;\/@=\/  *   \/\/ \/===== ITOA  ++++++++++ \/----------\/\nmultiply @ =!=========\/ \/\/           \/++++++++++\/ ----------\nconvert back !\/@!============\/            ++++++++++ \/----------\/\nand print the result \/  .#    *                  \/++++++++++\/ --------#\n\/====================\/          *                  ++++++++#\n|\n|    \/-&lt;+&gt;                    #\/?=&lt;&lt;&lt;&lt;!&gt;&gt;&gt;&gt;                   \/&gt;&gt;+&lt;+&lt;-\n|   #?===\/! BMOV1 =====       -&gt;&gt;&gt;&gt;+\/    \/\/  \/======== BSPL2 !======?\/#\n|    \/-&gt;+&lt;         \/===|=========== FMOV4 =\/  \/\/                \/&lt;&lt;+&gt;+&gt;-\n|   #?===\/! FMOV1 =|===|==============  \/====\/  \/====== FSPL2 !======?\/#\n|                \/==|===|==============|==|=======\/\n|           * * *|* | * | * * * * * * *|* | * * *                \/+&lt;-\n|           * \/&gt;@\/&lt;@\/&gt;&gt;@\/&gt;&gt;=== \/====&gt;&gt;@&lt;@&lt;  *   \/==== ADD2  !&gt;=?\/&lt;#\n===== MUL2 =?\/&gt;@==&lt;#&lt;&lt;&lt;==  !&lt;&lt;&lt;&lt;@&gt;&gt;&gt;&gt;-?\/ *  \/\/            \/-\n*    \\        \/@========|======&lt;\/ * \/\/  \/== ZERO  !?\/#\n* * * \\* * * * | * * * * | * * * * *\/\/  \/\/\n\\       |         ==========\/  \/\/\n======!=======================\/\n<\/pre>\n<p> Want to see more true brilliance? How about integer square root? Written<br \/>\nto look almost like the square root radical?<\/p>\n<pre>\n\/&gt;!\/?&gt;=!\/?&gt;!\/=======?&lt;&lt;&lt;#\n|  -\/&lt;-=-\/  &gt;&gt;&gt;+&lt;&lt;&lt;-\/\nsqrt=&gt;+&lt;=!\/?!\/-&gt;-?+&gt;?\/\n\\!=&lt;&lt;+&gt;\/&lt;&lt;+&gt;\/\n===&lt;++\/\n<\/pre>\n<p> One last example: one of the most pathological functions ever, Ackermann&#8217;s<br \/>\nfunction. This was designed by a mathematician trying to prove that there were<br \/>\nprograms that didn&#8217;t require the full power of a turing machine, but that were<br \/>\nmore complicated than primitive recursive functions. The definition of the<br \/>\nfunction is:<\/p>\n<p>A(x,y) = <\/p>\n<ul>\n<li> y + 1 if x = 0<\/li>\n<li> A(x-1,1) if x &gt; 0 and y = 0<\/li>\n<li> A(x-1,A(x,y-1)) if x &gt; 0 and y &gt; 0<\/li>\n<\/ul>\n<p> The value of Ackerman&#8217;s function grows like nothing else. A(4, 2) is about<br \/>\n2&times;10<sup>19728<\/sup>.And it&#8217;s done by adding ones that many times. <\/p>\n<p> Here&#8217;s Ackerman&#8217;s in SNUSP:<\/p>\n<pre>\n\/==!\/==atoi=@@@-@-----#\n|   |\n|   |       \/=========!==!====   ** recursion **\n$,@\/&gt;,@\/==ack=!?&lt;+#    |   |     |   A(0,j) -&gt; j+1\nj   i           &lt;?+&gt;-@\/#  |     |   A(i,0) -&gt; A(i-1,1)\n@&gt;@-&gt;@\/@&lt;-@\/#  A(i,j) -&gt; A(i-1,A(i,j-1))\n#      #  |  |     |\n\/-&lt;&lt;+&gt;&gt;!=\/  =====|==@&gt;&gt;&gt;@&lt;&lt;#\n(a &gt; 0)   ?      ?           |   |    |\n&gt;&gt;+&lt;&lt;-\/!==========\/   |    |\n#      #               |    |\n|    |\n#\/?========!==\/    ==!\/=======?#\n-&gt;&gt;+&gt;+&lt;&lt;&lt;\/            &gt;&gt;&gt;+&lt;&lt;&lt;-\/\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m currently away on a family vacation, and as soon as vacation is over, I&#8217;m off on a business trip for a week. And along the way, I&#8217;ve got some deadlines for my book. So to fill in, I&#8217;m recycling some old posts. I decided that it&#8217;s been entirely too long since there was any [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[92],"tags":[],"class_list":["post-805","post","type-post","status-publish","format-standard","hentry","category-pathological-programming"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p4lzZS-cZ","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/805","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/comments?post=805"}],"version-history":[{"count":0,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/posts\/805\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/media?parent=805"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/categories?post=805"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.goodmath.org\/blog\/wp-json\/wp\/v2\/tags?post=805"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}