Fun

Programs, as seen by users

I recently came across the following image:

Programs, as seen by users

And I thought it greatly sums up the usual problem. Both users and developers think at vastly different levels of abstraction. To the developer the UI is „just another shell“ around the core and most erratic behavior of the UI can easily be explained by the inner workings of another component in the program. To the user, however, the UI is the program. And she just doesn't bother with understanding anything else. For all intents and purposes it's really magic.

Now, above image is a bit small, unfortunately and I didn't find an original creator or a higher-resolution version, so I created a vector version of the image which is attached to this post. Actually, I made two vector versions, one white on black and one black on white, the latter of which should use up substantially less toner when printed:

Programs, as seen by users – white on black Programs, as seen by users – black on white

The font used on the high-res PDFs versions is the free (and pretty) Fontin font.

I attached the Expression Design files as well, if someone wants the „source“ files. The Design and PDF files are released into the public domain by me.

What NetHack monster am I?

Cute:
.......
...h...
/......
If I were a NetHack monster, I would be a dwarf. I enjoy using expensive, high-quality equipment, and I'm not afraid to work hard to get it.
(If I weren't a dwarf, I'd be a tengu.)
But I think that doesn't quite fit.

Wolfram rule-based cellular automata in Windows Batch

Cellular automata

One-dimensional elementary cellular automata are very simple. You just got a single row of cells which have one of two states: On or Off (0 or 1, living or dead, whatever you want to call it), so they can be nicely represented by a simple two-color bitmap.

States in cellular automata change according to the neighbourhood of a cell in the previous (global) state. Let's say you're a living cell (On, 1) and your neighbours in both directions are dead (Off, 0). Suppose you also have a table that states that your state in exactly this case changes to dead (might happen, maybe you just were too lonely to exist, don't blame me). But in another configuration your left neighbour might still be living and in that case you get to live on. Or in yet another configuration you are a dead cell and regardless what your neighbours are you change state to living.

State transitions

Such a table essentially needs only a few things: State of a cell, state of all neighbour cells (two in this case) and the state of the cell in the following generation. We can visualize this as follows:

Tabular representation of a one-dimensional cellular automaton

In the top row we have a cell with two neighbours, one left, one right, so three cells each. The bottom row gives the following state for each configuration. As you may have noticed, there are only eight possible configurations. And we can impose an order on them as I have done here. And the relevant part, once that order is established is simply a string of eight zeros and ones—so essentially eight bits. We can simply write this rule as a number. What wonderful way of shortening things. This numbering was conceived by Stephen Wolfram, a British mathematician and thus it's called Wolfram code or a Wolfram rule.

The rule pictured above is rule 30.

Display

So we now know that such a cellular automaton might be described by a single number and that it can change states. What good is that?

Well, we might display a certain state of the automaton as a series of either black or white boxes:

A single generation from the rule 30 cellular automaton

and then we might display each of these states below the previous one:

Image representation of several generations of Rule 30

et voila, we got a nice picture. Slightly chaotic, but that's usual for rule 30 and we got some nice recurring triangle formations in there.

So the point of all that was to generate a weird-looking image. Now for the fun part of this. Programming such a beast.

The code

It isn't exactly complicated to do this, so lets start at the top:

Rem width of the area
Set width=81
Rem height of the area
Set height=40

We obviously need some control over how much is calculated and rendered. I put a single cell with state 1 in the center of the first row (initial state) so it's advisable to choose an uneven width because many patterns fan out to both sides (as seen above) and then they reach the left and right edge simultaneuosly. Height might be chose for a similar reason, since as the pattern fans out and reaches the sides it gets meaningless pretty quickly.

Rem rule can be given via commandline, if not, just ask for it
Set rule=%1
If%1Neq "" GoTo dont_ask_rule
:ask_rule
Set /p rule=Rule?
:dont_ask_rule
If %rule% LssGoTo ask_rule
If %rule% Gtr 255 GoTo ask_rule

If the rule is given as the first parameter we only ask for it if it lies outside the permitted range (0–255), else we ask anyway until a correct rule is given.

Call :dissect_rule

Following that I wrote a simple subroutine which dissects the numerical rule into its eight parts:

:dissect_rule
For /l %%i In (0,1,7) Do Set /a wolfram_%%i=^(rule% ^>^> %%i^) ^& 1
GoTo :EOF

So after that we have eight variables, named <cmd>wolfram_x</cmd> with <cmd>x</cmd> being a number from 0 to 7 which hold the successor states for each configuration.

Call :init_field

We then initialize the area in which we store the states of each cell for each generation:

:init_field
For /l %%r In (1,1,%height%) Do (
    For /l %%c In (1,1,%width%) Do Set field_%%r_%%c=0
)
Set /a halfwidth=width/2
Set field1_%halfwid­th%=1
GoTo :EOF

Basically we just initialize everything with zero and add a single one in the center of the first generation.

We have a problem with this approach, however, since when states are computed they need a neighbourhood. But how does the neighbourhood look for the first and last cells in each row? At first I simply put another cell to the left and right of the row, containing a zero. This works fine for most rules and we leave it as that for now. How one would implement this I leave as an exercise for the reader.

We might need a subroutine to display the whole area:

:show_field
For /l %%r In (1,1,%height%) Do Call :show_field_row %%r
Goto :EOF
:show_field_row
Set line=
For /l %%c In (1,1,%width%) Do If !field_%<span class=„re2“>1_%%­c!==1 (Set line=!line!X) Else (Set line=!line! )
Echo.!line!
GoTo :EOF

As you can see, that are actually two subroutines. They come in handy later.

What is still missing, however, is the calculation of successor states. So let's do that now.

:compute_row
Rem %1 is the current row
For /l %%c In (1,1,%width%) Do Call :compute_row_fi­eld %%c %1
Call :show_field_row %1
GoTo :EOF

Nothing fancy here, we just delegate the computation of a single cell to another subroutine. As you may note we display the calculated row immediately after we calculated it, this makes the watching experience while the batch file runs a bit less boring as we see a new line every few seconds (yes it is that slow).

:compute_row_fi­eld
Rem %1 is the field, %2 the current row
Set /a oldrow=%2 – 1
Call :get_case %oldrow% %1
Set field_%2_%1=!wol­fram_%<span class=„re2“>ca­se%!
GoTo :EOF
:get_case
Rem %1 is the row above the one currently calculated, %2 is the current field
Rem left and right neighbours
Set /a l=%2 – 1
Set /a r=%2 + 1
Set /a case=^(!field_%<span class=„re2“>1_%%! ^<^< 2^) + ^(!field_%<span class=„re2“>1_%2! ^<^< 1^) + ^(!field_%<span class=„re2“>1_%%!^)
GoTo :EOF

Here we calculate the new state for a given cell, by using another helper subroutine which looks up the specific case from the table. We make use of the fact that the configuration of a cell and its neighbours are essentially three-bit numbers and the table is laid out in such a way here that we can access it simply by converting the configuration into a number between 0 and 7. The code for that looks a little ugly, since lots of escaping is needed (I escaped the parentheses just out of fear they might break something, as they often do when nesting structures).

But that was it, essentially. Running the batch without arguments produces the following prompt:

\CMD\cellular_au­tomaton>wolfram­.cmd
Rule? _

entering, say, 54 in there, yields the following picture:

Rule? 54
                                       X
                                      XXX
                                     X   X
                                    XXX XXX
                                   X   X   X
                                  XXX XXX XXX
                                 X   X   X   X
                                XXX XXX XXX XXX
                               X   X   X   X   X
                              XXX XXX XXX XXX XXX
                             X   X   X   X   X   X
                            XXX XXX XXX XXX XXX XXX
                           X   X   X   X   X   X   X
                          XXX XXX XXX XXX XXX XXX XXX
                         X   X   X   X   X   X   X   X
                        XXX XXX XXX XXX XXX XXX XXX XXX
                       X   X   X   X   X   X   X   X   X
                      XXX XXX XXX XXX XXX XXX XXX XXX XXX
                     X   X   X   X   X   X   X   X   X   X
                    XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
                   X   X   X   X   X   X   X   X   X   X   X
                  XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
                 X   X   X   X   X   X   X   X   X   X   X   X
                XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
               X   X   X   X   X   X   X   X   X   X   X   X   X
              XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
             X   X   X   X   X   X   X   X   X   X   X   X   X   X
            XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
           X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
          XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
         X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
        XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
       X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
      XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
     X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
    XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
  XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
 X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X   X
XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX

The actual source code is a bit longer, since I offer an option how the sides of the area are handled (all zero, all one, wraparound and copy, the last of which is now the default which seems the most sensible to me—rules like 169 look very different when calculated with the edges being zero).

I am now working on SVG export from within the same batch file and I hope I found all major bugs by now. But the first working version was just 54 lines long. I think, had I been using Java instead (which was the other choice here), I would have needed significantly more.

UPDATE (2008–12–26 16:21): SVG export is now done and works as it should. At the moment I am mis-using the terminal server in the uni to compute all 256 rules simultaneously:

257 instances of cmd … I remember times when even more than 50 calculators were too much …

Cable compatibility

Talk about weird problems that can occur:

Windows Vista Problem Report: Problem caused by Firewire cable

I never knew there could be compatibility issues with cables …

Batch tricks: Reversing text

If there is one thing the Windows Command Processor (cmd.exe) can do (except starting other programs) it's string processing. Not at Perl's level but certainly more sohpisticated than the C standard library (not counting regex here).

I was just playing around a bit and came up with this:

@echo off
setlocal enableextensions enabledelayedexpansion
set "DATA=%*"
:loop
set REVDATA=%REVDATA%%DATA:~-1%
set DATA=%DATA:~0,-1%
if defined DATA goto loop
echo %REVDATA%
endlocal

Pretty straightforward, as usual. The obligatory setlocal with the usual options (I almost always set them, regardless whether I need them or not). Saving all command line arguments into a string and then dissecting it character by character. As soon as the original string is eaten up we can quit and output the result.

And it works in Unicode, too:

T:\>reverse ↔¾Ω∞()‡‼ αβγδ да ◙
◙ ад δγβα ‼‡)(∞Ω¾↔

Windows Batch which(1)

Ever wondered which exact executable will be executed when running a command from the command line? UNIXes and Linux have which(1) which tells that. There are implementations on Windows, but not one in batch language I was aware of :-)

So that naturally called for ugly things to be done. I wrote this a while ago and noticed that it does not always works correctly on Windows Vista. At the time of its writing I was working with Windows 2000 and it worked pretty well there. Somehow something is messing with extensions:
C:\>which which
C:\Users\Johannes Rössel\SVN\Pr­ojekte\CMD\which­\which.cmd
obviously works.
C:\>which which.cmd
doesn't. Contrary to that
C:\>which wget
does not work, but
C:\>which wget.exe
C:\Users\Johannes Rössel\Apps\wget­.exe
does. For things in the system's own paths (which are searched first) the above problems do not seem to apply:
C:\>which explorer
C:\Windows\ex­plorer.exe

C:\>which explorer.exe
C:\Windows\ex­plorer.exe
Weird, indeed. But currently I lack time to investigate further. I know it worked pretty well once, maybe I look into it again some day. Until then it's just another random example of Windows Command Processor perversion :-)

UPDATE (2008–06–01): I found another bug that manifests itself most prominently on Windows Vista x64, concerning paths with closing parentheses in them (as happens when installing x86 applications there). That means I have to do a bit escaping as soon as those paths show up in the argument of a FOR loop. Using ! and FOR /F seems to work somehow, except that I only get a single token from that.

Windows Batch Sieve of Eratosthenes

A while ago a fellow student of mine held a „lecture“ for pupils on programming where I should help helping the kids. Prime numbers are a nice topic for introductory courses, since they are easy to understand and a simple search for them is written in a few lines of code. I suggested mentioning the Sieve of Eratosthenes as well as giving an implementation of it, since I think the algorithm is pretty easy to understand and nicely fast in generating the first n primes. The programming language we used was Pascal and I was able to come up with a naïve implementation in a manner of minutes. Glancing over the program again I thought it wouldn't be that hard to implement in CMD, so I tried … there was still plenty of time left so I wrote the following perversion of batch language :-)

It's actually very short and I was surprised that it took only that few lines to write. We start by allocating a bunch of n boolean array elements:
set n=%1
for /l %%i in (2,1,%n%) do set l%%i=1
and then we simply iterate over them and delete all those environment variables that resemble multiples of the current number:
:sieve
set /a begin=%1
set /a max=%n% / %1
for /l %%k in (%begin%,1,%max%) do set /a foo=%1 * %%k && set l!foo!=
goto :EOF
and finally we simply output those that are left:
for /l %%i in (2,1,%n%) do if DEFINED l%%i echo %%i
That actually already was most of the code, the rest is merely auxiliary.Now that I look at that code again the sieve loop could as well be
for /l %%k in (%begin%,%1,%max­%) do set l!foo!=
This should work too and we save a variable assignment during the inner loop. But I'm too lazy to do benchmarks now so I just leave it the old way that is tried to work.

There is a practical limit for n, though. The batch runs fine for 100 or even 1000 numbers, but sieving 20000 numbers already takes about a minute on my notebook. And there was a point at which the environment seemed to grow too large to handle in a sensible way.

And no, it does not compute all this in parallel, though I wonder how hard it would be to create batch files that calculate things concurrently in multiple processes; might actually make use of all those multicore systems out there. But I don't have a good idea currently how they should communicate if need arises; files are an option but slow and subject to races … well, I still have a lot of lectures I only attend physically, so my mind may be free to solve these problems :-)

Windows Batch Dice Roller

Something I've written a while back now (February 2007): A dice roller, written as a Windows batch file. It supports an arbitrary number of dice (well, up to certain limits of the shell, like 32 bit integers and strings of about 32000 characters maximum) and arbitrarily many sides (up to … you'll get the picture). So if you want to roll, say … 1200 dice with 462 sides each you may do so:
C:>roll 1200d462
The results are then spewn onto the console in the order they were rolled. No sorting yet, I couldn't get myself to implement even simple sorting algorithms, though I may revisit this in future.

This innocent batch file sports a finite state machine for parsing the parameters which may be given by the following regular expression:

[1-9][0-9]*[WDwd][1-9][0-9]*(\+[1-9][0-9]*)?

I allow both German and English notation (w vs. d as separator of number and sides of the dice) as well as optional adding of all rolls and a constant (for Shadowrun 3 initiative rolls). Due to the nature of parsing the user will get pretty precise feedback where a parsing error occurred and what was expected (Hmm, this may call for a general batch FSM generation tool :).

A few limitations, however:

  • Rolling is slow, so 1000 rolls will take a while.
  • Since CMD only knows 32 bit signed integers, the maximum number of dice is 2147483647.
  • Since the results are stored in a single environment variable which are limited to 32764 characters, the maximum practical number of dice reduces further. Otherwise the results will be truncated.
  • Since CMD's random number generator will only yield random numbers between 0 and 32767 the maximum practical number of sides is 32768, otherwise, no roll will yield a result above 32768.
  • Since capping rolls to the number of sides is done by a modulo operation, the results won't be equally distributed if the number of sides is no divisor of 32768 (might be especially noticeable above 16384).

The code is nearly undocumented, but that just adds to the fun :-)

Counting, the ugly way

@echo off
set X=0
echo set /a X+=1 >>%0
echo echo %%X%%>>%0

... But it does work ... each time you run it, the list of numbers grows by one :-)

The interesting part here is that the lines added during running are executed in the same instance of the running batch.

Nullity

Anyone ever heard of Nullity? A great new (well, about 10 years old, by now) mathematical concept (not to be confused with the other mathematical concept that goes by this name) invented by James Anderson that enables us to divide zero by itself. Along with this special "number" comes the so-called "Transreal arithmetic". So, basically Nullity is a special non-real number and defined as the result of 0 ÷ 0. It has been shown that it is also equal to 00 and 0 ⋅ ∞. The only real difference to existing concepts as NaN is that Nullity (Φ) is equal to itself, while NaN is not in standard IEEE floating point arithmetic. Apparently he even convinced a school to teach that concept and is building computers that use it. As for me, I have yet to encounter a final solution of 0 ÷ 0 and thus Φ to a problem. When dealing with limits, l'Hôspital usually takes care of that. And since most computations have their roots in maths I never encountered something that yielded NaN. Positive and negative infinity—sure, but no NaN. Furthermore, replacing NaN by Φ won't gain us anything, except for calling d.IsNullity() instead of d.IsNaN(). Just my two cents on this issue. Wikinews has a little more opinions on this.
Syndicate content