{"id":16627101,"url":"https://github.com/ttulka/turmin","last_synced_at":"2025-08-12T15:14:30.402Z","repository":{"id":253977639,"uuid":"844872783","full_name":"ttulka/turmin","owner":"ttulka","description":"Turmin esoteric programming language is neither a Turing machine nor a Minsky machine.","archived":false,"fork":false,"pushed_at":"2024-09-05T05:46:30.000Z","size":260,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-24T17:42:06.377Z","etag":null,"topics":["esolang","js","minsky","programming-language","turing-machine"],"latest_commit_sha":null,"homepage":"https://esolangs.org/wiki/Turmin","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ttulka.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-20T06:13:23.000Z","updated_at":"2024-09-05T05:43:53.000Z","dependencies_parsed_at":"2025-02-14T22:34:14.133Z","dependency_job_id":"cf68b751-237c-4828-bcb3-476e1483e3ba","html_url":"https://github.com/ttulka/turmin","commit_stats":null,"previous_names":["ttulka/turmin"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ttulka/turmin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fturmin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fturmin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fturmin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fturmin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ttulka","download_url":"https://codeload.github.com/ttulka/turmin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttulka%2Fturmin/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270083048,"owners_count":24523852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esolang","js","minsky","programming-language","turing-machine"],"created_at":"2024-10-12T04:13:22.563Z","updated_at":"2025-08-12T15:14:30.373Z","avatar_url":"https://github.com/ttulka.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Turmin\n\n\u003cimg src=\"logo-small.png\" style=\"width: 12%; float: right; margin: 1rem 0 1rem 2rem; border-radius: 1rem; max-width: 150px; float: right; z-index: 99\" align=\"right\" width=\"150\"\u003e\n\n**Turmin** is neither a Turing machine nor a Minsky machine. It is a language for programming Turing machines with a minimalistic yet convenient instruction set. The explicit state machine used traditionally in description numbers of Turing machines is conveniently replaced by conditional jumps borrowed from Minsky machines.\n\n## Memory model\n\nLike Turing machines, a Turmin program operates on an unbounded tape of cells, each holding a symbol from the program alphabet. The used charset depends on the implementation, but each interpreter must support at least ASCII starting from #20 (SPACE). \n\nThe character #20 is also the initial value of each cell, so an empty cell has the value #20. This is just a convenient shortcut, avoiding the introduction of any special characters (such as `ε`) or additional instructions like *clear* and *jump if empty*. An implementation can simply interpret an empty cell, either undefined or having an empty value, as a space.\n\n## Instructions\n\n| Instruction | Name  | Meaning |\n| ----------- | ----- | ------- |\n| `s`*S*      | SET   | Set symbol *S* to the current cell |\n| `r`         | RIGHT | Move to the cell on the right |\n| `l`         | LEFT  | Move to the cell left |\n| `j`*SN*     | JUMP  | If the current cell is *S*, jump to the *N*-th instruction |\n\nInstructions in a Turmin program are indexed from zero. Jumping to a nonexistent index will cause the program to halt.\n\nWhitespaces between instructions are permitted.\n\n## Extensions\n\nIn addition to the base four instructions, a Turmin interpreter may also implement the following extensions:\n\n### Debug\n\nThe directive `d` (DEBUG) will output useful debugging information.\n\nDEBUG should not be counted as an ordinary instruction, allowing it to be added to or removed from the source code without affecting the computation.\n\n### Labels\n\nA label is a directive that begins with a colon followed by zero `:0` and an arbitrary number. For instance, `:01` and `:099999` are valid labels.\n\nLabels without the colon can be used in JUMP instructions as the parameter *N*. For instance, `jx01` and `jx099999`.\n\n### Comments\n\nA code comment starts with `/` and ends with `\\` or a newline. \n\nCode comments can contain any arbitrary text; they are fully ignored by interpretation.\n\n## Examples\n\n### Empty program\n\nThe simplest program is an empty one:\n\n```turmin\n\n```\n\nIt does nothing.\n\n### Infinite loop\n\nThe simplest infinite loop can be created by repeatedly jumping to the same instruction:\n\n```turmin\nj 0\n```\n\n### Addition\n\nTurmin does not natively support numbers, so a concept must be developed. The simplest approach is to use unary numbers, represented by tally marks (`|` or any arbitrary symbol) separated by spaces, where the number of tally marks corresponds to the value.\n\nFor example, the following tape content represents the numbers 2 and 3:\n\n```\n|| |||\n```\n\nAdding unary numbers is straightforward—both expressions simply need to be concatenated:\n\n```turmin\nj 3 r j|0   / move to the next number\ns|          / replace a space with a tally mark\nr j|4       / to the end of the second number\nl s         / erase the last tally mark\n```\n\nThe result for the input 2 and 3 is as follows (5):\n\n```\n|||||\n```\n\n### Palindromes\n\nTurmin is a symbolic machine, making it well-suited for string manipulation.\n\nTo check if an input string of `x`s and `y`s is a palindrome (such as `xx` or `yyxyy`), the first character is “eaten” and compared to the last one. If a discrepancy is found, the tape is erased. If all characters are eaten without finding a difference, the program prints `1`:\n\n```turmin\nj 27\nl jx1 jy1         / to begininng\nr jx7 jy17        / check the rightmost symbol\n\n/ check x\ns\nr jx8jy8          //8\nl jy29 s l jx0jy0 //11\n\n/ check y\ns\nr jx18jy18        //18\nl jx29 s l jx0jy0 //21\n\n/ accept (print 1)\ns1 j130           //27\n\n/ erase tape\ns l jx29jy29      //29\n```\n\nComments `//n` label the instruction index, aiding in navigating jumps.\n\n### Fibonacci sequence\n\nThe idea is to use unary numbers and move them as the sequence prescribes, adding them accordingly.\n\nThe initial input consists of three arguments: the two starting elements of the sequence and the number of desired iterations.\n\nFor example, 3 iterations can be performed starting with 1 and 2:\n\n```\n | || |||\n```\n\nFirst, the program decrements the iteration counter. If the counter reaches zero, the program halts:\n\n```\n | || ||\n```\n\nNext, the second number is moved as the new first element by marking it digit by digit:\n\n```\n | | |+ ||\n|| | ++ ||\n```\n\nThe marks are then removed, and the two numbers are added together:\n\n```\n|| | +| ||\n|| | || ||\n|| ||| ||\n```\n\nThen, the next iteration begins.\n\n```turmin\n/ decrement iteration\nrj|0        //0\nrj|2        //2\nr j 999 l   / halt if no iterations left\nrj|7        //7\nl s         //9\n\n/ back to the left tape begin\nlj|11       //11\nlj|13       //13\nlj|15       //15\nr\n\n/ to the second number\n/ mark last digit\nrj|18       //18\nrj|20       //20\nls+         //22\n\n/ back to the left tape begin\n/ add a new digit to the begin\nlj|24       //24\nlj|26       //26\nlj 32       //28\nlj|30       //30\ns|          //32\n\n/ to the third number\nrj|33       //33\nrj|35       //35\nr j+43 l    / all digits marked\nrj|40       //40\nj+22        / repeat\n\n/ remove marks\ns|rj+43     //43\n\n/ add the 2nd and 3rd numbers\nsx l s \nlj|49       //49\ns|\n\n/ shift the iterations number\nrj|52       //52\nrs|\nrj|56       //56\nls\n\n/ to the left tape begin\nlj|60       //60\nlj|62       //62\nlj|64       //64\n\n/ new iteration\nr j|0\n```\n\n### Hello, World!\n\nThis legendary program is straightforward to implement in Turmin:\n\n```turmin\nsHrserslrslrsors,rs rsWrsorsrrslrsdrs!\n```\n\n## Computational class\n\nIt should be evident that Turmin is a Turing-complete language, as it has read-write access to unbounded memory and supports conditional jumps. We can easily show that Turmin can simulate both Turing and Minsky machines.\n\n### Turing machine\n\nA Turing machine performs computations based on state transitions. In Turmin, states can be simulated as snippets of code that the program jumps to based on a transition.\n\nConsider the following Turing machine with two states, S1 and S2, which rewrites `A`s to `X`s until it encounters a `B`:\n\n```\n  ┌─A/X/R──(S1)──B/B/L──\u003e(S2)\n  └─────────^   \n```\n\nTranslating this Turing machine into Turmin is a mechanical process:\n\n```turmin\n/ S1\njB3 sX r jA0\n/ S2\nl\n```\n\n### Minsky machine\n\nWe can simulate the registers of a Minsky machine using unary numbers separated by spaces or any other symbol.\n\nIncrementing a register involves adding a tally mark and shifting to the right, while decrementing involves removing a tally mark and shifting to the left.\n\nConditional jumps are natively supported in Turmin, and checking for zero is as simple as verifying whether any tally mark exists between separators.\n\n### Cyclic tag system\n\nIt is almost trivial to translate any cyclic tag system into Turmin. For example, the cyclic tag system with the productions (011, 10, 101) corresponds to the following Turmin program:\n\n```turmin\n/ 011\nj 51         / halt on empty\nj014         / next production\nrj02j12      / move rightmost \ns0rs1rs1     / append 011\nlj010j110r   / move leftmost\ns r d        / delete + debug\n\n/ 10\nj 51         / halt on empty\nj029         / next production\nrj019j119    / move rightmost \ns1rs0        / append 10\nlj025j125r   / move leftmost    \ns r d        / delete + debug\n\n/ 101\nj 51         / halt on empty\nj046         / next production\nrj034j134    / move rightmost \ns1rs0rs1     / append 101\nlj042j142r   / move leftmost\ns r d        / delete + debug\n\nj00j10       / repeat\n```\n\n## JavaScript interpreter\n\n```sh\nnpm i turmin\n```\n\n```js\nconst turmin = require('turmin')\n\nconst result = turmin(\n    'j 3rj|0s|rj|4ls ', \n    '|| |||'\n)\nresult // \"|||||\"\n```\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttulka%2Fturmin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fttulka%2Fturmin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttulka%2Fturmin/lists"}