Monday, 30 December 2013

Window Snapper

Many programs have a nice dividers in their GUI - and you can usually drag the divider to resize the panels on either side. I've often been a little frustrated when resizing windows to tile them to fill the screen. Perhaps a Word document on the left, a PDF in the upper right, and email in the lower right. It was quite tedious, and because of that I didn't do it often, and I feel this slightly diminished the power of windows. So I wrote an AutoHotkey script and now I have what I wanted.

To use it, while the script is running, you can right-button drag window borders, and the script will move all neighbouring window edges at the same time. The script will grab window borders within 10 pixels (configurable) of the border/s you are right-button dragging. It also assumes a seven pixel wide window resize border, but that's also configurable at the top of the script. You can resize from edges or corners - giving you lots of power when resizing windows.

The most common use-case I have is with just two windows positioned with Win+Left and Win+Right (like explained here). With this script you can resize both windows effortlessly.

Here's an example of it in action:
 I can resize all five windows with one right-button drag, in the area where the four window corners meet in the middle of the screen. If I drag towards the upper right, I can get something like this:
 And things like this are possible too, but unsnapping window edges like I've done below with the left and right can be a little fiddly. I could potentially add something like Ctrl+Right-Click to only resize windows actually near the mouse...
Please have a go with the window snapper script. Please let me know what you think after using it!

Creative Commons License

Friday, 19 July 2013

Engagement in the Family

My brother-in-law Rowan Barton is engaged to Elpida Savvidou. This is awesome news (even if not recent :-). Their engagement party is movie themed, and we've got some western style props, so I've created custom wanted posters! Here they are:

A wanted poster showing that Elpida is wanted alive for stealing a heart, reward $1000.

A wanted poster showing that Rowan is wanted dead or alive for parental bank robbery, reward $1000.

Once printed we are going to brown the edges with the heat from a fire.

The SVG files were created with Inkscape (Trace Bitmap is fantastic) and are available for use if you'd like. I put them in the public domain (but I'd be thrilled to hear from you if you use these). They make use of the Playbill font.

I'm interested to see what other people have created. Enjoy :-)

Saturday, 13 July 2013

Minecraft vs Real Life

I have been digging a hole in the ground. It is just a bit more than one and a half metres deep, and around a metre in diameter. Here is the hole:

A hole in the ground about 1 metre in diameter and just over one and a half metres deep.

Here is the hole with the dirt I have emptied out of the hole in view:

The same hole as in the previous picture but showing the piles of 'hole' dirt around it.

Here is an equivalent sized hole in Minecraft:

Apart from the Minecraft hole being digital, it was also a lot neater. And it took less time to dig. The real hole above has taken several weekends of digging - probably close to 20 hours of digging. The Minecraft hole took around 20 seconds, that's including deciding where to dig. Perhaps that's one reason why games like Minecraft are enjoyable to play - they let you do mundane things really quickly.

Saturday, 6 July 2013

Bits of Minecraft

Minecraft has sunk a lot of my time over the few years it's been around. Here are some of the things I've done in it (in order of construction):

A rainbow made of wool is visible to the left, and a large woolen cake lurks in the fog to the right.
Rainbow! ... and cake

A triple helix with hanging vines made of dirt rises into the sky in front of a seemingly floating land.
Triple helix near an overworld plate

From my overworld you can see my home base tower on the left, satellite dish in the centre and the word "Craft" made of wool on the right.
Home, satellite dish and "Craft"
The rainbow, triple helix and satellite dish were all planned using Lisp. Here's some Lisp code you can use to plan rainbows:

(loop with freq = (list)
       and reach = (1+ 20)
       and width = 8
      for j from reach downto 0
    do (loop for i from (- reach) to reach
             for r = (round (sqrt (+ (square i) (square j))))
             for c = (cond ((= i j 0) #\+)
                           ((< r (- reach width)) #\-)
                           ((<= r (1- reach)) (- r (- reach width)))
                           (t #\Space))

        when (not (eql #\Space c))
        do (aif (cdr (assoc c freq))
            (incf (car it))
            (push (list c 1) freq))
        when (or (minusp i) (not (eql #\Space c))) do (princ c))

    do (terpri)
    finally (return freq))

It produces output like this (this one's a small version to fit in the width of the blog):

((#\+ 1) (#\- 256) (0 45) (1 45) (2 43) (3 57) (4 57) (5 57) (6 59) (7 57))

The last bit is a count of each block type so you know how much to gather of each type. Three dimensional objects like the dish and triple helix use more code which I can post if people are interested.

P.S. Don't spend too much time playing computer games.

Saturday, 29 June 2013

Diode PN Junction Explained

I never felt like I properly understood how the PN junction in a diode works. So I looked it up and came across some explanations that really helped me understand it better. I've put it all into a diagram. But let's introduce some of the concepts first.

A diode is made of a semiconductor (like Silicon) with two regions. The semiconductor makes up a crystal. One region in the crystal has been doped with atoms that have a spare electron when in the crystal lattice. It is known as the N region. The other region in the crystal has been doped with atoms that have spare room for an electron when in the crystal lattice (the spare spots are known as holes). It is known as the P region. That's where the name PN junction comes from.

The N region with its spare electrons conducts via movement of these spare electrons (the electrons are the charge carriers in an N region). The electrons are the charge carriers. Conversely, the P region conducts via the movement of the 'holes' (the holes are the charge carriers in a P region). As an aside, undoped semiconductors don't conduct as well because they don't have mobile charge carriers.

An important note to remember is that while the regions may be called N and P, this does not mean that they are overall positively or negatively charged. The regions have an overall neutral charge. Following on from that, if you were to take away the electrons in an N region, the crystal structure would be positively charged. The opposite would occur if you filled the holes in a P region with electrons.

So, with that explanation, here's the diagram:
So the depletion region gives a potential barrier (from the fixed charges). The width of the depletion region (and thus also the size of the potential barrier) depends on the applied potential (in effect, it depends on the direction of the attempted flow of current).

Thanks to:

Saturday, 22 June 2013

Hard to Find Excel Tidbit

A short post this week. I recalled that there was a syntax for Excel ranges in VBA. I searched online, but couldn't find much, so here is the tidbit: Ranges can be specified using square brackets. If you used named ranges a lot, this turn out quite nice. So if you have a named range called ImportantInfo, you can refer to it as ... [ImportantInfo]! And it may not provide the method list when you type a full stop after it, but it IS a range object, so you can use it like this:

    Answer = [ImportantInfo].Offset(RowCount, ColumnCount).Text
    MsgBox "The cell Sheet2!E3 contains """ & [Sheet2!E3] & """."
    Dim Cell As Range
    For Each Cell In [B1:B3]
        MsgBox Cell.Text
    Next Cell

One of the reasons I think it's neat when used for named ranges is that with most named ranges in square brackets, you don't have to specify the sheet to disambiguate it. That makes for shorter, and thus easier to read code.


Saturday, 15 June 2013

Linked Lists in VBA (Excel)

I use Microsoft Excel quite a bit. And recently we had a challenge at work to validate lane use signal displays using conflict matrices. Well, I had some Lisp written to generate sequences given a set of allowed 'transitions'. So I wanted to put that logic into Excel, which meant VBA. I thought it would be quick, but it took about two and a half full days of work... Part of porting over my logic was creating a linked list class named "List" in VBA. It is my first VBA class module (yay!). Here's the code in the "Node" class module:

'' Linked Lists in VBA is released under a BSD licence. Author: Jonathan F Johansen
Option Explicit
Public Car As Variant
Public Cdr As List

Public Function ToString() As String
    ToString = "[" & PlainListString() & "]"
End Function

Public Function PlainListString() As String
    If Cdr Is Nothing Then
        PlainListString = CStr(Car)
        PlainListString = CStr(Car) & ", " & Cdr.PlainListString()
    End If
End Function

I had more in the class module, but took most of the methods out of there because I wanted to treat Nothing as the empty list. Here are the functions from a separate module:

'' Linked Lists in VBA is released under a BSD licence. Author: Jonathan F Johansen
Option Explicit

'' Making Lists:

Function Cons(Item As Variant, Optional Rest As List) As List
    Set Cons = New List
    Cons.Car = Item
    Set Cons.Cdr = Rest
End Function

MakeList(ParamArray Items() As Variant) As List
    On Error GoTo ZeroLength ' Leaving MakeList as Nothing.
    Dim I As Long
    For I = UBound(Items) To LBound(Items) Step -1
        Set MakeList = Cons(Items(I), MakeList)
    Next I
End Function

'' Working with Lists

Append(aList As List, OtherList As List) As List
    If aList Is Nothing Then
        Set Append = OtherList
    ElseIf OtherList Is Nothing Then
        Set Append = aList
    ElseIf aList.Cdr Is Nothing Then
        Set Append = Cons(aList.Car, OtherList)
        Set Append = Cons(aList.Car, Append(aList.Cdr, OtherList))
    End If
End Function

Reverse(aList As List, Optional OntoFrontOf As List) As List
    If aList Is Nothing Then
        Set Reverse = OntoFrontOf
        Set Reverse = Reverse(aList.Cdr, Cons(aList.Car, OntoFrontOf))
    End If
End Function

Length(aList As List) As Long
    If aList Is Nothing Then Exit Function 'Returning 0
    Length = 1 + Length(aList.Cdr)
End Function

Member(Item As Variant, aList As List) As Boolean
    If aList Is Nothing Then Exit Function
    If aList.Car = Item Then
        Member = True
    ElseIf aList.Cdr Is Nothing Then
        Member = False
        Member = Member(Item, aList.Cdr)
    End If
End Function

Replace(OldItem As Variant, NewItem As Variant, aList As List) As List
    If aList Is Nothing Then
    ElseIf aList.Cdr Is Nothing Then
        If aList.Car = OldItem Then
            Set Replace = Cons(NewItem)
            Set Replace = aList
        End If
        If aList.Car = OldItem Then
            Set Replace = Cons(NewItem, Replace(OldItem, NewItem, aList.Cdr))
            Set Replace = Cons(aList.Car, Replace(OldItem, NewItem, aList.Cdr))
        End If
    End If
End Function

Remove(Item As Variant, aList As List) As List
    If aList Is Nothing Then Exit Function
    If Item = aList.Car Then
        Set Remove = Remove(Item, aList.Cdr)
        Set Remove = Cons(aList.Car, Remove(Item, aList.Cdr))
    End If
End Function

Count(Item As Variant, List As List) As Long
    If List Is Nothing Then Exit Function
    If List.Car = Item Then Count = 1
    Count = Count + Count(Item, List.Cdr)
End Function

CountMaxConsecutive(Item As Variant, List As List) As Long
    If List Is Nothing Then Exit Function
    Dim Rest As List, Count As Long
    Set Rest = List
    Do Until Rest Is Nothing
        If Rest.Car = Item Then
            Count = Count + 1
            Count = 0
        End If
        If Count > CountMaxConsecutive Then CountMaxConsecutive = Count
        Set Rest = Rest.Cdr
End Function

CellTextToList(aRange As Range) As List
    Dim I As Long
    If IsEmpty(aRange) Then Exit Function
    For I = aRange.Cells.Count To 1 Step -1
        Set CellTextToList = Cons(aRange.Cells(I).Text, CellTextToList)
    Next I
End Function

ListToRow(aList As List, Target As Range) As Range
    Dim List As List
    Set List = aList
    Set ListToRow = Target
    Do Until List Is Nothing
        ListToRow = List.Car
        Set ListToRow = ListToRow.Offset(0, 1)
        Set List = List.Cdr
End Function

I found it useful, but it could do with a few more utilities. One interesting thing is that looping over a list isn't to complex, as you can see in the last function above. You just declare a local List variable and then use a Do Until localList Is Nothing, and at the end of the loop body, Set localList = localList.Cdr. If you don't declare a local list, but modify the argument, you'll find that the list is chewed up in the caller's scope too...

Here are some examples of the List in action:
Option Explicit

Sub TestLinkedLists()
    MsgBox Cons("a", Cons("b")).ToString
    MsgBox Length(MakeList(1, 2, 3, 4, 5))
    MsgBox Reverse(MakeList(1, 2, 3, 4, 5)).ToString
    MsgBox MakeList(1, 2, 3, 4, 5).ToString
    MsgBox Member(4, MakeList(1, 2, 3, 4, 5))
    MsgBox Member(4, Nothing)
    MsgBox Append(MakeList(1, 2, 3, 4), MakeList(5, 6, 7)).ToString
    MsgBox Replace(4, "four", MakeList(1, 2, 3, 4, 5)).ToString
    MsgBox Remove(3, MakeList(1, 2, 3, 4, 5)).ToString
    MsgBox Count(True, MakeList(False,True,True,True,False,True))
    MsgBox CountMaxConsecutive(True, _

                     MakeList(False, True, True, True, False, True))
    MsgBox CellTextToList(Range("A2:A6")).ToString
    MsgBox "List output to B2, range returned is " _
         & ListToRow(CellTextToList(Range("A2:A6")), Range("C2")).Address _
         & " ready to go for something else..."

End Sub

If you've read the code, you might notice the liberal use of recursion, and the use of functional style. I used recursion a lot in the spreadsheet, and I think this List class helped a lot.

The code on this page is collected into an Excel spreadsheet for convenience too. You can download it from here. As noted in the code comments, the code is released under the BSD license - and I'd love to hear from you if you use it or extend it. Enjoy!

Saturday, 8 June 2013

Excel Table to Jira Table

Excel table, meet Jira :-). After writing the previous AutoHotkey script to convert the clipboard contents to a comma separated list, I wrote this one. It makes constructing Jira tables a breeze.

;;; Converts a copied table from Excel into Jira format
  StringReplace, ForFirstLine, Clipboard, `r`n, §
  StringSplit, ForFirstLine, ForFirstLine, §
  StringReplace, ForFirstLine1, ForFirstLine1, %A_Tab%, ||, All
  StringReplace, ForFirstLine2, ForFirstLine2, %A_Tab%, |, All
  ForFirstLine2 := RTrim(ForFirstLine2, "`r`n")
  StringReplace, ForFirstLine2, ForFirstLine2, `r`n, |`r`n|, All
  Clipboard := "||" . ForFirstLine1 . "||`r`n|" . ForFirstLine2 . "|"
  Send ^v

To use it, just press Windows+Shift+J (but that's easily changed). It puts double pipes on the first line, and single pipes on other lines.

Saturday, 1 June 2013

Clipboard Processing with AutoHotkey

I've been doing a lot of text processing recently, and a lot of it has been to convert a column of cells from Excel into a comma separated list. Well, I used to do that with Notepad++, but last week I bit the bullet and wrote an AutoHotkey script to do it for me. Without further ado, here are the goods:

    StringReplace, Clipboard, Clipboard, `r`n, `,%A_Space%, All
    Clipboard := RTrim(Clipboard, ", `n")
; Gets rid of the annoying trailing newline that Office programs put in.
    Send ^v

It will paste the converted clipboard contents when you press Windows+V. Also, I found a way to get text/content copied from MS Office to plain, plain text by removing the trailing newline character.

Friday, 24 May 2013

Notepad++ Find and Replace

I think Notepad++ is a great program. I use it a lot at work and at home. I have used it to process text in various ways. I really like Notepad++'s find and replace options, especially since the Regular Expression engine was updated to PCRE. A great post on Notepad++'s find and replace can be found on Mark's Speechblog. In the examples below, don't type in the double quotes. Here are a few Find and Replace searches I have found useful:

This one turns new lines into commas with spaces. I use it to convert a column of Excel data into text as a comma separated list. I've since written an AutoHotkey script to do this too (because I do this so often), which will be the topic of a future post.
Search Mode: Extended
Find: "\r\n"
Replace with: ", "

This finds a specific second column of freeform text from several other columns with digits. The second find string converts a line like "11937577    M0609/VD06   108721      11933802    198024      11933835" into just "M0609/VD06".
Search Mode: Regular expression
Find: "\d+ +(.+)" and "\d+ +(.+) +\d+ +\d+ +\d+ +\d+"
Replace with: "\1"

This one uses start and end of line anchors to ensure the whole line is matched, and grabs the last column. It converts something like "108608     Left turn MVT from Road SEB to Ave NEB    NULL       9      7774/SEB/LQ" into "7774/SEB/LQ".
Search Mode: Regular expression
Find: "^.* +(.+)$"
Replace with: "\1"

This one puts a capital M in front of lines that begin with a digit.
Search Mode: Regular expression
Find: "^(\d)"
Replace with: "M\1"

This one splits some text in a specific tabular form into separate lines.
Search Mode: Regular expression
Find: "(\d+/[^\t\r\n]*\t[^\t\r\n]*\t[^\t\r\n]*\t(SB|NB)\t[^\t\r\n]*\t[^\t\r\n]*\t[^\t\r\n]*\t[^\t\r\n]*\t[^\t\r\n]*\t)"
Replace with: "\1\r\n"

This one removes a tab from the end of a line if it has any. I should have put the last \t in the above regular expression outside of the group, as in "(...[^\t\r\n]*)\t".
Search Mode: Regular expression
Find: "\t$"
Replace with: "" (nothing)

For this find and replace, I wanted to wrap everything on non-empty lines with some other text (in this case it's for a custom SQL query).
Search Mode: Regular expression
Find: "^(.+)$"
Replace with: "   or v.Identifier like '%\1%'"

Have fun with Notepad++!

Saturday, 16 February 2013

Simple Glossaries in LaTeX

I use LaTeX (via MikTeX) and TeXnicCenter a bit, starting from when I did my PhD. It's a great document preparation system which has some annoying sides, but I won't go down that path. I tried to set up a glossary in a document recently, and it wasn't obvious to me how to do that. I did get it working though. Here's what I did, so that others (including myself) don't have to figure it out again:
  1. Follow the steps provided at LaTeX Matters, namely:
    1.  Put two lines into your preamble (before \begin{document}):
    2. When you define or introduce certain terms, wrap them in a \glossary command like so:
      \glossary{name={entry name}, description={entry description}}
      The inside curly braces are only necessary if you have commas in the entries.
    3. Place this command where you want the glossary to appear:
    4. If you want your glossary to have an entry in the Table of Contents, then put this with the previous line:
    5. Then, instead of running a command as described in the post, follow the next step, which is equivalent, but for TeXnicCenter.
  2. Prompted by Archiddeon's comment in a LaTex forum, in TeXnicCenter, add a post-processing step to a build profile:
    1. Select the Build menu then choose Define Output Profiles...
    2. On the left, select a profile you want to start from
    3. Click the Copy button down below, enter a new name for the profile and click OK
    4. Then click on the Postprocessor tab
    5. Create a new postprocessor step by clicking the little "new folder" icon at the top right
    6. Then enter a name like "Prepare the glossary" and the following:
      Executable: makeindex
      Arguments: "%tm.glo" -s "" -t "%tm.glg" -o "%tm.gls"
  3. Click OK until you're back at the main window!
Then you should be able to select the new profile and generate the document with a glossary! I'd run it 2-3 times to let the page numbers settle. Joy!

Friday, 8 February 2013

The 147 Problem from Programming Praxis

Programming Praxis is a great site. The 147 problem was recently posted there, and I tackled it with a bit too much time... Following is the code, with discussion.

(defun sum1/ (s)
    "Read the name as Sum the Inverses"
    (apply #'+ (mapcar #'/ s)))

(defun limits (n)
    "I took the limits discussion on the site a bit further..."
    (loop for i from n downto 1
          for prod = (apply #'* prods); Produces 1 to start with
          for prods = (cons (1+ prod) prods)
          for min = (min (car prods) n)
          for max = (max (* i prod) n)
        collect (list min max)))

When calling limits with n = 5, we get ((2 5) (3 8) (5 18) (5 84) (5 1806)) which shows the maximum ranges of each number we'll search for. The actual search for solutions to 1/a+1/b+1/c+1/d+1/e = 1 then looks like this:

(defun search1 (n &optional givens limits)
    "Actually finds all of the valid solutions to the 147
problem with n numbers. Call it without the optional arguments
to start it off."
    (let ((limits (if (null givens) (limits n) limits)))

        ;; Limits is whittled down during the recursion,
        ;; so detect starting off by looking at givens.
        (if (= n (length givens))
            (if (= 1 (sum1/ givens))
                (list (reverse givens)))
            (loop for next from (max (caar limits)

                                     (if givens (car givens) 0))
                           to (cadar limits)
                  for s = (cons next givens)
                until (or (every (lambda (i) (> i n)) s)
                          (and (not (cdr limits)) (< (sum1/ s) 1)))
                appending (search1 n s (cdr limits))))))

This code times how long it takes to solve the first few solutions before the times get too big:

(time (loop for n from 0 to 5 collect (nreverse (search1 n))))

Which gave 4.1 seconds on my computer.

Note that the code works for n = 0 and 1 (producing the empty list, and a single solution: 1, respectively). As some other people have mentioned, Common Lisp is well thought out. I think this also supports that thought, as I didn't design the algorithm specifically to handle cases n = 0 and 1.

And lastly, the following code finds the smallest distinct solutions, as described at Programming Praxis:

  (remove nil
    (mapcar (lambda (s)
              (if (apply #'/= s); Distinctness
                (cons s (apply #'+ s)))); Sum the denominators
            (search1 5)))
  #'< :key #'cdr); Sort by the sum of denominators

Which gives (3 4 5 6 20), confirming our solution.

Happy coding!

Saturday, 2 February 2013

Solving the Discretised Traffic Model Equations

This post follows on from when we discretised our traffic model equations. We now solve them in this post.

The solving process is quite simple since we avoided most references to the future values of variables. If we did, we'd have to use matrices to solve the discretised model equations. As it is, we can simply calculate each value separately.

The code is modeled around each cell, so here's the discretised cell equation: $$\rho(x_i,t_f) = \rho(x_i,t_c) - \frac{t_f-t_c}{x_{i+}-x_{i-}}\left(\rho(x_{i+},t_c) v(x_{i+},t_c) - \rho(x_{i-},t_c) v(x_{i-},t_c)\right).$$ where
\(\rho\) = vehicular density (veh/m);
\(t\) = time (s);
\(t_c\) = the current time (s);
\(t_f\) = the future time (s);
\(x\) = distance (m) along road;
\(i\) = the index of the current cell, ranging from 1 to \(n\);
\(x_i\) = the location of the 'centroid' of the current cell (m);
\(x_{i-}\) = the left (upstream) boundary of the current cell
\(x_{i+}\) =
\(v_f\) = free flow speed (m/s);
\(\rho_j\) = jam density (veh/m), the average vehicles per metre in stationary traffic; and
\(v\) = vehicle speed (m/s), and is given by: \(v = v_f(1-\rho/\rho_j)\).

The left boundary is given by: $$\rho(0,t) = \rho_j/4.$$

Oh, and in case it isn't clear, the flow of traffic is in the direction of increasing \(x\) , which is to the right. That means that upstream is to the left, and downstream is to the right.

The above equations have been implemented in Common Lisp, with MathP (but I'll wait till the end to show the final code). It outputs the values scaled up by 1000 for convenience. To call it, we evaluate something like this:

(step-simulation :road-length 1000 :n 20 :dt 1.0 :time-run 200)

Great! So, let's look at the results. Here is a visualisation of the results for the above simulation:

Initial traffic simulation results. Time increases from top to bottom, distance increases from left to right. Light traffic is green, medium traffic is yellow, and heavier traffic is red.

Not so good... there are fluctuations in the solution, causing negative vehicle densities. Thankfully, that can be fixed with an Upwind scheme. In our case, we just move the centroid more upstream within the cell. This removes the fluctuations, but probably increases error elsewhere in the simulation. The results with the Upwind scheme are:
"Upwind" traffic simulation results. Time increases from top to bottom, distance increases from left to right. Light traffic is green, medium traffic is yellow, and heavier traffic is red.

Looking good. The traffic on the left fills the road over time, and there are no fluctuations.

The final code to implement this is:

(defparameter *free-flow-speed* (/ 60 3.6); = 60 km/h
    "Speed (m/s) of freely flowing, low density traffic.")
(defparameter *jam-density* (/ 7.0); = 1 veh every 7 m

    "Jam density (veh/m), the average vehicles per metre in stationary traffic.")
(defparameter *road-length* 1000.0; = 1 km

    "Length (m) of road being simulated.")
(defparameter *cell-count* 10

    "Number of cells road is split into for simulation.")

(defun step-simulation (&key
        (vf *free-flow-speed*)
        (pj *jam-density*)
        (road-length *road-length*)
        (n *cell-count*)
        (dt 1.0); Time step in seconds.
        (time-run 10.0); Time to run simulation for.
        (t0 0.0); Starting time for simulation.
        (upwind 0.5); Upwinding parameter [0 = only upstream, 1 = only downstream]
        p0; Initial road density for each cell.
        pin); Input density function (veh/m). Should take one argument - the time.
    dx = roadLength/(n-1)
; Spacing between cell centres.
    pin = if pin pin fn(_) pj/4.0

    ;; Set the boundary density in the initial state.
    unless(p0 p0 := makeArray(n :initialElement 0.0) p0[0] := #!pin(t0))
    v(p) = vf*(1-p/pj); Velocity as function of density.
    x(i) = (i-1)*dx; Cell centroid locations.
    xp(i) = if i<n (i-0.5)*dx roadLength; Plus, or right (downstream) boundary locations.
    xm(i) = if i>1 (i-1.5)*dx 0; Minus, or left (upstream) boundary locations.
    stepsim(pold atime dt) =
        makeVector(n fn(i) {
            pm = if i>1 (1-upwind)*pold[i-2]+upwind*pold[i-1] pold[0]
            pp = if i<n (1-upwind)*pold[i-1]+upwind*pold[i] pold[n-1]
            in = max(0 dt*pm*v(pm))
            out= max(0 dt*pp*v(pp))
            if i==1 #!pin(atime) pold[i-1] + (in - out)/(xp(i)-xm(i))})
(loop for atime from t0 to (+ t0 time-run) by dt
            for ps = p0 then (stepsim ps atime dt)
        do (loop for p across ps
            do (format t " ~4,1,3F" p)
            finally (terpri)))})

Saturday, 26 January 2013

Biblical Topic: Resurrection

These are some notes I've put together about the resurrection and the immortality of the soul. All of the quotes are from the ESV unless otherwise noted, but please have a Bible ready to look verses up in, because I have not included the text of every quote. For many people, considering this may not be easy, but we know from Proverbs 25:2 that "It is the glory of God to conceal things, but the glory of kings is to search things out." Jesus also, knowing God, did the same and spoke in parables.

Having said that, if you will listen further, here are some things to consider:

Why did Martha say what she did, after Lazarus died?

John 11:23-26: Jesus said to her, "Your brother will rise again."  Martha said to him, "I know that he will rise again in the resurrection on the last day."  Jesus said to her, "I am the resurrection and the life. Whoever believes in me, though he die, yet shall he live, and everyone who lives and believes in me shall never die. Do you believe this?"

There is a resurrection, at the last day. Jesus' comfort to her is not that he is still alive, but in heaven, but that he will rise again. Even though Lazarus died, "yet shall he live". And, everyone who lives and believes in Jesus shall never die - the Bible tells us about God's and Jesus' understanding of that here:

Matthew 22:31-32: And as for the resurrection of the dead, have you not read what was said to you by God: 'I am the God of Abraham, and the God of Isaac, and the God of Jacob'? He is not God of the dead, but of the living."

By Jesus' words, we know that when God said that He is the God of Abraham, Isaac and Jacob, He was referring to the resurrection of the dead. So we understand God's power - he remembers them (Abraham, Isaac and Jacob), and will raise them up on the last day. The resurrection is a key Bible theme and worthy of study. If this all seems strange, perhaps Acts 17:30-32 will be reassuring. For further places to look, read of Abraham sacrificing Isaac in Genesis 22:1-18, taking note of verses 5 and 10 and comparing with Hebrews 11:17-19, and please read 1 Corinthians 15:12-19-23 - however the whole chapter is worth close study, especially about the resurrection. Also, a Bible search on "resurrection" will show many matches and will give a feel for the subject in the New Testament.

The Old Testament is not silent on this subject, indeed, it helps us understand the resurrection. One of the key areas are the promises to Abraham. For example:

Genesis 13:14-17: The LORD said to Abram, after Lot had separated from him, "Lift up your eyes and look from the place where you are, northward and southward and eastward and westward, for all the land that you see I will give to you and to your offspring forever.  I will make your offspring as the dust of the earth, so that if one can count the dust of the earth, your offspring also can be counted.  Arise, walk through the length and the breadth of the land, for I will give it to you."

So we see that God promises two things: eternal life for Abraham and his offspring, and a location to have eternal life in - he and his descendants will have the land forever. Indeed, not just the land of Israel, but ALL of the earth will be filled with the glory of the Lord (Numbers 14:21, Habakkuk 2:14). By the Habakkuk quote, it is people that fill the earth with God's glory. All of us, resurrected believers, in Christ, sinless, worshiping God and glorifying Him. I would not say that is the only place we will ever go once we are resurrected (it will not be a jail), but we will be immortal, and be given the land. Our Lord, Christ will reign over the world forever:

Revelation 11:15: Then the seventh angel blew his trumpet, and there were loud voices in heaven, saying, "The kingdom of the world has become the kingdom of our Lord and of his Christ, and he shall reign forever and ever."
2 Samuel 7:12-13: When your days are fulfilled and you lie down with your fathers, I will raise up your offspring after you, who shall come from your body, and I will establish his kingdom.  He shall build a house for my name, and I will establish the throne of his kingdom forever.
1 Chronicles 17:9-14: And I will appoint a place for my people Israel and will plant them, that they may dwell in their own place and be disturbed no more. And violent men shall waste them no more, as formerly, from the time that I appointed judges over my people Israel. And I will subdue all your enemies. Moreover, I declare to you that the LORD will build you a house.  When your days are fulfilled to walk with your fathers, I will raise up your offspring after you, one of your own sons, and I will establish his kingdom.  He shall build a house for me, and I will establish his throne forever.  I will be to him a father, and he shall be to me a son. I will not take my steadfast love from him, as I took it from him who was before you, but I will confirm him in my house and in my kingdom forever, and his throne shall be established forever.'"
Isaiah 9:7: Of the increase of his government and of peace there will be no end, on the throne of David and over his kingdom, to establish it and to uphold it with justice and with righteousness from this time forth and forevermore. The zeal of the LORD of hosts will do this.

What then of our soul? We have been promised a resurrection - why are we given a body to live immortally when resurrected, as it says in 1 Corinthians 15:35-55?

Romans 6:23: For the wages of sin is death, but the free gift of God is eternal life in Christ Jesus our Lord.

Here we see the two options put before us. God has given you and me the gift of eternal life - living forever. We will live forever, but sinners will not - they are not given the gift of eternal life, and, they will die. The two preceding verses emphasise the same point:

Romans 6:21-22: But what fruit were you getting at that time from the things of which you are now ashamed? For the end of those things is death.  But now that you have been set free from sin and have become slaves of God, the fruit you get leads to sanctification and its end, eternal life.

So why are the wages of sin death? It started in Eden:

Genesis 2:16-17: And the LORD God commanded the man, saying, "You may surely eat of every tree of the garden, but of the tree of the knowledge of good and evil you shall not eat, for in the day that you eat of it you shall surely die."

We know from the Bible record, that Adam and Eve did not die that exact day - so what does verse 17 mean? The Hebrew in verse 17 for "shall surely die" is "mooth mooth" - two H4191's. H4191 is Strong's number for it. Strong says:

A primitive root; to die (literally or figuratively); causatively to kill: -  X at all, X crying, (be) dead (body, man, one), (put to, worthy of) death, destroy (-er), (cause to, be like to, must) die, kill, necro [-mancer], X must needs, slay, X surely, X very suddenly, X in [no] wise.

The Hebrew word carries with it the meanings of death, kill, destroy, slay, suddenly, in no wise. So to "die die" emphasises that they would definitely die, be destroyed, surely and suddenly be no more. So in that day that they ate that fruit, Adam and Eve were destined to die and be no more.

Genesis 2:7: then the LORD God formed the man of dust from the ground and breathed into his nostrils the breath of life, and the man became a living creature.

We came from the dust, and had life breathed into us. We were formed by God.

Genesis 3:19: By the sweat of your face you shall eat bread, till you return to the ground, for out of it you were taken; for you are dust, and to dust you shall return."

We are dust, and to dust we return (see also Psalms 37:20; 49:12; 68:2). In a similar way, we, humans, are likened to grass that grows up, but perishes away quickly (Psalms 103:14-16; 37:2, Isaiah 40:6-8; 37:27, James 1:10, but also see Matthew 6:30). We were formed and given life by God, and He is who we should fear/respect and obey. Our souls, our lives are God's:

Ezekiel 18:4: Behold, all souls are mine; the soul of the father as well as the soul of the son is mine: the soul who sins shall die.
Ezekiel 18:20: The soul who sins shall die. The son shall not suffer for the iniquity of the father, nor the father suffer for the iniquity of the son. The righteousness of the righteous shall be upon himself, and the wickedness of the wicked shall be upon himself.

Indeed, God has no pleasure in a person's death (Ezekiel 18:23, Matthew 18:14) - even if they are wicked - God wishes us to obey Him and live. The soul will die - another way to look at it is given in Genesis 6:3, where it says God's Spirit will not abide in man forever:

Genesis 6:3: Then the LORD said, "My Spirit shall not abide in man forever, for he is flesh: his days shall be 120 years."

Without God we are nothing - he sustains everything by His power, so when someone dies, and God's Spirit leaves them. When we die, go to Sheol, return to dust, we will not think, or know, or do anything:

Ecclesiastes 9:10: Whatever your hand finds to do, do it with your might, for there is no work or thought or knowledge or wisdom in Sheol, to which you are going.

This is not an isolated quote; see also Psalms 112:9-10, Proverbs 10:28; 11:7. So, what is the result of all this? Even though we are weak and in many ways insignificant, we respect and love the God that loved us before we loved Him, and thank Him for His gift towards us of eternal life through His son, Jesus Christ, and obey Him - not from fear - but from respect and gratitude for all He has done for us.

For further reading, see Revelation 20:12-14, where we read of the book of life, and how the sea, death and hades/hell give up the dead in them, and they are judged. Why would hades/hell grouped with the sea, and death?

So I ask again, why did Martha say "I know that he will rise again in the resurrection on the last day.", and not something else?

Saturday, 19 January 2013

Random Scripts in Various Languages

In the last few weeks of work, I've come across several different languages to perform different tasks. They were useful, so I've included them below.


The first one is PowerShell. We used it to extract data for a customer. It's a temporary measure - their business intelligence server will be able to do this for them soon. The idea was to automate calling some SQL queries on a server and exporting the results as CSV. Of interest is that I set the culture to get a specific datetime format (I know, I could get the same effect in SQL). Here is some cleansed parts of the script:

$startDate = "11 Oct 2012"
$days = "1"

$prefix = "declare @StartDate datetime, @EndDate datetime
set @StartDate = DATEADD(HH, -10, '$startDate')
set @EndDate = DATEADD(DD, $days, @StartDate)"

$culture = [System.Globalization.CultureInfo]::InvariantCulture.Clone()
$culture.DateTimeFormat.ShortDatePattern = "yyyy-MM-dd"
$culture.DateTimeFormat.LongTimePattern = "HH:mm"
[System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture
[System.Threading.Thread]::CurrentThread.CurrentCulture = $culture

Write-Output "Extract $days day(s) worth of data from ${startDate}:"

Write-Host "Extracting Performance Log data..."
$query = "$prefix

select Column_Names etc."

$data = Custom-Call-SQL $query
Write-Host "Exporting CSV file..."
$data | Export-CSV PerformanceData.csv -encoding ascii -notype


To run a PowerShell script, put it in a file named something like "script.ps1", open a Powershell prompt (should be under Accessories in the Start menu), and enter the script file and path.


The next one was an unusual (to me) use for AutoHotkey. I say unusual, because I didn't think AutoHotkey would be great at working with large files, but it was. It combines the whole contents of several files from sub-folders "Day 2" to "Day 7" into one master file. The reason I went to AutoHotkey is that the files were too big for Notepad++. Here is the script:

#SingleInstance force
SendMode Input
SetWorkingDir %A_ScriptDir%

OutputFile = PerformanceData.csv
Loop, 6
  Day := A_Index+1
  From = Day %Day%\%OutputFile%
  CombineLines(From, OutputFile)
MsgBox, Finished copying content to %OutputFile%.

CombineLines(fromfile, tofile)

  ;; The "to" file is open for the whole loop for efficiency when done this way.  Loop, Read, %fromfile%, %tofile%
    FileAppend, %A_LoopReadLine%`n

To run an AutoHotkey script like this one, copy the contents into a file like "script.ahk" and double click it (assuming you have AutoHotkey installed).

Unix Find and Grep

The next one is from my friend Michael Gleeson. It's a Unix command, and it searches the files in a directory for the <string>, and prints the file and matching line to standard output. It is:

find . -type f -print0 | xargs -0 grep <string>

Regular Expressions

The second last one is for (Perl compatible) regular expressions. Notepad++ was updated to use Perl compatible regular expressions as of version 6. Notepad++ can use regular expressions for "Find and Replace". Doing so is a great feature - it gives you great flexibility to not only find bits of text that match specific patterns, but to also intelligently rearrange or replace those bits of text. I used it recently to change date formats in some of the files I generated with the above scripts. The find text was "(\d{2})/(\d{2})/(\d{4})", and the replace text was "\2-\1-\3". The parentheses in the find text create variables you can use in the replacement text. In our case, we have created three variables. They are named \1, \2 and \3. In the replace text, I've swapped the variables around, because I am converting American Month-Day-Year format to an Australian Day-Month-Year format.

Performing a find and replace in Notepad++ with the above terms replaces "02/27/1900" with "27-02-1900", etc.

See also a post on Mark's Speechblog for more on Notepad++'s powerful find and replace (pre version 6). Also, I'm told that a Unix command, sed (stream editor) can do similar things, and a lot more (see here for a great page about sed).

Visual Basic

The last one is from Visual Basic. I use this in an Excel file, to find a single file. It opens a standard file selector dialog. It's a function, so you call it when you want a file. The function returns a Boolean indicating whether a file was successfully selected, and it puts the file name into the ByRef argument. Here it is:

Function GetAFileName(ByRef FileName As String) As Boolean
' Actually browse for a file to import.
    Dim fd As FileDialog
    Set fd = Application.FileDialog(msoFileDialogOpen)
    fd.AllowMultiSelect = False
    GetAFileName = (fd.Show = -1)
    If GetAFileName Then
        FileName = fd.SelectedItems(1)
    End If
    Set fd = Nothing
End Function

Have you got any random scripts of your own? Please share them below.

Saturday, 12 January 2013

Ignoring Arguments in Anonymous Functions

Anonymous functions are a useful (hmm, that's an understatement) feature of Common Lisp. I use them a lot. While using them, sometimes I want to ignore some arguments that are required by the consumer of the anonymous function. For example, here is an example of collecting the keys in a hash-table into a list:
(let (result)
    (maphash (lambda (key value)
                (declare (ignore value))
                (push key result))


In this situation, the anonymous function is quite simple, and the ignore advice is swamping it. I wrote a small macro (named fn) to make ignoring arguments in anonymous functions easier. It's included and used extensively in the MathP code. To ignore an argument, use an underscore for it in the argument list. For example, the above code becomes:
(let (result)
    (maphash (fn (key _) (push key result))

Because the code is that much shorter, I find it that much easier to read. Here is the macro that does the magic:
(defmacro fn (args &body body)
    (let (arg-list ignores)
        (loop for arg in args
            if (string= (symbol-name arg) "_")
            do (let ((sym (gensym)))
(push sym arg-list) (push sym ignores))
            else do (push arg arg-list))
        `(lambda ,(nreverse arg-list) (declare (ignore ,@ignores)) ,@body)))

I hope the above code is useful to you; Use it however you want. I accept no responsibility for problems arising from it's use, but if you do find it useful, I'd be tickled pink to hear from you.

Do you know of a similar macro? Please leave a comment.

Saturday, 5 January 2013

Syntax for Lambda-Lift/Positional-Lambda

I've checked out the clever Lambda-Lift library by Hexstream, and I like it. It's a library that provides a succinct way to write positional lambdas. Having recently used implemented a reader macro, I decided to try one out for it. Almost immediately afterwards, I read the Reddit announcement, which mentioned that not using a reader macro was a good idea.

It seems that wanting to use reader macros for small things is a common weakness in Common Lisp programmers. Uses of dispatching macro character pairs to shorten code can actually make the code harder to read. This is more likely for people who don't know what the associated dispatch function does (or even sometimes where it came from). The tendency towards reader macros may arise from the desire for a more concise way to write Lisp code. This may be more of an issue if you are used to writing very terse code, such as Perl of Mathematica.

The issue with reader macros for general consumption is that they provide another layer to understand. While definitely not insurmountable, effort is still required to investigate and understand what the reader macro does or produces. In effect, reader macros use syntax to compress Lisp code.

The most Lispy way to compress code is probably to use higher order functions and macros. I think the benefit of using macros is that building macros upon macros is easier because of the uniform syntax. When macros are the right choice, you can benefit from their rich support in Common Lisp.

Anyway, here's my attempt. Use or leave it.

(defun read-positional-lambda-form (stream char n)
    (declare (ignore char))
    (let* ((next (peek-char nil stream))
           (n (or n (and (digit-char-p next)
                         (- (char-code (read-char stream))

                            #.(char-code #\0)))))
           (next (peek-char nil stream))
           (rest (and (char-equal next #\r) next))
           (next (progn (when rest (read-char stream))

                        (peek-char nil stream)))
           (body (if (member next '(#\Space #\Tab #\Newline nil #\)))
                    '() `(,(read stream nil nil t)))))
        `(lambda-lift:lift ,@(when n `(,(intern (format nil "~D" n) '#:keyword)))
               ,@(when rest `(&rest ,(read-from-string (string rest))))

(set-dispatch-macro-character #\# #\L #'read-positional-lambda-form)

The above code is released into the Public Domain the same as the Lambda-Lift library. Here are some examples of it:

'#L3           ;== (lift :3)
'#L3(print :2) ;== (lift :3 (print :2))
'#L2r          ;== (lift :2 &rest r)
'#L3r(print r) ;== (lift :3 &rest r (print r))
'#L3:2         ;== (lift :3 :2)
'#L2rr         ;== (lift :2 &rest r r)
(funcall #L5  
         'one 'two 'three 'four 'five) ;== FIVE
(funcall #L5:3          'one 'two 'three 'four 'five) ;== THREE
(funcall #L5(string :1) 'one 'two 'three 'four 'five) ;== "ONE"
(funcall #L5(reverse (string :4)) 'one 'two 'three 'four 'five) ;== "RUOF"
(funcall #L2rr 'one 'two 'three 'four 'five) ;== (THREE FOUR FIVE)