Permalink
Browse files

Updated Turing, Fizzbuzz and README

  • Loading branch information...
1 parent 290de13 commit e926434eead4def930f99c7b1084a3274a20bac8 Daniel Holden committed Nov 16, 2012
Showing with 148 additions and 15 deletions.
  1. +1 −1 BRAINFUCK.h
  2. +1 −0 COMPLETE.h
  3. +13 −0 FIZZBUZZ.h
  4. +28 −0 INT.h
  5. +3 −0 MAIN_FZBZ.h
  6. +64 −8 README.md
  7. +36 −3 TEST.h
  8. +2 −3 TURING.h
View
@@ -128,7 +128,7 @@
#define BF_RECR($, X) JOIN(RECR_D, $)(INC($), BF_COND, BF_MACRO, BF_UPDATE, BF_FINALLY, X)
/*! Empty Data Array - Extend for more Cells */
-#define BF_DATA_EMPTY() (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
+#define BF_DATA_EMPTY() (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
/*! Perform Brainfuck on input I */
#define BRAINFUCK(I) BF_RECR($0, (0, 0, I, BF_DATA_EMPTY()))
View
@@ -13,6 +13,7 @@
#include "CHAR.h"
#include "LIST.h"
+#include "FIZZBUZZ.h"
#include "BRAINFUCK.h"
#include "TURING.h"
View
@@ -0,0 +1,13 @@
+#include "COMPLETE.h"
+
+/*! Thought it was time to hop on this band wagon */
+
+#define FIZZBUZZ_C($, X) LT($, X, 101)
+#define FIZZBUZZ_M($, X) IF_ELSE( NOT(BOOL(MOD($, X, 15))) , FizzBuzz \
+ , IF_ELSE( NOT(BOOL(MOD($, X, 3))) , Fizz \
+ , IF_ELSE( NOT(BOOL(MOD($, X, 5))) , Buzz \
+ , X \
+ )))
+#define FIZZBUZZ_U($, X) INC(X)
+#define FIZZBUZZ_E($, X)
+#define FIZZBUZZ() JOIN(RECR_D, 0)(1, FIZZBUZZ_C, FIZZBUZZ_M, FIZZBUZZ_U, FIZZBUZZ_E, 1)
View
@@ -24,6 +24,34 @@
#define SUB_E($, X) FST(X)
#define SUB($, X, Y) JOIN(RECR_D, $)(INC($), SUB_C, SUB_M, SUB_U, SUB_E, (X, Y))
+/*! Multiplication */
+#define MUL_C($, X) BOOL(SND(X))
+#define MUL_M($, X)
+#define MUL_U($, X) (FST(X), DEC(SND(X)), ADD($, FST(X), TRD(X)))
+#define MUL_E($, X) TRD(X)
+#define MUL($, X, Y) JOIN(RECR_D, $)(INC($), MUL_C, MUL_M, MUL_U, MUL_E, (X, Y, 0))
+
+/*! Division */
+#define DIV_C($, X) GE($, FST(X), SND(X))
+#define DIV_M($, X)
+#define DIV_U($, X) (SUB($, FST(X), SND(X)), SND(X), INC(TRD(X)))
+#define DIV_E($, X) TRD(X)
+#define DIV($, X, Y) JOIN(RECR_D, $)(INC($), DIV_C, DIV_M, DIV_U, DIV_E, (X, Y, 0))
+
+/*! Remainder */
+#define MOD_C($, X) GE($, FST(X), SND(X))
+#define MOD_M($, X)
+#define MOD_U($, X) (SUB($, FST(X), SND(X)), SND(X))
+#define MOD_E($, X) FST(X)
+#define MOD($, X, Y) JOIN(RECR_D, $)(INC($), MOD_C, MOD_M, MOD_U, MOD_E, (X, Y))
+
+/*! Power */
+#define POW_C($, X) BOOL(SND(X))
+#define POW_M($, X)
+#define POW_U($, X) (FST(X), DEC(SND(X)), MUL($, TRD(X), FST(X)))
+#define POW_E($, X) TRD(X)
+#define POW($, X, Y) JOIN(RECR_D, $)(INC($), POW_C, POW_M, POW_U, POW_E, (X, Y, 1))
+
/*! Ordering */
#define GT($, X, Y) BOOL(SUB($, X, Y))
#define LT($, X, Y) BOOL(SUB($, Y, X))
View
@@ -0,0 +1,3 @@
+#include "COMPLETE.h"
+
+FIZZBUZZ()
View
@@ -25,10 +25,12 @@ Then a program can be compiled as so:
* `cpp MAIN.h -D STDIN=(U,U,U,U,U,U,U,U,U,U,F,R,U,U,U,U,U,U,U,R,U,U,U,U,U,U,U,U,U,U,R,U,U,U,R,U,L,L,L,L,D,B,R,U,U,O,R,U,O,U,U,U,U,U,U,U,O,O,U,U,U,O,R,U,U,O,L,L,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,O,R,O,U,U,U,O,D,D,D,D,D,D,O,D,D,D,D,D,D,D,D,O,R,U,O)`
-Wait for about 30 seconds then the result should appear.
+Wait for about 15 seconds then the result should appear.
* `'H' 'e' 'l' 'l' 'o' ' ' 'W' 'o' 'r' 'l' 'd' '!'`
+Currently the maximum recursion depth is set to around `1000` and the data array size around `100`. These can be easily extended but for now, as a general rule of thumb computations exceeding `1000` steps may not run.
+
About
-----
@@ -108,9 +110,9 @@ There are two existing techniques to achieve recursion in the C Preprocessor. Th
...
```
-There are two problems with this approach. The first is that a number of functions must be created as deep as the stack. The second is that the `COND` or `UPDATE` functions must not contain in themselves any reference to the `REPEAT` macro. Even trivial loops such as `while(X != 10) { X += 2; }` cannot be expressed via the above method because `X += 2` requires addition and `X != 10` requires subtraction.
+There are two problems with this approach. The first is that a number of functions must be created as deep as the stack. The second is that the `COND` or `UPDATE` functions must not contain in themselves any reference to the `REPEAT` macro. Even trivial loops such as `while(X != 10) { X += 2; }` cannot be expressed via the above method because `X += 2` requires addition and `X != 10` requires subtraction - both of which may be defined in terms of `REPEAT`.
-Another method is explained by [pfultz](https://github.com/pfultz2/Cloak/wiki/Is-the-C-preprocessor-Turing-complete%3F) which removes several of these issues. I attempted his implementation but encountered several issues of my own. In general the semantics of this particular behavior of delayed evaluation were too complicated to get my head around and unify with the rest of my system.
+Another method is explained by [pfultz](https://github.com/pfultz2/Cloak/wiki/Is-the-C-preprocessor-Turing-complete%3F) which removes several of these issues. I attempted his implementation but encountered several issues of my own. In general the semantics of this particular behavior of delayed evaluation were too complicated to get my head around and unify with the rest of my system. It also exhibited the issues with conditionals explained above - but because there was no finite stack depth it tended toward infinite recursion.
In the end I implemented a combination of the two. The recursion depth `$` is explicitly passed in to allow for recursive functions to call other recursive functions, and a more general pattern is used to capture all kinds of recursive functions.
@@ -120,7 +122,7 @@ In the end I implemented a combination of the two. The recursion depth `$` is ex
// M - Side Effect
// U - Update Function
// E - Function Upon termination
-// X - value to act on
+// X - value to act upon
// Usage:
//
// #define RCOND($, X) BOOL(X)
@@ -133,7 +135,7 @@ In the end I implemented a combination of the two. The recursion depth `$` is ex
//
```
-The core recursive functions requires two macros to avoid some issues with `JOIN` and also to allow for "kicking" of looped recursion when the conditional fails. This is to stop the unwanted behavior of conditionals explained above.
+The core recursive function requires two macros to avoid some issues with `JOIN` and also to allow for "kicking" of looped recursion when the conditional fails. This is to stop the unwanted behavior of conditionals explained above.
```c
@@ -149,7 +151,9 @@ The core recursive functions requires two macros to avoid some issues with `JOIN
...
```
-While this still required enumeration two recursive macros the contents are the same, and it does provide general purpose reuse for many types of iteration. One issue with this recursion is that is only allows manipulation of a single data value `X`. To compute on more than one value then requires a data structure...
+While this still required enumeration to maximum stack depth, the contents of each expression are the same, and it does provide general purpose reuse for many types of iteration.
+
+But one final problem with this recursion is that is only allows manipulation of a single data value `X`. To compute on more than one value requires a data structure...
__Lists__
@@ -183,10 +187,62 @@ TAIL( (3, 1, 99, 12) )
CONS( 5, (1, 2, 3) )
```
-I then used the recursion primative to build many more useful list operations. Lists provided useful for all my data structures including arrays and state-tuples. From this point on programming the Brainfuck interpreter was fairly straight forward.
+I then used the recursion primative to build many more useful list operations. Lists provided useful for all my data structures including arrays and state-tuples.
+
+__Brainfuck__
+
+Finally I could put all of the above together to define a program which computed brainfuck. This is a recursion across a brainfuck state specified as `(Instrction Pointer, Data Pointer, Instruction Array, Data Array)`.
+
+Symbols are extracted using the `NTH` item of the instruction array. Then are then pattern matched using `JOIN` against macros which perform the correct behaviour for that instruction. The state is updated correctly and termination conditions are checked. A conditional side effect is performed if the ouput symbol is seen.
+
+More more information see the source code...
+
+
+Turing Machine
+==============
+
+I also have included code for a turing machine. Unfortunately the setup is a little more laborious as state transitions, starting state, and initial tape state must all be defined. This machine currently does not treat all edge cases and will terminate only when the head goes off the right side of the tape. All transitions must be defined. I will be making updates to improve these conditions soon.
+
+The initial starting state is defined using `Q` for example `-D Q=s0`
+The initial tape state is defined using `T`, for example `-D T=(0,0,1,1,0,1,0,0)`
+
+Transitions are defined using the form `-D T_A_R=(B,W,D)` where:
+
+* `A` - Current State
+* `B` - Next State
+* `R <- {0, 1}` - Binary Tape Read
+* `W <- {0, 1}` - Binary Tape Write
+* `D <- {l, R}` - Tape Head Direction
+
+For example `-D T_s0_0=(s1,1,R)`.
+
+It is important to ensure all valid transitions are defined and also important to ensuring there are no spaces in the tuple - otherwise it will not parse correctly on the command line.
+
+Putting this altogether we can define a machine which alternate writing `0` and `1` to the tape as follows:
+
+* `cpp MAIN_TM.h -D T=(0,0,1,0,1,1,0,0,1) -D Q=s0 -D T_s0_0=(s1,0,R) -D T_s0_1=(s1,0,R) -D T_s1_0=(s0,1,R) -D T_s1_1=(s0,1,R)`
+
+This should output:
+
+* `( (0, 1, 0, 1, 0, 1, 0, 1, 0), s1, 9 )`
+
+Which shows the final tape state, the final machine state and the final tape head position.
+
+
+FizzBuzz
+========
+
+I felt it was time to hop on that bandwagon. Perhaps the simplest example of use.
+
+To compile:
+
+* `cpp MAIN_FZBZ.h`
+
+Should output:
+* `1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz`
Library
--------
+=======
All code is avaliable under BSD3 and contributions toward the code as a library are welcome. I mainly built the functionality required for brainfuck but (clearly) many more things are possible and any missing peices are more than welcome.
View
@@ -28,6 +28,39 @@ ADD($0, 2, 3)
ADD($0, ADD($0, 2, 3), 2)
ADD($0, ADD($0, 2, 3), 2)
+MUL($0, 5, 2)
+MUL($0, 3, 4)
+MUL($0, 16, 3)
+MUL($0, 7, 8)
+
+DIV($0, 15, 5)
+DIV($0, 15, 4)
+DIV($0, 15, 3)
+DIV($0, 15, 2)
+DIV($0, 15, 1)
+
+MOD($0, 10, 1)
+MOD($0, 10, 2)
+MOD($0, 10, 3)
+MOD($0, 10, 4)
+MOD($0, 10, 5)
+MOD($0, 10, 6)
+MOD($0, 10, 7)
+MOD($0, 10, 8)
+MOD($0, 10, 9)
+MOD($0, 10, 10)
+
+POW($0, 2, 0)
+POW($0, 2, 1)
+POW($0, 2, 2)
+POW($0, 2, 3)
+POW($0, 2, 4)
+POW($0, 2, 5)
+POW($0, 2, 6)
+POW($0, 2, 7)
+POW($0, 2, 8)
+POW($0, 2, 9)
+
/* logic */
GT($0, 4, 3)
@@ -175,9 +208,9 @@ BRAINFUCK( () )
BRAINFUCK( (R,R,L) )
BRAINFUCK( (O,O,R,O) )
BRAINFUCK( (O,U,O,U,O) )
-BRAINFUCK( (U,U,U,U,U,U,U,U,U,U,F,R,U,U,U,U,U,U,U,U,U,L,D,B,R,O) )
-BRAINFUCK( (U,U,U,U,U,U,U,U,U,U,F,R,U,U,U,U,U,R,U,U,U,U,L,L,D,B,R,U,O,R,O) )
-BRAINFUCK( (U,U,U,U,U,U,U,U,U,U,F,R,U,U,U,U,U,U,U,R,U,U,U,U,U,U,U,U,U,U,R,U,U,U,R,U,L,L,L,L,D,B,R,U,U,O,R,U,O,U,U,U,U,U,U,U,O,O,U,U,U,O,R,U,U,O,L,L,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,O,R,O,U,U,U,O,D,D,D,D,D,D,O,D,D,D,D,D,D,D,D,O,R,U,O) )
+//BRAINFUCK( (U,U,U,U,U,U,U,U,U,U,F,R,U,U,U,U,U,U,U,U,U,L,D,B,R,O) )
+//BRAINFUCK( (U,U,U,U,U,U,U,U,U,U,F,R,U,U,U,U,U,R,U,U,U,U,L,L,D,B,R,U,O,R,O) )
+//BRAINFUCK( (U,U,U,U,U,U,U,U,U,U,F,R,U,U,U,U,U,U,U,R,U,U,U,U,U,U,U,U,U,U,R,U,U,U,R,U,L,L,L,L,D,B,R,U,U,O,R,U,O,U,U,U,U,U,U,U,O,O,U,U,U,O,R,U,U,O,L,L,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,O,R,O,U,U,U,O,D,D,D,D,D,D,O,D,D,D,D,D,D,D,D,O,R,U,O) )
/* Turing Machine */
View
@@ -61,9 +61,8 @@
#define TM_HEAD_U($, X) IF_ELSE( TM_IS_RIGHT(TRD(TM_TRANS($, X))) , INC(TM_H(X)) , DEC(TM_H(X)) )
#define TURING_RECR_C($, X) NOT(TM_IS_BLANK(TM_READ($, X)))
-#define TURING_RECR_M($, X) [TM_HEAD_U($, X)]
-//#define TURING_RECR_U($, X) ( TM_TAPE_U($, X), TM_STATE_U($, X), TM_HEAD_U($, X) )
-#define TURING_RECR_U($, X) ( TM_T(X), TM_Q(X), TM_HEAD_U($, X) )
+#define TURING_RECR_M($, X)
+#define TURING_RECR_U($, X) ( TM_TAPE_U($, X), TM_STATE_U($, X), TM_HEAD_U($, X) )
#define TURING_RECR_E($, X) X
#define TURING_RECR($, T, Q, H) JOIN(RECR_D, $)(INC($), TURING_RECR_C, TURING_RECR_M, TURING_RECR_U, TURING_RECR_E, (T, Q, H))

0 comments on commit e926434

Please sign in to comment.