Fractran - 1779 fractions
(Edit: fixed)
(I hope people still follow this topic because it took some time!)
It looks like SO won't let me post anything until this is, so I posted the Fractran source here .
The input is defined as follows:
First, we encode the fraction m/n = p_0^a0... p_k^ak :
- Start with 1. Then for each
ai : - Multiply by
p_2i^ai if ai > 0 - Multiply by
p_2i+1^{-ai} if a_i < 0
Thus, we encode any fraction as a positive integer. Now, given the program (sequence of encoded fractions F0, F1, ...), we encode that
p_0^F0 p1^F1 ...
Finally, input to the interpreter is specified:
2^(program) 3^(input) 5
where program and input encoded as above. For example, in the first test task 3/2 gets the encoding up to 15 , so the program gets the encoding up to 2^15 ; and 108 gets encoding up to 500 . So we go through
2^{2^15} 3^500 5
for the program. The output signal then has the form
2^(program) 3^(output)
so in the first example it will be
2^{2^15} 3^3125
How it works?
I wrote a metalanguage that compiles into Fractran. It allows you to use functions (simple Fractran and sequences of other functions) and a while and if while (for convenience!). The code for this can be found here .
If you want to compile this code to Fractran itself, my program (C ++) can be found here [tar.gz]. In a terrific dogfooding show (and showing off) I used my C ++ YAML yaml-cpp parser, so you will need to download and install a link with that. For iaml-cpp and the “compiler”, you will need CMake to generate a cross-platform makefile.
Using this program:
./fracc interpreter.frp
It reads the function name from standard input and writes the corresponding "pseudo-fraction" (I will explain that per second) to standard output. So, to compile the interpreter (Interpret function), you can run
echo "Interpret" | ./fracc interpreter.frp > interpret
The output ("pseudo-Fractran") will be a sequence of strings, each of which contains a string of numbers separated by spaces. The string corresponds to the fraction: if the nth character in the string an , then the fraction is the product of p_n^an .
It is very easy to convert this to Fractran, but if you are lazy, you can use to-fractions.py . [ Note : I used to have a C ++ program, and I casually ignored integer overflow. I translated it into Python to avoid this.]
Input note : if you want to test another function this way, the convention will always be the same. It has a number of parameters (as a rule, the comment above the function explains this) in the pseudo-fractal, so give it what it wants, plus 1 in the very next slot (so, in the usual Fractran, we multiply once by the first right one that it will not be used ) This is the “signal” bit to trigger the function.
However
I do not recommend actually trying to run the Fractran interpreter (alas). I tested many of its components and, for example, the IncrementPrimes function, which takes a pair of primes and returns the next two primes, takes about 8 minutes using my silly C ++ interpreter (no need to publish this :). Plus, it is (at least) quadratic in the number of function calls - doubling the number of function calls makes it take at least four times (more if there are while or if loops). Therefore, I assume that starting the interpreter will take at least several days, if not years: (
So how do I know this works? Well, of course, I'm not 100% sure, but I'm pretty close. First of all, I tested many, many of its components, and, in particular, very carefully tested all elements of the metalanguage (function sequences and if and while ).
In addition, the metalanguage is easy to translate into your favorite language and even easier to translate to C ++, since all function parameters are passed by reference. If you feel lazy again, you can download my translation here [tar.gz] (there is no makefile, these are just two .cpp files, so a direct call to gcc is fine).
So, you can compare the two interpreters, run the C ++ version (it also accepts I / O in pseudo-Fractran), check that this works, and then convince yourself that the metalanguage also works.
Or!
If you feel inspired and really want the interpreted interpreter to be interpreted, you can write a "smart" Fractran interpreter based on the type of Fractran output received. The output is very structured - function sequences are implemented using signals, so if you somehow cache where the interpreter was, you can jump right there if nothing important has changed. This, I think, will dramatically speed up the program (possibly, reduce the execution time by one or more privileges).
But I'm not quite sure how to do this, and I'm happy with what I did, so I will leave this as an exercise for the reader.