// Universal Turing machine implementation, released under ISC/BSD license: // Copyright (c) 2009, Alex Stangl , John Tromp // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // This implementation, initially written on 01/02/2009 is an attempt to // write a shortest possible implementation of a Universal Turing machine, // which takes 5n command-line integer arguments consisting of // (input state, input symbol, output state, output symbol, direction) // see http://www.mathrix.org/experimentalAIT/TuringMachine.html for full // rules and other details. Compromises were made with coding style and // error handling, to shorten the source code. #include // GETARG returns argc'th cmdline arg converted to int, incrementing argc #define GETARG atoi(argv[argc++]) int main(int argc, char **argv) { // Init all variables; minPos is low water mark, calloc allocates // zero-filled tape array. int state=argc=1, step=0, tapeSize=2; char *oldTape, *newTape=0, *minPos, *tapePtr=0; // Crank FSM until terminal state reached while (state) { // allocate new zero-filled tape, copy old tape // over it, adjust pointers; leaves old tape allocated for now if (tapePtr <= newTape | tapePtr >= newTape+tapeSize) oldTape = newTape, newTape=(char*)calloc(tapeSize, 2), tapePtr = oldTape ? (memcpy(newTape+tapeSize/2, oldTape, tapeSize), tapePtr - oldTape + tapeSize/2 + newTape) : newTape + tapeSize, minPos = oldTape ? minPos - oldTape + tapeSize/2 + newTape : tapePtr, tapeSize *= 2; // Does this cmdline tuple rule match current (state, tape symbol)? argc = GETARG-state | GETARG-*tapePtr%2 // non-matching rule, advance to next rule ? argc + 3 // matching rule; update state, write symbol, move tape head, // update low water mark, increment step count, and reset argc : (state=GETARG, *tapePtr=GETARG|48, tapePtr+=GETARG, minPos -= tapePtr < minPos, ++step, 1); } // Output results: written tape contents, followed by # of steps processed printf("%s\n%d", minPos, step); // per Stroustrup, main needs no return stmt, in which case it returns 0 }