Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
132 lines (98 sloc) 3.87 KB
<?php
/*
Brainfuck interpreter in PHP
Copyright (C) 2002 Daniel Lorch
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/******************************************************
Some tools which I created and you might find useful
******************************************************/
/*
fuck_text() generates brainfuck code from $text. The resulting code will use the current
register p for looping and the register p+1 for the resulting character. Thus, make sure
these two registers are zero (prepend "[-]>[-]<<" to clear the first two registers).
I suggest you to use this function in conjunction with wordwrap:
$bf = wordwrap(fuck_text("Hello World"), 75, "\n", 1));
wich will generate nice, formatted output.
*/
function fuck_text($text) {
/* value of current pointer */
$value = 0;
for($_t = 0; $_t < strlen($text); ++$_t) {
/* ordinal difference between current char and the one we want to have */
$diff = ord($text[$_t]) - $value;
/* it's easier like this than always computing this value - saves some cpu cycles*/
$value = ord($text[$_t]);
/* repeat current character */
if($diff == 0) {
$result .= ">.<";
continue;
}
/* is it worth making a loop?
No. A bunch of + or - consume less space than the loop. */
if(abs($diff) < 10) {
/* output a bunch of + or - */
if($diff > 0)
$result .= ">" . str_repeat("+", $diff);
else if($diff < 0)
$result .= ">" . str_repeat("-", abs($diff));
}
/* Yes, create a loop. This will make the resulting code more compact. */
else {
/* we strictly use ints, as PHP has some bugs with floating point operations
(even if no division is involved) */
$loop = (int)sqrt(abs($diff));
/* set loop counter */
$result .= str_repeat("+", $loop);
/* execute loop, then add reminder */
if($diff > 0) {
$result .= "[->" . str_repeat("+", $loop) . "<]";
$result .= ">" . str_repeat("+", $diff - pow($loop, 2));
}
else if($diff < 0) {
$result .= "[->" . str_repeat("-", $loop) . "<]";
$result .= ">" . str_repeat("-", abs($diff) - pow($loop, 2));
}
} /* end: if loop */
$result .= ".<";
} /* end: for */
/* cleanup */
return str_replace("<>", "", $result);
}
/*
This function checks whether the brackets are balanced. Make sure you get the
return value correctly, as 0 means "OK" and not "false":
positive return value : this many [ too much = this many ] missing
zero : balanced
negatice return value : this many ] too much = this many [ missing
*/
function bf_brackets_balance($bf) {
$histogram = count_chars($bf);
return $histogram[91] - $histogram[93];
}
/*
This returns the real number of brainfuck commands when all other characters
are ignored.
*/
function bf_count_chars($bf) {
return count(preg_split("/[\[\]+\-<>.,]/", $bf)) - 1;
}
/*
bf_reduce() removes all unnecessary characters from a brainfuck source, only
leaving actual instructions left.
*/
function bf_reduce($bf) {
preg_match_all("/[\[\]+\-<>.,]/", $bf, $matches);
return join("", $matches[0]);
}
?>