Saturday, February 2, 2013

The Anatomy of a Markov Algorithm: How my solution to Facebook Qualification Round Problem 2 works

Here is my Markov Algorithm solution to the second problem in the Facebook Qualification Round, broken up into sections. The first thing necessary is to run some preprocessing on the input to add a question mark to the end.

SECTION 1. Get rid of the rubbish.


:(->[
:)->]
:->
 ->
a->
b->
c->
d->
e->
f->
g->
h->
i->
j->
k->
l->
m->
n->
o->
p->
q->
r->
s->
t->
u->
v->
w->
x->
y->
z->
Here it takes a string such as "this is a colon (:) and this is three smileys (:):(:))?" and turns all smileys/potential parentheses into square brackets, and then removes all non-parentheses or brackets, giving "(](][[)?". The question is whether some of the square brackets can be turned into parentheses and the other brackets deleted so as to leave a balanced set of parentheses. 

SECTION 2. Duplicate

)?->}?)
]?->?)
(?->{?(
[?->{?
({->{(
){->{)
[{->{[
]{->{]
(}->}(
)}->})
[}->}[
]}->}]
?-><|

This is the clever bit. The first four rules make the question mark run backwards through the string, making two broken copies of the original string: to the right, you get the version if all closed square brackets are turned into closed parentheses and all open square brackets are deleted: in the case above you would be left with "()())". 

To the left, you get what would happen if you deleted all closed square brackets, and turned all open square brackets into open parentheses. To differentiate the left from the right, however, I make them curly brackets. (rules 5-9 here are just to make the curly brackets, destined for the left, pass through the other brackets/parentheses you haven't dealt with yet) So you would get "{{{{}" on the left. Note however, that you are generating these in reverse order, so you would actually end up with "}{{{{".

Finally you change the question mark into a vertical bar. So after going through this section of the algorithm, you end up with "}{{{{|()())".

{<-><)
}<-><(
<->

Now I change the curly brackets back to parentheses. Since they are in reverse order, I reverse the sign of the brackets. The less-than-signs are just to keep the curly brackets and parentheses separated until they are all converted - since section 2 teaches curly brackets and parentheses to go through. So now we are at "())))|()())".
So what have we done?

We have replaced our original bracket/parenthesis encoding of the string with two series of parentheses - one corresponding to turning all of the closed brackets to parentheses and deleting the open brackets, and the other corresponding to turning all of the open brackets to parentheses and deleting the closed brackets (and this second one we have reversed the string and inverted the brackets).

Now, suppose that we have some expression like "(](][[)" that can be made into a valid expression (let's call it VE) by rounding some of the square brackets and removing the others. If you round all of the closed square brackets and remove all of the open square brackets, the effect is the same as taking VE, removing some number (possibly 0) of open brackets and adding some number (possibly 0) of closed brackets. The effect will be to have the end of a valid sequence of parentheses.

Similarly, if we round all of the open square brackets and remove all of the closed square brackets, we must have the start of a valid sequence of parentheses.

It turns out that the converse is true:
A sequence of open/closed square brackets and parentheses can be turned into a valid sequence of brackets and parentheses by rounding some square brackets and removing the rest iff both of the following are true:
  • When you round all of the open square brackets and remove the closed ones you get the start of a valid sequence of parentheses
  • When you round all of the closed square brackets and remove the open ones you get the end of a valid sequence of parentheses.
Proof is left to the interested reader.
It follows that we want to respond YES, if both the left expression (which should be the start of a valid sequence of parentheses, inverted and reversed) and the right expression (which should be the end of a valid sequence of parentheses) are the ends of valid sequences of parentheses. Luckily it is easy to check if something is the end of a valid sequence of parentheses with 1 rule:

SECTION 3. Validate

()->

Given a sequence of open and closed parentheses, this rule turns all ends of valid sequences of parentheses into a number (possibly 0) of closed parentheses. All other sequences will still have an open parenthesis left. In our original string, we are at ")))|)"
)|->|
|)->|
So now we soak up all closed brackets adjacent to the vertical bar, leaving our original string at "|". If we had a valid expression, we are now at "|". Otherwise, there is an open bracket next to the vertical bar.

|(->NO
(|->NO
NO(->NO
NO)->NO
(NO->NO
)NO->NO
|->YES

This completes the test, turning all invalid sequences into NO and valid ones into YES.

Thursday, April 12, 2012

Optimizing Interpreter for Whenever

I have edited the original interpreter for the Whenever programming language (http://www.dangermouse.net/esoteric/whenever.html) so that it performs the following optimization:

* Temporarily remove all copies of a deferred statement from the to-do list until you do a non-deferred statement.

It results in quite a speed-up of many whenever programs. In particular, the Fibonacci program provided on the page linked above calculates all 50 Fibonacci numbers very quickly.

Two other changes made:
* read() is implemented
* replaced the subtraction operator '-' (which wasn't working) with '_'

The new version of Command.java is here and the new version of CodeTable.java is here.

Any suggestions that I have just done this in order to submit a solution to the Google Code Jam in the Whenever programming language seem very unlikely.

Saturday, May 7, 2011

Improved Markov Algorithm Executor

I have uploaded a new version of my markov algorithm simulator at http://www.ideone.com/VtaWx . It is somewhat faster, as it handles all rules simultaneously on each iteration.

More details later.

Saturday, July 24, 2010

Slightly Optimized C++ Program for running Markov Algorithms

I realise there is not much point giving you a 438-rule Markov Algorithm and telling you that it takes more than 6,000,000 iterations to do anything without some sort of execution engine.

Version 0.2 of my C++ Markov Algorithm Executor can be found after the jump. I apologise, my C++ is terrible.

brainfuck Overview

brainfuck is, perhaps, the most famous of esoteric programming languages.

I will give you a quick overview here of the syntax (such as there is) and instruction set of this language, after the jump.

Markov Algorithm Sudoku Solver

I thought that I should start off slowly, to give people an introduction to the general topic, to allow people to warm up to this blog and not put people off right from the start.

I quickly shelved this idea, and decided to instead show something hideously complicated.

Please find here my 458-rule Markov Algorithm for solving sudoku's. Given is an example input. The Algorithm solves this input in 6,525,264 iterations. Your mileage may vary.

Eventually in this blog, I will explain how this Markov Algorithm works. Note that it does not use any sophisticated Sudoku-solving techniques, but just trial and error.

I will give a full description of Markov Algorithms later, but for now you can see more details on the Sphere Online Judge.

Welcome to esotericode

This blog is about esoteric programing languages, including (but definitely not limited to):
* Brainfuck
* Whitespace
* FALSE
* Markov Algorithms
* FRACTRAN

It will include:
* Example programmes in esoteric languages
* Descriptions of how to go about writing code in esoteric languages
* Instructions of how to compile and/or execute esoteric languages.
* Sketches of proofs of Turing Completeness of esoteric languages

and much besides.

If you are not interested in esoteric programming languages, and do not feel you could become interested in them, then I have to be honest, this is probably not the blog for you.