Re: Solution to QOTW #23 in language of QOTW #24

Mark Jason Dominus <[email protected]> Tue, 21 Sep 2004 13:51:22 -0400
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <[email protected]>
Daniel Martin <martin-+m399P62/[email protected]>:
> As a demonstration that turing machines can indeed do all the things
> more convenient computer systems can, I attach a solution to the
> "parens" problem of a few weeks ago in the turing machine language
> of QOTW #24.

I was kind of hoping someone would post an interpreter.  But maybe
that's too insane.

> Unfortunately, the restriction on the output format means that it
> can't quite output like QOTW #23 specified.  However, doing this
> should get you the right output (assuming that your turing machine
> interpreter is called tm.pl, and that you have a "tr" program that
> understands backslashed escapes):

I changed the definition of my interpreter so that (, ), [, and ] are
valid tape symbols, and also that a r/w head motion of the form "x!"
means that the interpreter should print the tape contents just before
moving the head.  If you don't like that, it should be easy to alter
the TM instructions so that section D copies the new parenthesis
string while scanning it.

This is a fairly straightforward translation of my
parenthesis-generating program.  It is substantially simpler than
Daniel Martin's, although not so featureful; I think it has fewer
states and fewer total instructions, even if you don't count the
argument-processing and copying parts of Martin's code.

The input should be a string of the form '()()()()()'.  If you don't
like that, it should be easy to paste in the chunk of Martin's code
that transforms a decimal numeral into a string of that form.

The execution of 

        perl tm.pl parens.pl '()()()()'

generates:

        ()()()()
        ()()(())
        ()(())()
        ()(()())
        ()((()))
        (())()()
        (())(())
        (()())()
        (()()())
        (()(()))
        ((()))()
        ((())())
        ((()()))
        (((())))

which I believe is correct, and also in lexicographic order.


# Initialization: Scan to the right-hand end
init ( init ( R
init ) init ) R
init _ A_scan_1 _ L!            # Print the tape contents at this point

# Section A
# Locate innermost changeable pair )( and replace with []
# If there isn't one, then we have ((((())))), so halt.

A_scan_1 ) A_scan_1 ) L
A_scan_1 ( A_scan_2 ( L

A_scan_2 ( A_scan_2 ( L
A_scan_2 ) A_change [ R
A_scan_2 _ HALT     _ R         # HALT instruction

A_change ( B_scan_L ] L

# Section B
# Mark outer pairs that surround inner pair

B_scan_L [ B_scan_L [ L
B_scan_L ] B_scan_L ] L
B_scan_L ) B_scan_L ) L
B_scan_L ( B_scan_R [ R
B_scan_L _ C_scan_R _ R

B_scan_R [ B_scan_R [ R
B_scan_R ] B_scan_R ] R
B_scan_R ) B_scan_L ] L
B_scan_R ( B_scan_L ] L  # Note that this changes ( to ]

# Section C
# Reset rightmost marks
# In the 'counting' analogy, this is like resetting the 999 part of
# 345999 to 000.

C_scan_R [ C_scan_R [ R
C_scan_R ] C_scan_R ] R
C_scan_R ( C_close [ R
C_scan_R ) C_close [ R
C_scan_R _ D_fix _ L

C_close ( C_open ] R
C_close ) C_open ] R

C_open ( C_close [ R
C_open ) C_close [ R
C_open _ D_fix _ L

# Section D
# Replace [] with () and start over

D_fix ( D_fix ( L
D_fix ) D_fix ) L
D_fix [ D_fix ( L
D_fix ] D_fix ) L
D_fix _ init _ R